# Path: vectortween/Animation.py
# class Animation(AbstractAnimation):
#     def __init__(self, frm, to):
#         self.frm = frm
#         self.to = to
# 
#     def make_frame(self, frame, birthframe, startframe, stopframe, deathframe, noiseframe=None):
#         """
#         returns a single frame
#         :param frame: current frame 
#         :param birthframe: frame before which animation always returns None
#         :param startframe: frame from which animation starts to evolve 
#         :param stopframe: frame in which animation completed
#         :param deathframe: frame in which animation starts returning None
#         :param noiseframe: frame in which a time varying noise function is evaluated
#         :return: tweened value
#         """
#         return None
# 
#     def curve_points(self, beginframe, endframe, framestep, birthframe, startframe, stopframe, deathframe,
#                      filternone=True, noiseframe=None):
#         """
#         returns a list of frames from startframe to stopframe, in steps of framestepj
#         warning: the list of points may include "None" elements 
#         :param beginframe: first frame to include in list of points
#         :param endframe: last frame to include in list of points
#         :param framestep: framestep 
#         :param birthframe: frame before which animation always returns None
#         :param startframe: frame from which animation starts to evolve 
#         :param stopframe: frame in which animation completed
#         :param deathframe: frame in which animation starts returning None 
#         :param filternone: automatically remove None entries
#         :param noiseframe: for time varying noise, this represents the time for which the noise should be evaluated
#         :return: list of tweened values
#         """
#         if endframe < beginframe and framestep > 0:
#             assert False, "infinite loop: beginframe = {0}, endframe = {1}, framestep = {2}".format(beginframe,
#                                                                                                     endframe, framestep)
#         if endframe > beginframe and framestep < 0:
#             assert False, "infinite loop: beginframe = {0}, endframe = {1}, framestep = {2}".format(beginframe,
#                                                                                                     endframe, framestep)
# 
#         i = beginframe
#         result = [self.make_frame(i, birthframe, startframe, stopframe, deathframe, noiseframe)]
#         while i < endframe:
#             i += framestep
#             if i <= endframe:
#                 result.append(self.make_frame(i, birthframe, startframe, stopframe, deathframe, noiseframe))
#         if filternone:
#             return filter_none(result)
#         else:
#             return result
# 
# Path: vectortween/NumberAnimation.py
# class NumberAnimation(Animation):
#     """
#     class to animate the value of a number between startframe and stopframe
#     tweening optionally can be applied (default is None, which means linear animation)
#     """
# 
#     def __init__(self, frm, to, tween=None, noise_fn=None):
#         """
#         
#         :param frm: start value 
#         :param to: end value
#         :param tween: optional tweening function (default: linear)
#         :param noise_fn: optional noise function (default: None)
#           noise_fn needs to accept two parameters: a value (frm <= value <= to) and a time (0 <= time <= 1)
#           if the noise_fn uses parameter t the noise will be animated in time; by accepting but ignoring t,
#           the noise is only spatial
#         """
#         super().__init__(frm, to)
#         if tween is None:
#             tween = ['linear']
#         self.noise_fn = noise_fn
#         self.T = Tween(*tween)
# 
#     #@lru_cache(maxsize=1000)
#     def make_frame(self, frame, birthframe, startframe, stopframe, deathframe, noiseframe=None):
#         """
#         animation happens between startframe and stopframe
#         the value is None before aliveframe, and after deathframe
#          * if aliveframe is not specified it defaults to startframe
#          * if deathframe is not specified it defaults to stopframe
#      
#         initial value is held from aliveframe to startframe
#     
#         final value is held from stopfrome to deathframe 
#         """
# 
#         if birthframe is None:
#             birthframe = startframe
#         if deathframe is None:
#             deathframe = stopframe
#         if frame < birthframe:
#             return None
#         if frame > deathframe:
#             return None
#         if frame < startframe:
#             return self.frm
#         if frame > stopframe:
#             return self.to
# 
#         t = self.T.tween2(frame, startframe, stopframe)
#         newval = Mapping.linlin(t, 0, 1, self.frm, self.to)
#         if self.noise_fn is not None:
#             if noiseframe is not None:
#                 nf = noiseframe
#             else:
#                 nf = t
#             noise_val = self.noise_fn(newval, nf)
#         else:
#             noise_val = 0
# 
#         return newval + noise_val


