import collections from .GameChild import GameChild class Animation(GameChild): def __init__(self, parent, method=None, interval=None, unfiltered=False): GameChild.__init__(self, parent) self.unfiltered = unfiltered self.default_method = method or self.build_frame self.accounts = collections.OrderedDict() self.register(self.default_method, interval=interval) self.last_update = 0 def build_frame(self): pass def register(self, *args, **kwargs): interval = None if "interval" in kwargs: interval = kwargs["interval"] for method in args: if method not in self.accounts: self.accounts[method] = Account(interval, self) else: self.accounts[method].set_interval(interval) def play(self, method=None, interval=None, delay=0, play_once=False, **kwargs): account = self.accounts[self.get_default(method)] account.set_delay(delay) account.set_args(kwargs) account.set_play_once(play_once) if interval: account.set_interval(interval) account.play() def get_default(self, method=None): if not method: method = self.default_method elif isinstance(method, str): return getattr(self, method) return method def halt(self, method=None): if not method: for account in self.accounts.values(): account.halt() else: if method in self.accounts: self.accounts[method].halt() def is_playing(self, method=None, check_all=False, include_delay=False): if check_all: return any(self.is_account_playing(account, include_delay) for method, account in self.accounts.items()) return self.is_account_playing(self.accounts[self.get_default(method)], include_delay) def is_account_playing(self, account, include_delay): return account.playing and (include_delay or not account.delay) def reset_timer(self, method=None): if not method: for account in self.accounts.values(): account.reset_timer() else: self.accounts[method].reset_timer() def update(self): for method, account in self.accounts.items(): if account.update(): method(**account.args) class Account: def __init__(self, interval, animation): self.animation = animation self.time_filter = animation.get_game().time_filter self.set_interval(interval) self.set_delay(0) self.set_play_once(False) self.interval_index = 0 self.last_frame = 0 self.halt() def set_interval(self, interval): if isinstance(interval, int) or isinstance(interval, str): interval = [interval] self.interval = interval def set_delay(self, delay): self.delay = delay def set_play_once(self, play_once): self.play_once = play_once def set_args(self, args): self.args = args def play(self): self.playing = True def halt(self): self.last_update = None self.playing = False def update(self): if self.playing: if self.animation.unfiltered: ticks = self.time_filter.get_unfiltered_ticks() else: ticks = self.time_filter.get_ticks() self.update_delay(ticks) if not self.delay: interval = self.interval if interval: if ticks - self.last_frame < self.get_current_interval(): return False self.last_frame = ticks self.increment_interval_index() if self.play_once: self.halt() return True def get_current_interval(self): return self.interval[self.interval_index] def increment_interval_index(self, increment=1): index = self.interval_index + increment while index >= len(self.interval): index -= len(self.interval) self.interval_index = index def reset_interval(self): self.interval_index = 0 def reset_timer(self): if self.animation.unfiltered: ticks = self.time_filter.get_unfiltered_ticks() else: ticks = self.time_filter.get_ticks() self.last_frame = ticks def update_delay(self, ticks): delay = self.delay if delay > 0: last_update = self.last_update or ticks delay -= ticks - last_update if delay < 0: delay = 0 self.last_update = ticks self.delay = delay