def start_resize(item_image, image, from_size, to_size, duration, origin_type = 1, callback = None):
    """
    Start a resize animation on the specified ItemImage.
    - item: ItemImage to resize.
    - image: Image that is resized an assigned to the ItemImage.
    - from_size: Initial size specified as (width, height).
    - to_size: Final size specified as (width, height).
    - origin_type: Origin. Possible values:
        0 - Left X, Left Y.
        1 - Center X, Center Y.
    - callback: Function that is invoked with parameter item when the animation is completed. None
      there is no callback function.     
    """
    stage = __get_item_stage(item_image)        
    
    # If a move timer is already started for the item, stop it
    key = (item_image, "resize")
    milliseconds = 20
    stage.stop_timer(key)    
    
    # Set the initial size
    resized_image = assets.Image(pygame.transform.smoothscale(image.surface, (int(from_size[0]), int(from_size[1]))))
    item_image.set_image(resized_image) 
    
    if origin_type == 1:
        orgin_pos = (item_image.get_left() + item_image.get_width() / 2, item_image.get_top() + item_image.get_height() / 2)
    else:
        orgin_pos = None
    
    # Start the timer    
    data = [None, image, duration, origin_type, orgin_pos, from_size, to_size, callback, stage]        
    stage.start_timer(key, milliseconds, __timer_resize, data, True, True)    
def start_move(item, left, top, duration, acceleration = None, move_marks = None, callback = None):
    """
    Starts an animation that moves the specified item in a straight line to 
    the specified position.
    - item: Item.
    - left: Target left.
    - top: Target top.
    - duration: Duration in milliseconds of the move animation.
    - acceleration: Acceleration. It use a sinusoidal function to calculate
          the displacement as time pass. A pair with (maxvel_t, maxvel_dist, tension)
          should be passed in this parameter to control the movement, where:       
          * maxvel_t: Value between 0 and 1 that indicate the percentage of the
              time of the point with the higher velocity. If you indicate 
              0.5 the maximum velocity will be reached in the middle of the
              movement.
          * maxvel_dist: Value between 0 and 1 that indicate the percentage of the
             distance that is traveled at maxvel_t. 
          * tension: Indicate how curved is the movement, it is power that is 
              applied to the sine function. If it is 1 the movement is a 
              sinusoidal function. Values less than 1 indicate a movement more
              closer to an uniform movement, and values greater that 1 indicates
              a more accelerated displacement.
              
        Use None to generate a uniform move.
    - move_marks: An instance of MoveMarks. Define an image that is repeated to mark the path traveled.
      None to don't print move marks.
    - callback: Function that is invoked with parameter item when the animation is completed. None
      there is no callback function.     
    """ 
    stage = __get_item_stage(item)        
    
    # If a move timer is already started for the item, stop it
    key = (item, "move")
    milliseconds = 20
    stage.stop_timer(key)    
    
    item_left = item.get_left()
    item_top = item.get_top()    
    
    # Initialize the move marks data    
    if move_marks == None:    
        move_marks_data = None
    else:
        angle = math.atan2(top - item_top, left - item_left)
        dx_per_mark = math.cos(angle) * move_marks.separation
        dy_per_mark = math.sin(angle) * move_marks.separation
        if abs(dx_per_mark) < 1 and abs(dy_per_mark) < 1:
            move_marks_data = None
        else:
            mark_image_dx = item.get_width() / 2 - move_marks.mark_image.get_width() / 2
            mark_image_dy = item.get_height() / 2 - move_marks.mark_image.get_height() / 2
            move_marks_data = [item_left - dx_per_mark, item_top - dy_per_mark, dx_per_mark, dy_per_mark, mark_image_dx, mark_image_dy]
                    
    # Start the timer
    data = [None, duration, item_left, item_top, left, top, acceleration, move_marks, move_marks_data, callback, stage]        
    stage.start_timer(key, milliseconds, __timer_move, data, True, True)
def wait(stage, milliseconds, callback):
    """
    Waits the specified time and invoke the callback.
    - stage: Stage.
    - milliseconds: Number of milliseconds to wait.
    - callback: Function to invoke (without parameters).
    
    Return the wait's timer key. It can be used to cancel the wait using the
    cancel_wait function.    
    """    
    key = ("wait", animations.WAIT_ORDINAL)
    stage.start_timer(key, milliseconds, __timer_wait, (stage, callback))
    animations.WAIT_ORDINAL += 1
    if animations.WAIT_ORDINAL == 99999:
        animations.WAIT_ORDINAL = 1
        
    return key
def fade_out_layer(layer, duration = 500, callback = None):
    """    
    Perform a fade out animation to hide the items of a layer.
    - layer: Layer.    
    - duration: Duration in milliseconds of the fade in animation.
    - callback: Function that is invoked with parameter layer when the animation is completed. None
      there is no callback function.     
    """
    stage = __get_layer_stage(layer)
    
    key = (layer, "fade")
    milliseconds = 20
    
    # If a fade timer was already started for the item, stop it
    stage.stop_timer(key)
    
    # Start the timer
    data = [pygame.time.get_ticks(), None, duration, callback, stage]
    stage.start_timer(key, milliseconds, __timer_fade_out_layer, data, True, True)
def wait_locked(stage, milliseconds, callback):
    """
    Waits the specified time and invoke the callback. While the game waits
    for the specified time the interface is locked and cannot receive mouse
    or other events.
    - stage: Stage.
    - milliseconds: Number of milliseconds to wait.
    - callback: Function to invoke (without parameters).
    
    Return the wait's timer key. It can be used to cancel the wait using the
    cancel_wait function.
    """
    stage.lock_ui()
    key = ("wait_locked", animations.WAIT_ORDINAL)
    stage.start_timer(key, milliseconds, __timer_wait_locked, (stage, callback))
    animations.WAIT_ORDINAL += 1
    if animations.WAIT_ORDINAL == 99999:
        animations.WAIT_ORDINAL = 1
        
    return key
