Source code for domonic.lerpy.tween

from domonic.events import EventDispatcher, TweenEvent
from domonic.javascript import window
from domonic.lerpy import get_timer
from domonic.lerpy.easing import *


class TweenEquation:
    def __init__(self, ease, extra=None):
        self.ease = ease
        self.extra = extra


class TweenData:
    def __init__(self, prop, target, equation=None):
        self.prop = prop
        self.target = target
        self.equation = equation
        self.start = 0
        self.change = 0


[docs]class Tween(EventDispatcher): """ Tween is a complex lerp but you don't have do the math cos robert penner did already. Just pass an easing equation from the easing package i.e twn = Tween(someObj, { 'x':10, 'y':5, 'z':3}, 6, Linear.easeIn ) will tween the objects properties over the given time using Linear.easeIn """ FPS = 60 _tweening = False _paused = False _target = None _values = None _equations = None _duration = 0 _delay = 0 _position = 0 _loop = False _timeStart = 0 _timePaused = 0 _timePrevious = 0 def __init__(self, target=None, values=None, duration=0, equations=None, delay=0, loop=False): self.target = target self.values = values self.duration = duration self.equations = equations self.delay = delay self.loop = loop self._intID = None super().__init__() @property def tweening(self): return self._foo @property def paused(self): return self._paused @property def position(self): if self._position < 0: return 0 elif self._position > 100: return 100 else: return self._position @property def target(self): return self._target @target.setter def target(self, target): self._target = target @property def values(self): v = {} for value in self._values: v[value.prop] = value.target return v @values.setter def values(self, values): if values != None: self._values = [] for s in values: self._values.append(TweenData(s, values[s])) self.equations = self._equations @property def duration(self): return self._duration # /1000 @duration.setter def duration(self, duration): self._duration = duration # * 1000 @property def equations(self): return self._equations @equations.setter def equations(self, equations): if equations != None: self._equations = equations e = equations if type(equations) == list else [equations] i = 0 for v in self._values: i = len(e) - 1 if i > len(e) - 1 else i if callable(e[i]): p = TweenEquation(e[i]) else: p = TweenEquation(e[i].fn, {"a": e[i].a, "b": e[i].b}) v.equation = p i += 1 @property def delay(self): return self._delay # / 1000 @delay.setter def delay(self, delay): self._delay = delay # * 1000 @property def loop(self): return self._loop @loop.setter def loop(self, loop): """Set to True if you want it to loop""" self._loop = loop def start(self): self._timeStart = get_timer() # TODO!! --- self._timePaused = 0 self._timePrevious = self._timeStart self._position = 0 for v in self._values: v.start = self._target[v.prop] v.change = v.target - v.start self._tweening = True self._paused = False self._intID = window.setInterval(self._update, 1000 / Tween.FPS, TweenEvent(TweenEvent.TIMER)) self.dispatchEvent(TweenEvent(TweenEvent.START, self)) def stop(self): self._tweening = False self.dispatchEvent(TweenEvent(TweenEvent.STOP, self)) # NOTE # window.clearInterval(self._intID ) # clearInt fails. because join won't allow as a 'return' happens just after the stop self._intID.stopped.set() # call stopped on the thread so program exits
[docs] def pause(self): """Pauses the tween from changing the values""" # TODO - pause should modify timer so it DOESNT jump frames. at mo does the opposite. # seems to not increment. then suddenly jumps to catch up with where it should be self._paused = True self.dispatchEvent(TweenEvent(TweenEvent.PAUSE if self._paused else TweenEvent.UNPAUSE, self))
[docs] def unpause(self): """unpauses the tween""" self._paused = False self.dispatchEvent(TweenEvent(TweenEvent.UNPAUSE, self))
def reset(self): for v in self._values: self._target[v.prop] = v.start self._update(get_timer()) self.dispatchEvent(TweenEvent(TweenEvent.RESET, self)) def _update(self, event): timeCurrent = get_timer() if self._tweening: if not self._paused: self.dispatchEvent(TweenEvent(TweenEvent.UPDATE_START, self)) time = timeCurrent - self._timePaused - self._timeStart self._position = 100 / (self._duration + self._delay) * time if time < self._delay: return time -= self._delay if time > self._duration: for v in self._values: self._target[v.prop] = v.target if self._loop: self._timeStart = timeCurrent self._timePaused = 0 self._timePrevious = self._timeStart self._position = 0 self.reset() else: self.dispatchEvent(TweenEvent(TweenEvent.UPDATE_END, self)) self.stop() self.dispatchEvent(TweenEvent(TweenEvent.COMPLETE, self)) return for v in self._values: e = v.equation x = e.extra a = x.a if x != None else 0 b = x.b if x != None else 0 self._target[v.prop] = e.ease(time, v.start, v.change, self._duration, a, b) self.dispatchEvent(TweenEvent(TweenEvent.UPDATE_END, self)) else: self._timePaused += timeCurrent - self._timePrevious self._timePrevious = timeCurrent
# def _dispatchEvent(self, event): # if event.type == TweenEvent.UPDATE_START: # self._timeStart = get_timer() # self._timePaused = 0 # self._timePrevious = self._timeStart # self._position = 0 # self.dispatchEvent(event) # elif event.type == TweenEvent.UPDATE_END: # self.dispatchEvent(event) # elif event.type == TweenEvent.START: # self.dispatchEvent(event) # elif event.type == TweenEvent.STOP: # self.dispatchEvent(event) # elif event.type == TweenEvent.PAUSE: # self.dispatchEvent(event) # elif event.type == TweenEvent.UNPAUSE: # self.dispatchEvent(event) # elif event.type == TweenEvent.RESET: # self.dispatchEvent(event) # elif event.type == TweenEvent.COMPLETE: # self.dispatchEvent(event) # elif event.type == TweenEvent.UPDATE: # self.dispatchEvent(event) # else: # super(Tween, self)._dispatchEvent(event)