from functools import lru_cache
from vectortween.Animation import Animation
from vectortween.NumberAnimation import NumberAnimation
    """

    def __init__(self, frm, to, tween=None, tweengreen=None, tweenblue=None, tweenalpha=None):
        """
        :param frm: start color, e.g. (1,0,0) for red (optionally also specify an alpha component)
        :param to: stop color, e.g. (0,1,0) for green (optionally also specify an alpha component)
        :param tween: tween method for red color component (defaults to linear if not specified)
        :param tweengreen: tween method for green color component (defaults to same as red if not specified)
        :param tweenblue: tween method for blue color component (defaults to same as red if not specified)
        :param tweenalpha: tween method for alpha color component (defaults to Linear if not specified)
 
        Note: output will contain alpha if input contains alpha
        """
        super().__init__(frm, to)
        try:
            dummy = frm[3]
            self.use_alpha = True
        except IndexError:
            self.use_alpha = False
            pass

        if tweenalpha is None:
            tweenalpha = ['linear']

        self.anim_red = NumberAnimation(self.frm[0], self.to[0], tween)
        self.anim_green = NumberAnimation(self.frm[1], self.to[1], tweengreen)
        self.anim_blue = NumberAnimation(self.frm[2], self.to[2], tweenblue)
        if self.use_alpha:
            self.anim_alpha = NumberAnimation(self.frm[3], self.to[3], tweenalpha)
        else:

# Path: vectortween/Animation.py
# class Animation(AbstractAnimation):
#     def __init__(self, frm, to):
#         self.frm = frm
#         self.to = to
# 
#     def make_frame(self, frame, birthframe, startframe, stopframe, deathframe, noiseframe=None):
#         """
#         returns a single frame
#         :param frame: current frame 
#         :param birthframe: frame before which animation always returns None
#         :param startframe: frame from which animation starts to evolve 
#         :param stopframe: frame in which animation completed
#         :param deathframe: frame in which animation starts returning None
#         :param noiseframe: frame in which a time varying noise function is evaluated
#         :return: tweened value
#         """
#         return None
# 
#     def curve_points(self, beginframe, endframe, framestep, birthframe, startframe, stopframe, deathframe,
#                      filternone=True, noiseframe=None):
#         """
#         returns a list of frames from startframe to stopframe, in steps of framestepj
#         warning: the list of points may include "None" elements 
#         :param beginframe: first frame to include in list of points
#         :param endframe: last frame to include in list of points
#         :param framestep: framestep 
#         :param birthframe: frame before which animation always returns None
#         :param startframe: frame from which animation starts to evolve 
#         :param stopframe: frame in which animation completed
#         :param deathframe: frame in which animation starts returning None 
#         :param filternone: automatically remove None entries
#         :param noiseframe: for time varying noise, this represents the time for which the noise should be evaluated
#         :return: list of tweened values
#         """
#         if endframe < beginframe and framestep > 0:
#             assert False, "infinite loop: beginframe = {0}, endframe = {1}, framestep = {2}".format(beginframe,
#                                                                                                     endframe, framestep)
#         if endframe > beginframe and framestep < 0:
#             assert False, "infinite loop: beginframe = {0}, endframe = {1}, framestep = {2}".format(beginframe,
#                                                                                                     endframe, framestep)
# 
#         i = beginframe
#         result = [self.make_frame(i, birthframe, startframe, stopframe, deathframe, noiseframe)]
#         while i < endframe:
#             i += framestep
#             if i <= endframe:
#                 result.append(self.make_frame(i, birthframe, startframe, stopframe, deathframe, noiseframe))
#         if filternone:
#             return filter_none(result)
#         else:
#             return result
# 
# Path: vectortween/NumberAnimation.py
# class NumberAnimation(Animation):
#     """
#     class to animate the value of a number between startframe and stopframe
#     tweening optionally can be applied (default is None, which means linear animation)
#     """
# 
#     def __init__(self, frm, to, tween=None, noise_fn=None):
#         """
#         
#         :param frm: start value 
#         :param to: end value
#         :param tween: optional tweening function (default: linear)
#         :param noise_fn: optional noise function (default: None)
#           noise_fn needs to accept two parameters: a value (frm <= value <= to) and a time (0 <= time <= 1)
#           if the noise_fn uses parameter t the noise will be animated in time; by accepting but ignoring t,
#           the noise is only spatial
#         """
#         super().__init__(frm, to)
#         if tween is None:
#             tween = ['linear']
#         self.noise_fn = noise_fn
#         self.T = Tween(*tween)
# 
#     #@lru_cache(maxsize=1000)
#     def make_frame(self, frame, birthframe, startframe, stopframe, deathframe, noiseframe=None):
#         """
#         animation happens between startframe and stopframe
#         the value is None before aliveframe, and after deathframe
#          * if aliveframe is not specified it defaults to startframe
#          * if deathframe is not specified it defaults to stopframe
#      
#         initial value is held from aliveframe to startframe
#     
#         final value is held from stopfrome to deathframe 
#         """
# 
#         if birthframe is None:
#             birthframe = startframe
#         if deathframe is None:
#             deathframe = stopframe
#         if frame < birthframe:
#             return None
#         if frame > deathframe:
#             return None
#         if frame < startframe:
#             return self.frm
#         if frame > stopframe:
#             return self.to
# 
#         t = self.T.tween2(frame, startframe, stopframe)
#         newval = Mapping.linlin(t, 0, 1, self.frm, self.to)
#         if self.noise_fn is not None:
#             if noiseframe is not None:
#                 nf = noiseframe
#             else:
#                 nf = t
#             noise_val = self.noise_fn(newval, nf)
#         else:
#             noise_val = 0
# 
#         return newval + noise_val


