pilas.pytweener

Package pilas :: Module pytweener |
[hide private]
[frames] | no frames]

# Source Code for Module pilas.pytweener

      1  # pyTweener
      2  #
      3  # Tweening functions for python
      4  #
      5  # Heavily based on caurina Tweener: http://code.google.com/p/tweener/
      6  #
      7  # Released under M.I.T License - see above url
      8  # Python version by Ben Harling 2009
      9  import math
     10
     11 -class Tweener(object):
     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
     20 -    def hasTweens(self):
     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
     55 -    def addTween(self, obj, **kwargs):
     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
    103 -    def removeTween(self, tweenObj):
    104          if tweenObj in self.currentTweens:
    105              tweenObj.complete = True
    106              #self.currentTweens.remove( tweenObj )
    107
    108 -    def getTweensAffectingObject(self, obj):
    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
    117 -    def removeTweeningFrom(self, obj):
    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
    124 -    def removeTweeningFromObjectField(self, obj, field):
    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
    133 -    def finish(self):
    134          #go to last frame for all tweens
    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
    150 -    def eliminar_todas(self):
    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          #print obj, tduration, kwargs
    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
    180 -    def decodeArguments(self):
    181          """Internal setup procedure to create tweenables and work out
    182             how to deal with each"""
    183
    184          if len(self.tweenables) == 0:
    185              # nothing to do
    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          # check that its compatible
    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                      # no start value, assume its 0
    223                      # but make sure the start and change
    224                      # dataTypes match :)
    225                      startVal = newVal * 0
    226
    227                  startVal = initial_value
    228                  tweenable = Tweenable( startVal, newVal - startVal)
    229                  newFunc = [ k, func, tweenable]
    230
    231                  #setattr(self, funcName, newFunc[2])
    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
    293 -    def resume( self ):
    294          """Resume from pause"""
    295          if self.paused:
    296              self.paused=False
    297
    298 -    def update(self, ptime):
    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
    335 -    def getTweenable(self, name):
    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
    361 -    def Remove(self):
    362          """Disables and removes this tween
    363              without calling the complete function"""
    364          self.complete = True
    365
    366
    367 -class Tweenable:
    368 -    def __init__(self, start, change):
    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  """
    415 -class Easing:
    416 -    class Back:
    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
    428 -        def easeInOut (t, b, c, d, s = 1.70158):
    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
    438 -    class Bounce:
    439          @staticmethod
    440 -        def easeOut (t, b, c, d):
    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
    455 -        def easeIn (t, b, c, d):
    456              return c - Easing.Bounce.easeOut(d-t, 0, c, d) + b
    457
    458          @staticmethod
    459 -        def easeInOut (t, b, c, d):
    460              if t < d * 0.5:
    461                  return Easing.Bounce.easeIn (t * 2, 0, c, d) * .5 + b
    462
    463              return Easing.Bounce.easeOut (t * 2 -d, 0, c, d) * .5 + c*.5 + b
    464
    465
    466
    467 -    class Circ:
    468          @staticmethod
    469 -        def easeIn (t, b, c, d):
    470              t = t / d
    471              return -c * (math.sqrt(1 - t**2) - 1) + b
    472
    473          @staticmethod
    474 -        def easeOut (t, b, c, d):
    475              t = t / d - 1
    476              return c * math.sqrt(1 - t**2) + b
    477
    478          @staticmethod
    479 -        def easeInOut (t, b, c, d):
    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
    488 -    class Cubic:
    489          @staticmethod
    490 -        def easeIn (t, b, c, d):
    491              t = t / d
    492              return c * t**3 + b
    493
    494          @staticmethod
    495 -        def easeOut (t, b, c, d):
    496              t = t / d - 1
    497              return c * (t**3 + 1) + b
    498
    499          @staticmethod
    500 -        def easeInOut (t, b, c, d):
    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
    509 -    class Elastic:
    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
    548 -        def easeInOut (t, b, c, d, a = 0, p = 0):
    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
    570 -    class Expo:
    571          @staticmethod
    572 -        def easeIn(t, b, c, d):
    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
    579 -        def easeOut(t, b, c, d):
    580              if t == d:
    581                  return b + c
    582              else:
    583                  return c * (-math.pow(2, -10 * t / d) + 1) + b
    584
    585          @staticmethod
    586 -        def easeInOut(t, b, c, d):
    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
    600 -    class Linear:
    601          @staticmethod
    602 -        def easeNone(t, b, c, d):
    603              return c * t / d + b
    604
    605          @staticmethod
    606 -        def easeIn(t, b, c, d):
    607              return c * t / d + b
    608
    609          @staticmethod
    610 -        def easeOut(t, b, c, d):
    611              return c * t / d + b
    612
    613          @staticmethod
    614 -        def easeInOut(t, b, c, d):
    615              return c * t / d + b
    616
    617
    618 -    class Quad:
    619          @staticmethod
    620 -        def easeIn (t, b, c, d):
    621              t = t / d
    622              return c * t**2 + b
    623
    624          @staticmethod
    625 -        def easeOut (t, b, c, d):
    626              t = t / d
    627              return -c * t * (t-2) + b
    628
    629          @staticmethod
    630 -        def easeInOut (t, b, c, d):
    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
    639 -    class Quart:
    640          @staticmethod
    641 -        def easeIn (t, b, c, d):
    642              t = t / d
    643              return c * t**4 + b
    644
    645          @staticmethod
    646 -        def easeOut (t, b, c, d):
    647              t = t / d - 1
    648              return -c * (t**4 - 1) + b
    649
    650          @staticmethod
    651 -        def easeInOut (t, b, c, d):
    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
    660 -    class Quint:
    661          @staticmethod
    662 -        def easeIn (t, b, c, d):
    663              t = t / d
    664              return c * t**5 + b
    665
    666          @staticmethod
    667 -        def easeOut (t, b, c, d):
    668              t = t / d - 1
    669              return c * (t**5 + 1) + b
    670
    671          @staticmethod
    672 -        def easeInOut (t, b, c, d):
    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
    680 -    class Sine:
    681          @staticmethod
    682 -        def easeIn (t, b, c, d):
    683              return -c * math.cos(t / d * (math.pi / 2)) + c + b
    684
    685          @staticmethod
    686 -        def easeOut (t, b, c, d):
    687              return c * math.sin(t / d * (math.pi / 2)) + b
    688
    689          @staticmethod
    690 -        def easeInOut (t, b, c, d):
    691              return -c * 0.5 * (math.cos(math.pi * t / d) - 1) + b
    692
    693
    694 -    class Strong:
    695          @staticmethod
    696 -        def easeIn(t, b, c, d):
    697              return c * (t/d)**5 + b
    698
    699          @staticmethod
    700 -        def easeOut(t, b, c, d):
    701              return c * ((t / d - 1)**5 + 1) + b
    702
    703          @staticmethod
    704 -        def easeInOut(t, b, c, d):
    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
    713
    714
    715 -class TweenTestObject:
    716 -    def __init__(self):
    717          self.pos = 20
    718          self.rot = 50
    719
    720 -    def update(self):
    721          print self.pos, self.rot
    722
    723 -    def setRotation(self, rot):
    724          self.rot = rot
    725
    726 -    def getRotation(self):
    727          return self.rot
    728
    729 -    def complete(self):
    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          #print mt.duration,
    755          print tst.getRotation(), tst.pos
    756          time.sleep(0.06)
    757      print tst.getRotation(), tst.pos
    758