[hamster-applet] will be using Robert Penner's functions instead of housebrewn wonders
- From: Toms Baugis <tbaugis src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [hamster-applet] will be using Robert Penner's functions instead of housebrewn wonders
- Date: Sat, 14 Nov 2009 21:36:44 +0000 (UTC)
commit 05fdf066c1f23e9cbe6c29124ded65ac9cdedf8e
Author: Toms Bauģis <toms baugis gmail com>
Date: Sat Nov 14 19:41:44 2009 +0000
will be using Robert Penner's functions instead of housebrewn wonders
hamster/pytweener.py | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 436 insertions(+), 0 deletions(-)
---
diff --git a/hamster/pytweener.py b/hamster/pytweener.py
new file mode 100644
index 0000000..6b5b49a
--- /dev/null
+++ b/hamster/pytweener.py
@@ -0,0 +1,436 @@
+# pyTweener
+#
+# Tweening functions for python
+#
+# Heavily based on caurina Tweener: http://code.google.com/p/tweener/
+#
+# Released under M.I.T License - see above url
+# Python version by Ben Harling 2009
+import math
+
+class Easing:
+ class Back:
+ @staticmethod
+ def easeIn(t, b, c, d, s = 1.70158):
+ t= t/d
+ return c * (t) * t * ((s+1) * t - s) + b
+
+ @staticmethod
+ def easeOut (t, b, c, d, s = 1.70158):
+ t = t/d-1
+ return c*((t)*t*((s+1)*t + s) + 1) + b;
+
+ @staticmethod
+ def easeInOut (t, b, c, d, s = 1.70158):
+ t = t / d*0.5
+ s = s * 1.525
+
+ if ((t) < 1):
+ return c*0.5*(t*t*(((s)+1)*t - s)) + b
+
+ t = t - 2
+ return c / 2 * ((t) * t * (((s)+1) * t + s) + 2) + b
+
+ class Bounce:
+ @staticmethod
+ def easeOut (t, b, c, d):
+ t = t / d
+ if t < 1 / 2.75:
+ return c * (7.5625 * t * t) + b
+
+ elif t < 2 / 2.75:
+ t = t - 1.5 / 2.75
+ return c * (7.5625 * (t)*t + 0.75) + b
+
+ elif t < 2.5 / 2.75:
+ t = t - 2.25/2.75
+ return c * (7.5625 * (t)*t + .9375) + b
+ else:
+ t = t - 2.625 / 2.75
+ return c*(7.5625*(t)*t + 0.984375) + b
+
+ @staticmethod
+ def easeIn (t, b, c, d):
+ return c - Easing.Bounce.easeOut(d-t, 0, c, d) + b
+
+ @staticmethod
+ def easeInOut (t, b, c, d):
+ if t < d * 0.5:
+ return Easing.Bounce.easeIn (t*2, 0, c, d) * .5 + b
+ else:
+ return Easing.Bounce.easeOut (t*2-d, 0, c, d) * .5 + c*.5 + b
+
+
+def OUT_EXPO(t, b, c, d ):
+ return b+c if (t==d) else c * (-2**(-10 * t/d) + 1) + b;
+
+def LINEAR(t, b, c, d):
+ return c*t/d + b
+
+def IN_QUAD(t, b, c, d):
+ t/=d
+ return c*(t)*t + b
+
+def OUT_QUAD(t, b, c, d):
+ t/=d
+ return -c *(t)*(t-2) + b
+
+def IN_OUT_QUAD(t, b, c, d ):
+ t/=d/2
+ if ((t) < 1): return c/2*t*t + b
+ t-=1
+ return -c/2 * ((t)*(t-2) - 1) + b
+
+def OUT_IN_QUAD(t, b, c, d ):
+ if (t < d/2):
+ return self.OUT_QUAD (t*2, b, c/2, d)
+ return self.IN_QUAD((t*2)-d, b+c/2, c/2)
+
+def IN_CUBIC(t, b, c, d):
+ t/=d
+ return c*(t)*t*t + b
+
+def OUT_CUBIC(t, b, c, d):
+ t=t/d-1
+ return c*((t)*t*t + 1) + b
+
+def IN_OUT_CUBIC(t, b, c, d):
+ t/=d/2
+ if ((t) < 1):
+ return c/2*t*t*t + b
+ t-=2
+ return c/2*((t)*t*t + 2) + b
+
+def OUT_IN_CUBIC(t, b, c, d ):
+ if (t < d/2): return self.OUT_CUBIC (t*2, b, c/2, d)
+ return self.IN_CUBIC((t*2)-d, b+c/2, c/2, d)
+
+def IN_QUART(t, b, c, d):
+ t/=d
+ return c*(t)*t*t*t + b
+
+def OUT_QUART(t, b, c, d):
+ t=t/d-1
+ return -c * ((t)*t*t*t - 1) + b
+
+def IN_OUT_QUART(t, b, c, d):
+ t/=d/2
+ if (t < 1):
+ return c/2*t*t*t*t + b
+ t-=2
+ return -c/2 * ((t)*t*t*t - 2) + b
+
+def OUT_ELASTIC(t, b, c, d): # Not working :(
+ if (t==0):
+ return b
+ t/=d
+ if t==1:
+ return b+c
+ p = period = d*.3
+ a = amplitude = 1.0
+ if a < abs(c):
+ a = c
+ s = p/4
+ else:
+ s = p/(2*math.pi) * math.asin (c/a)
+
+ return (a*math.pow(2,-10*t) * math.sin( (t*d-s)*(2*math.PI)/p ) + c + b)
+
+class Tweener:
+ def __init__(self, duration = None, tween = None):
+ """Tweener
+ This class manages all active tweens, and provides a factory for
+ creating and spawning tween motions."""
+ self.currentTweens = []
+ self.defaultTweenType = tween or IN_OUT_QUAD
+ self.defaultDuration = duration or 1.0
+
+ def hasTweens(self):
+ return len(self.currentTweens) > 0
+
+
+ def addTween(self, obj, **kwargs):
+ """ addTween( object, **kwargs) -> tweenObject or False
+
+ Example:
+ tweener.addTween( myRocket, throttle=50, setThrust=400, tweenTime=5.0, tweenType=tweener.OUT_QUAD )
+
+ You must first specify an object, and at least one property or function with a corresponding
+ change value. The tween will throw an error if you specify an attribute the object does
+ not possess. Also the data types of the change and the initial value of the tweened item
+ must match. If you specify a 'set' -type function, the tweener will attempt to get the
+ starting value by call the corresponding 'get' function on the object. If you specify a
+ property, the tweener will read the current state as the starting value. You add both
+ functions and property changes to the same tween.
+
+ in addition to any properties you specify on the object, these keywords do additional
+ setup of the tween.
+
+ tweenTime = the duration of the motion
+ tweenType = one of the predefined tweening equations or your own function
+ onCompleteFunction = specify a function to call on completion of the tween
+ onUpdateFunction = specify a function to call every time the tween updates
+ tweenDelay = specify a delay before starting.
+ """
+ if "tweenTime" in kwargs:
+ t_time = kwargs.pop("tweenTime")
+ else: t_time = self.defaultDuration
+
+ if "tweenType" in kwargs:
+ t_type = kwargs.pop("tweenType")
+ else: t_type = self.defaultTweenType
+
+ if "onCompleteFunction" in kwargs:
+ t_completeFunc = kwargs.pop("onCompleteFunction")
+ else: t_completeFunc = None
+
+ if "onUpdateFunction" in kwargs:
+ t_updateFunc = kwargs.pop("onUpdateFunction")
+ else: t_updateFunc = None
+
+ if "tweenDelay" in kwargs:
+ t_delay = kwargs.pop("tweenDelay")
+ else: t_delay = 0
+
+ tw = Tween( obj, t_time, t_type, t_completeFunc, t_updateFunc, t_delay, **kwargs )
+ if tw:
+ self.currentTweens.append( tw )
+ return tw
+
+ def removeTween( tweenObj ):
+ if self.currentTweens.contains( tweenObj ):
+ tweenObj.complete = True
+ #self.currentTweens.remove( tweenObj )
+
+ def getTweensAffectingObject( self, obj ):
+ """Get a list of all tweens acting on the specified object
+ Useful for manipulating tweens on the fly"""
+ tweens = []
+ for t in self.currentTweens:
+ if t.target is obj:
+ tweens.append(t)
+ return tweens
+
+ def removeTweeningFrom( self, obj ):
+ """Stop tweening an object, without completing the motion
+ or firing the completeFunction"""
+ for t in self.currentTweens:
+ if t.target is obj:
+ t.complete = True
+
+
+ def update(self, timeSinceLastFrame):
+ for t in self.currentTweens:
+ if not t.complete:
+ t.update( timeSinceLastFrame )
+ else:
+ self.currentTweens.remove(t)
+
+class Tween(object):
+ def __init__(self, obj, tduration, tweenType, completeFunction, updateFunction, delay, **kwargs):
+ """Tween object:
+ Can be created directly, but much more easily using Tweener.addTween( ... )
+ """
+ #print obj, tduration, kwargs
+ self.duration = tduration
+ self.delay = delay
+ self.target = obj
+ self.tween = tweenType
+ self.tweenables = kwargs
+ self.delta = 0
+ self.completeFunction = completeFunction
+ self.updateFunction = updateFunction
+ self.complete = False
+ self.tProps = []
+ self.tFuncs = []
+ self.paused = self.delay > 0
+ self.decodeArguments()
+
+ def decodeArguments(self):
+ """Internal setup procedure to create tweenables and work out
+ how to deal with each"""
+
+ if len(self.tweenables) == 0:
+ # nothing to do
+ print "TWEEN ERROR: No Tweenable properties or functions defined"
+ self.complete = True
+ return
+
+ for k, v in self.tweenables.items():
+
+ # check that its compatible
+ if not hasattr( self.target, k):
+ print "TWEEN ERROR: " + str(self.target) + " has no function " + k
+ self.complete = True
+ break
+
+ prop = func = False
+ startVal = 0
+ newVal = v
+
+ try:
+ startVal = self.target.__dict__[k]
+ prop = k
+ propName = k
+
+ except:
+ func = getattr( self.target, k)
+ funcName = k
+
+ if func:
+ try:
+ getFunc = getattr(self.target, funcName.replace("set", "get") )
+ startVal = getFunc()
+ except:
+ # no start value, assume its 0
+ # but make sure the start and change
+ # dataTypes match :)
+ startVal = newVal * 0
+ tweenable = Tweenable( startVal, newVal - startVal)
+ newFunc = [ k, func, tweenable]
+
+ #setattr(self, funcName, newFunc[2])
+ self.tFuncs.append( newFunc )
+
+
+ if prop:
+ tweenable = Tweenable( startVal, newVal - startVal)
+ newProp = [ k, prop, tweenable]
+ self.tProps.append( newProp )
+
+ #print dir(self)
+
+ def pause( self, numSeconds=-1 ):
+ """Pause this tween
+ do tween.pause( 2 ) to pause for a specific time
+ or tween.pause() which pauses indefinitely."""
+ self.paused = True
+ self.delay = numSeconds
+
+ def resume( self ):
+ """Resume from pause"""
+ if self.paused:
+ self.paused=False
+
+ def update(self, ptime):
+ """Update this tween with the time since the last frame
+ if there is an update function, it is always called
+ whether the tween is running or paused"""
+ if self.paused:
+ if self.delay > 0:
+ self.delay = max( 0, self.delay - ptime )
+ if self.delay == 0:
+ self.paused = False
+ self.delay = -1
+ if self.updateFunction:
+ self.updateFunction()
+ return
+
+ self.delta = min(self.delta + ptime, self.duration)
+
+ if not self.complete:
+ for propName, prop, tweenable in self.tProps:
+ self.target.__dict__[prop] = self.tween( self.delta, tweenable.startValue, tweenable.change, self.duration )
+ for funcName, func, tweenable in self.tFuncs:
+ func( self.tween( self.delta, tweenable.startValue, tweenable.change, self.duration ) )
+
+
+ if self.delta == self.duration:
+ self.complete = True
+ if self.completeFunction:
+ self.completeFunction()
+
+ if self.updateFunction:
+ self.updateFunction()
+
+
+
+ def getTweenable(self, name):
+ """Return the tweenable values corresponding to the name of the original
+ tweening function or property.
+
+ Allows the parameters of tweens to be changed at runtime. The parameters
+ can even be tweened themselves!
+
+ eg:
+
+ # the rocket needs to escape!! - we're already moving, but must go faster!
+ twn = tweener.getTweensAffectingObject( myRocket )[0]
+ tweenable = twn.getTweenable( "thrusterPower" )
+ tweener.addTween( tweenable, change=1000.0, tweenTime=0.4, tweenType=tweener.IN_QUAD )
+
+ """
+ ret = None
+ for n, f, t in self.tFuncs:
+ if n == name:
+ ret = t
+ return ret
+ for n, p, t in self.tProps:
+ if n == name:
+ ret = t
+ return ret
+ return ret
+
+
+
+
+ def Remove(self):
+ """Disables and removes this tween
+ without calling the complete function"""
+ self.complete = True
+
+class Tweenable:
+ def __init__(self, start, change):
+ """Tweenable:
+ Holds values for anything that can be tweened
+ these are normally only created by Tweens"""
+ self.startValue = start
+ self.change = change
+
+
+
+
+
+class TweenTestObject:
+ def __init__(self):
+ self.pos = 20
+ self.rot = 50
+
+ def update(self):
+ print self.pos, self.rot
+
+ def setRotation(self, rot):
+ self.rot = rot
+
+ def getRotation(self):
+ return self.rot
+
+ def complete(self):
+ print "I'm done tweening now mommy!"
+
+
+if __name__=="__main__":
+ import time
+ T = Tweener()
+ tst = TweenTestObject()
+ mt = T.addTween( tst, setRotation=500.0, tweenTime=2.5, tweenType=T.OUT_EXPO,
+ pos=-200, tweenDelay=0.4, onCompleteFunction=tst.complete,
+ onUpdateFunction=tst.update )
+ s = time.clock()
+ changed = False
+ while T.hasTweens():
+ tm = time.clock()
+ d = tm - s
+ s = tm
+ T.update( d )
+ if mt.delta > 1.0 and not changed:
+
+ tweenable = mt.getTweenable( "setRotation" )
+
+ T.addTween( tweenable, change=-1000, tweenTime=0.7 )
+ T.addTween( mt, duration=-0.2, tweenTime=0.2 )
+ changed = True
+ #print mt.duration,
+ print tst.getRotation(), tst.pos
+ time.sleep(0.06)
+ print tst.getRotation(), tst.pos
\ No newline at end of file
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]