# Path: vectortween/ColorAnimation.py
from functools import lru_cache
from vectortween.Animation import Animation
from vectortween.NumberAnimation import NumberAnimation

    """

    def __init__(self, frm, to, tween=None, tweengreen=None, tweenblue=None, tweenalpha=None):
        """
        :param frm: start color, e.g. (1,0,0) for red (optionally also specify an alpha component)
        :param to: stop color, e.g. (0,1,0) for green (optionally also specify an alpha component)
        :param tween: tween method for red color component (defaults to linear if not specified)
        :param tweengreen: tween method for green color component (defaults to same as red if not specified)
        :param tweenblue: tween method for blue color component (defaults to same as red if not specified)
        :param tweenalpha: tween method for alpha color component (defaults to Linear if not specified)
 
        Note: output will contain alpha if input contains alpha
        """
        super().__init__(frm, to)
        try:
            dummy = frm[3]
            self.use_alpha = True
        except IndexError:
            self.use_alpha = False
            pass

        if tweenalpha is None:
            tweenalpha = ['linear']

        self.anim_red = NumberAnimation(self.frm[0], self.to[0], tween)
        self.anim_green = NumberAnimation(self.frm[1], self.to[1], tweengreen)
        self.anim_blue = NumberAnimation(self.frm[2], self.to[2], tweenblue)
        if self.use_alpha:
            self.anim_alpha = NumberAnimation(self.frm[3], self.to[3], tweenalpha)
        else:

            self.anim_alpha = NumberAnimation(1, 1, tweenalpha)