3
# Tweening functions for python
5
# Heavily based on caurina Tweener: http://code.google.com/p/tweener/
7
# Released under M.I.T License - see above url
8
# Python version by Ben Harling 2009
12
def __init__(self, duration = 0.5, tween = None):
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.Cubic.easeInOut
18
self.defaultDuration = duration or 1.0
21
return len(self.currentTweens) > 0
24
def addTween(self, obj, **kwargs):
25
""" addTween( object, **kwargs) -> tweenObject or False
28
tweener.addTween( myRocket, throttle=50, setThrust=400, tweenTime=5.0, tweenType=tweener.OUT_QUAD )
30
You must first specify an object, and at least one property or function with a corresponding
31
change value. The tween will throw an error if you specify an attribute the object does
32
not possess. Also the data types of the change and the initial value of the tweened item
33
must match. If you specify a 'set' -type function, the tweener will attempt to get the
34
starting value by call the corresponding 'get' function on the object. If you specify a
35
property, the tweener will read the current state as the starting value. You add both
36
functions and property changes to the same tween.
38
in addition to any properties you specify on the object, these keywords do additional
41
tweenTime = the duration of the motion
42
tweenType = one of the predefined tweening equations or your own function
43
onCompleteFunction = specify a function to call on completion of the tween
44
onUpdateFunction = specify a function to call every time the tween updates
45
tweenDelay = specify a delay before starting.
47
if "tweenTime" in kwargs:
48
t_time = kwargs.pop("tweenTime")
49
else: t_time = self.defaultDuration
51
if "tweenType" in kwargs:
52
t_type = kwargs.pop("tweenType")
53
else: t_type = self.defaultTweenType
55
if "onCompleteFunction" in kwargs:
56
t_completeFunc = kwargs.pop("onCompleteFunction")
57
else: t_completeFunc = None
59
if "onUpdateFunction" in kwargs:
60
t_updateFunc = kwargs.pop("onUpdateFunction")
61
else: t_updateFunc = None
63
if "tweenDelay" in kwargs:
64
t_delay = kwargs.pop("tweenDelay")
67
tw = Tween( obj, t_time, t_type, t_completeFunc, t_updateFunc, t_delay, **kwargs )
69
self.currentTweens.append( tw )
72
def removeTween(self, tweenObj):
73
if tweenObj in self.currentTweens:
74
tweenObj.complete = True
75
#self.currentTweens.remove( tweenObj )
77
def getTweensAffectingObject(self, obj):
78
"""Get a list of all tweens acting on the specified object
79
Useful for manipulating tweens on the fly"""
81
for t in self.currentTweens:
86
def removeTweeningFrom(self, obj):
87
"""Stop tweening an object, without completing the motion
88
or firing the completeFunction"""
89
for t in self.currentTweens:
94
#go to last frame for all tweens
95
for t in self.currentTweens:
97
self.currentTweens = []
99
def update(self, timeSinceLastFrame):
101
for t in self.currentTweens:
102
t.update(timeSinceLastFrame)
108
self.currentTweens.remove(t)
112
def __init__(self, obj, tduration, tweenType, completeFunction, updateFunction, delay, **kwargs):
114
Can be created directly, but much more easily using Tweener.addTween( ... )
116
#print obj, tduration, kwargs
117
self.duration = tduration
120
self.tween = tweenType
121
self.tweenables = kwargs
123
self.completeFunction = completeFunction
124
self.updateFunction = updateFunction
125
self.complete = False
128
self.paused = self.delay > 0
129
self.decodeArguments()
131
def decodeArguments(self):
132
"""Internal setup procedure to create tweenables and work out
133
how to deal with each"""
135
if len(self.tweenables) == 0:
137
print "TWEEN ERROR: No Tweenable properties or functions defined"
141
for k, v in self.tweenables.items():
143
# check that its compatible
144
if not hasattr( self.target, k):
145
print "TWEEN ERROR: " + str(self.target) + " has no function " + k
154
startVal = self.target.__dict__[k]
159
func = getattr( self.target, k)
164
getFunc = getattr(self.target, funcName.replace("set", "get") )
167
# no start value, assume its 0
168
# but make sure the start and change
170
startVal = newVal * 0
171
tweenable = Tweenable( startVal, newVal - startVal)
172
newFunc = [ k, func, tweenable]
174
#setattr(self, funcName, newFunc[2])
175
self.tFuncs.append( newFunc )
179
tweenable = Tweenable( startVal, newVal - startVal)
180
newProp = [ k, prop, tweenable]
181
self.tProps.append( newProp )
184
def pause( self, numSeconds=-1 ):
186
do tween.pause( 2 ) to pause for a specific time
187
or tween.pause() which pauses indefinitely."""
189
self.delay = numSeconds
192
"""Resume from pause"""
196
def update(self, ptime):
197
"""Update this tween with the time since the last frame
198
if there is an update function, it is always called
199
whether the tween is running or paused"""
206
self.delay = max( 0, self.delay - ptime )
210
if self.updateFunction:
211
self.updateFunction()
214
self.delta = min(self.delta + ptime, self.duration)
217
for propName, prop, tweenable in self.tProps:
218
self.target.__dict__[prop] = self.tween( self.delta, tweenable.startValue, tweenable.change, self.duration )
219
for funcName, func, tweenable in self.tFuncs:
220
func( self.tween( self.delta, tweenable.startValue, tweenable.change, self.duration ) )
223
if self.delta == self.duration:
225
if self.completeFunction:
226
self.completeFunction()
228
if self.updateFunction:
229
self.updateFunction()
233
def getTweenable(self, name):
234
"""Return the tweenable values corresponding to the name of the original
235
tweening function or property.
237
Allows the parameters of tweens to be changed at runtime. The parameters
238
can even be tweened themselves!
242
# the rocket needs to escape!! - we're already moving, but must go faster!
243
twn = tweener.getTweensAffectingObject( myRocket )[0]
244
tweenable = twn.getTweenable( "thrusterPower" )
245
tweener.addTween( tweenable, change=1000.0, tweenTime=0.4, tweenType=tweener.IN_QUAD )
249
for n, f, t in self.tFuncs:
253
for n, p, t in self.tProps:
260
"""Disables and removes this tween
261
without calling the complete function"""
266
def __init__(self, start, change):
268
Holds values for anything that can be tweened
269
these are normally only created by Tweens"""
270
self.startValue = start
274
"""Robert Penner's easing classes ported over from actionscript by Toms Baugis (at gmail com).
275
There certainly is room for improvement, but wanted to keep the readability to some extent.
277
================================================================================
279
(c) 2003 Robert Penner, all rights reserved.
280
This work is subject to the terms in
281
http://www.robertpenner.com/easing_terms_of_use.html.
282
================================================================================
284
TERMS OF USE - EASING EQUATIONS
286
Open source under the BSD License.
290
Redistribution and use in source and binary forms, with or without modification,
291
are permitted provided that the following conditions are met:
293
* Redistributions of source code must retain the above copyright notice,
294
this list of conditions and the following disclaimer.
295
* Redistributions in binary form must reproduce the above copyright notice,
296
this list of conditions and the following disclaimer in the documentation
297
and/or other materials provided with the distribution.
298
* Neither the name of the author nor the names of contributors may be used
299
to endorse or promote products derived from this software without specific
300
prior written permission.
302
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
303
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
304
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
305
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
306
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
307
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
308
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
309
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
310
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
311
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
316
def easeIn(t, b, c, d, s = 1.70158):
318
return c * t**2 * ((s+1) * t - s) + b
321
def easeOut (t, b, c, d, s = 1.70158):
323
return c * (t**2 * ((s + 1) * t + s) + 1) + b
326
def easeInOut (t, b, c, d, s = 1.70158):
331
return c * 0.5 * (t**2 * ((s + 1) * t - s)) + b
334
return c / 2 * (t**2 * ((s + 1) * t + s) + 2) + b
338
def easeOut (t, b, c, d):
341
return c * (7.5625 * t**2) + b
344
return c * (7.5625 * t**2 + 0.75) + b
347
return c * (7.5625 * t**2 + .9375) + b
350
return c * (7.5625 * t**2 + 0.984375) + b
353
def easeIn (t, b, c, d):
354
return c - Easing.Bounce.easeOut(d-t, 0, c, d) + b
357
def easeInOut (t, b, c, d):
359
return Easing.Bounce.easeIn (t * 2, 0, c, d) * .5 + b
361
return Easing.Bounce.easeOut (t * 2 -d, 0, c, d) * .5 + c*.5 + b
367
def easeIn (t, b, c, d):
369
return -c * (math.sqrt(1 - t**2) - 1) + b
372
def easeOut (t, b, c, d):
374
return c * math.sqrt(1 - t**2) + b
377
def easeInOut (t, b, c, d):
380
return -c * 0.5 * (math.sqrt(1 - t**2) - 1) + b
383
return c*0.5 * (math.sqrt(1 - t**2) + 1) + b
388
def easeIn (t, b, c, d):
393
def easeOut (t, b, c, d):
395
return c * (t**3 + 1) + b
398
def easeInOut (t, b, c, d):
401
return c * 0.5 * t**3 + b
404
return c * 0.5 * (t**3 + 2) + b
409
def easeIn (t, b, c, d, a = 0, p = 0):
413
if t == 1: return b+c
415
if not p: p = d * .3;
417
if not a or a < abs(c):
421
s = p / (2 * math.pi) * math.asin(c / a)
424
return - (a * math.pow(2, 10 * t) * math.sin((t*d-s) * (2 * math.pi) / p)) + b
428
def easeOut (t, b, c, d, a = 0, p = 0):
432
if (t == 1): return b + c
434
if not p: p = d * .3;
436
if not a or a < abs(c):
440
s = p / (2 * math.pi) * math.asin(c / a)
442
return a * math.pow(2,-10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) + c + b
446
def easeInOut (t, b, c, d, a = 0, p = 0):
450
if t == 2: return b + c
452
if not p: p = d * (.3 * 1.5)
454
if not a or a < abs(c):
458
s = p / (2 * math.pi) * math.asin(c / a)
462
return -.5 * (a * math.pow(2, 10 * t) * math.sin((t * d - s) * (2 * math.pi) / p)) + b
465
return a * math.pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) * .5 + c + b
470
def easeIn(t, b, c, d):
474
return c * math.pow(2, 10 * (t / d - 1)) + b - c * 0.001
477
def easeOut(t, b, c, d):
481
return c * (-math.pow(2, -10 * t / d) + 1) + b
484
def easeInOut(t, b, c, d):
493
return c * 0.5 * math.pow(2, 10 * (t - 1)) + b
495
return c * 0.5 * (-math.pow(2, -10 * (t - 1)) + 2) + b
500
def easeNone(t, b, c, d):
504
def easeIn(t, b, c, d):
508
def easeOut(t, b, c, d):
512
def easeInOut(t, b, c, d):
518
def easeIn (t, b, c, d):
523
def easeOut (t, b, c, d):
525
return -c * t * (t-2) + b
528
def easeInOut (t, b, c, d):
531
return c * 0.5 * t**2 + b
534
return -c * 0.5 * (t * (t - 2) - 1) + b
539
def easeIn (t, b, c, d):
544
def easeOut (t, b, c, d):
546
return -c * (t**4 - 1) + b
549
def easeInOut (t, b, c, d):
552
return c * 0.5 * t**4 + b
555
return -c * 0.5 * (t**4 - 2) + b
560
def easeIn (t, b, c, d):
565
def easeOut (t, b, c, d):
567
return c * (t**5 + 1) + b
570
def easeInOut (t, b, c, d):
573
return c * 0.5 * t**5 + b
576
return c * 0.5 * (t**5 + 2) + b
580
def easeIn (t, b, c, d):
581
return -c * math.cos(t / d * (math.pi / 2)) + c + b
584
def easeOut (t, b, c, d):
585
return c * math.sin(t / d * (math.pi / 2)) + b
588
def easeInOut (t, b, c, d):
589
return -c * 0.5 * (math.cos(math.pi * t / d) - 1) + b
594
def easeIn(t, b, c, d):
595
return c * (t/d)**5 + b
598
def easeOut(t, b, c, d):
599
return c * ((t / d - 1)**5 + 1) + b
602
def easeInOut(t, b, c, d):
606
return c * 0.5 * t**5 + b
609
return c * 0.5 * (t**5 + 2) + b
613
class TweenTestObject:
619
print self.pos, self.rot
621
def setRotation(self, rot):
624
def getRotation(self):
628
print "I'm done tweening now mommy!"
631
if __name__=="__main__":
634
tst = TweenTestObject()
635
mt = T.addTween( tst, setRotation=500.0, tweenTime=2.5, tweenType=T.OUT_EXPO,
636
pos=-200, tweenDelay=0.4, onCompleteFunction=tst.complete,
637
onUpdateFunction=tst.update )
645
if mt.delta > 1.0 and not changed:
647
tweenable = mt.getTweenable( "setRotation" )
649
T.addTween( tweenable, change=-1000, tweenTime=0.7 )
650
T.addTween( mt, duration=-0.2, tweenTime=0.2 )
653
print tst.getRotation(), tst.pos
655
print tst.getRotation(), tst.pos