def start_image_sequence(item_image, images, fps, loops = 0, callback = None):
    """
    Starts an animation showing a sequence of images through an ItemImage.
    - item_image: An instance of ItemImage, the images are assigned to this item.
    - images: Images (must be instances of assets.Image)
    - fps: Frames per seconds. Define the speed of the animation.
    - loops: Number of times that the sequence is repeated (0 to show the sequence only once). -1
      to repeat the image sequences indefinitely.
    - callback: Function that is invoked with parameter item_image when the animation is completed. None
      there is no callback function.     
      
    If there is already an image sequence started over the item it is stopped before start this animation. 
    """
    stage = __get_item_stage(item_image)        
    
    # If a image sequence timer was already started for the item, stop it
    key = (item_image, "image_sequence")
    stage.stop_timer(key)
    
    # Start the timer
    milliseconds = 1000 / fps
    stage.start_timer(key, milliseconds, __timer_image_sequence, [0, images, loops, callback, stage])
def fade_out_item(item, remove, duration = 500, callback = None):
    """    
    Perform a fade out animation to hide an item.
    - item: Item.
    - remove: True if the item will be removed at the end of the fade-out. False otherwise.
    - duration: Duration in milliseconds of the fade in animation.
    - callback: Function that is invoked with parameter item when the animation is completed. None
      there is no callback function.     
    """
    stage = __get_item_stage(item)
    
    key = (item, "fade")
    milliseconds = 20
    
    # If a fade timer was already started for the item, stop it
    stage.stop_timer(key)
    
    # Hide the rollover if there is a rollover over the item
    item.hide_rollover()
    
    # Start the timer
    data = [pygame.time.get_ticks(), None, duration, remove, callback, stage]
    stage.start_timer(key, milliseconds, __timer_fade_out_item, data, True, True)
def fade_in_item(item, duration = 500, callback = None, to_alpha = 255):
    """    
    Perform a fade in animation to show an item.
    - item: Item.
    - duration: Duration in milliseconds of the fade in animation.
    - callback: Function that is invoked with parameter item when the animation is completed. None
      there is no callback function. 
    - to_alpha: Final alpha value for the fade. 
    """
    stage = __get_item_stage(item)
    
    key = (item, "fade")
    milliseconds = 20
    
    if item.get_alpha() == 255:
        item.set_alpha(0)
    
    # If a fade timer was already started for the item, stop it
    stage.stop_timer(key)
    
    # Start the timer        
    data = [pygame.time.get_ticks(), None, duration, to_alpha, callback, stage]
    stage.start_timer(key, milliseconds, __timer_fade_in_item, data, True, True)
def blind_layer(layer, direction, area, duration = 450, callback = None, lock_ui = True):
    """
    Apply a blind effect to show or hide the specified layer.
    - layer: Layer.
    - direction: A value of BlindDirection that indicate the direction of the blind effect.
    - area: Area where the blind effect is applied. None to cross the entire screen. A smaller
      rectangle indicate the the blind only must cross the zone defined in the rectangle.
    - duration: Duration in milliseconds of the blind effect to cross the full screen.
      If you specify an area the duration could be smaller, because it could
      not cross the full screen. This behavior is defined to give consistency
      with the default time if you apply the effect over areas with different
      sizes. 
    - callback: Function to invoke with parameter Layer when the blind effect ends.
        None if there is no callback function.
    - lock_ui: Indicates if must lock the UI while performing the effect
    """
    stage = __get_layer_stage(layer)
    
    key = (layer, "blind")
    milliseconds = 20
    
    # Create the effect data, if there is a blind effect in progress stop
    # the effect and apply this effect from the previous position    
    data = stage.stop_timer(key)        
    window_width, window_height = stage.game.get_window_size()    
    dy_factor = float(window_height) / duration

    if data != None and data[9]:
        # There was an effect that was locking the UI, unlock it 
        stage.unlock_ui()
    
    if data != None and data[1] == direction and data[0] != None:
        # There is already an effect applied over the layer with
        # the same direction. Replace the callback and continue 
        # with the effect            
        data[7] = callback        
    else:
        if direction == BlindDirection.SHOW_UP or \
          direction == BlindDirection.SHOW_DOWN:        
            if direction == BlindDirection.SHOW_DOWN:
                if area == None:
                    current_top = 0
                else:
                    current_top = area.top
            else:
                if area == None:
                    current_top = window_height
                else:
                    current_top = area.top + area.height
            current_height = 0            
            layer.set_clip(pygame.Rect(0, current_top, window_width, 0))        
        elif direction == BlindDirection.HIDE_UP or \
          direction == BlindDirection.HIDE_DOWN:
            hidden = False
            if not layer.get_visible():
                hidden = True
            else:
                clip = layer.get_clip()
                if clip != None and (clip.width == 0 or clip.height == 0):
                    hidden = True
                          
            if hidden:
                # It is already hidden, don't apply the effect
                if callback != None:
                    callback(layer)
                return
            else:
                if area == None:
                    current_top = 0                        
                    current_height = window_height
                else:
                    current_top = area.top         
                    current_height = area.height                    
                layer.set_clip(None)            
                    
        data = [None, direction, dy_factor, window_width, window_height, current_top, current_height, callback, stage, lock_ui]
        
    if lock_ui:
        # Lock the UI while performing the effect
        stage.lock_ui()
    
    # Start the timer            
    stage.start_timer(key, milliseconds, __timer_blind_layer, data, True, True)