a
    VŸ$cšF  ã                   @   s  d dl mZmZmZmZmZ d dlmZmZm	Z	m
Z
mZmZmZmZmZmZmZmZ d dlZd dlZdZdadadZdZddd„Zdd	d
„ZeZeZi Ze e ¡Z!i Z"dae#ƒ Z$dd„ Z%dd„ Z&ddd„Z'dd„ Z(dd„ Z)d a*G dd„ dej+j,j-ƒZ.dd„ Z/dd„ Z0dd„ Z1dS ) é    )ÚdivisionÚabsolute_importÚwith_statementÚprint_functionÚunicode_literals)ÚPY2Ú
basestringÚbchrÚbordÚchrÚopenÚpystrÚrangeÚroundÚstrÚtobytesÚunicodeNF)i  i,  Tc                 C   s    t s|rdS tjjjdd dS )z,
    Stops the currently playing movie.
    NÚmovie©Úchannel)Ú
fullscreenÚrenpyÚaudioÚmusicÚstop)ÚclearÚonly_fullscreen© r   úrenpy/display\video.pyÚ
movie_stop/   s    r   c                 C   sT   t jjrdS |dur|a| g} |dkr,d}nd}| |d  } t jjj| d|d dS )z&
    This starts a movie playing.
    NéÿÿÿÿTFé   r   )r   Úloop)r   ÚgameÚless_updatesÚdefault_sizer   r   Úplay)ÚfilenameÚsizeÚloopsr"   r   r   r   Úmovie_start:   s    r*   c                   C   s   t  ¡  t ¡  dS )zU
    Called early in the interact process, to clear out the fullscreen
    flag.
    N)Údisplayable_channelsr   Úchannel_movier   r   r   r   Úearly_interacth   s    r-   c                  C   sd   t t ¡ ƒD ]} tjj | ¡st| = qtjj d¡r\t ¡ D ]} | d dkr<da q`q<dandatS )zz
    This is called each time the screen is drawn, and should return True
    if the movie should display fullscreen.
    r   r   FT)	ÚlistÚtextureÚkeysr   r   r   Úget_playingr+   r   )Úir   r   r   Úinteractr   s    r3   c                 C   s"  t jj | ¡sdS |d u r"t jj}t jj | ¡}| ¡ }|r„|d ur~| ¡ \}}|d }| 	|d||f¡}| 	dd||f¡}q¤d }n |r t jj |¡}	|	 ¡ }nd }|d urÎ|rÊt j
j ||t j
jj¡ nd }|d ur
t j
j |¡ t j
j |dd|i¡}
|
t| < d}nt | d ¡}
d}|
|fS )N)NFé   r   TÚmipmapF)r   r   r   r1   ÚconfigÚmipmap_moviesÚget_channelÚ
read_videoÚget_sizeÚ
subsurfaceÚdisplayÚmoduleÚalpha_mungeÚimÚidentityÚrenderÚmutated_surfaceÚdrawÚload_texturer/   Úget)r   Úmask_channelÚ	side_maskr5   ÚcÚsurfÚwÚhÚ	mask_surfÚmcÚtexÚnewr   r   r   Úget_movie_texture   s:    

rP   c                 C   s¾   t | ƒ\}}|d u rd S | ¡ \}}td| | d| | ƒ}|| }|| }	tjj ||¡}
tjj d| ddd| ¡|
_	tjj |dd|¡|
_
|
 |t|| d ƒt||	 d ƒf¡ |
S )Ng      ð?ç        r4   )rP   r:   Úminr   r<   rA   ÚRenderÚmatrixÚMatrix2DÚforwardÚreverseÚblitÚint)r   ÚwidthÚheightrN   Ú_newÚswÚshÚscaleÚdwÚdhÚrvr   r   r   Úrender_movie¿   s    (rc   c                 C   sB   t jjj|j|j|jdd |jr>t jjj|j|j|jdd d S )NT)r   r"   Úsynchro_start)	r   r   r   r&   Ú_playr   r"   ÚmaskrF   )ÚoldrO   r   r   r   Údefault_play_callbackÔ   s    rh   c                       sŽ   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdd„ Zdd	„ Zd
d„ Zd‡ fdd„	Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z‡  ZS )ÚMoviea£  
    :doc: movie

    This is a displayable that shows the current movie.

    `fps`
        The framerate that the movie should be shown at. (This is currently
        ignored, but the parameter is kept for backwards compatibility.
        The framerate is auto-detected.)

    `size`
        This should be specified as either a tuple giving the width and
        height of the movie, or None to automatically adjust to the size
        of the playing movie. (If None, the displayable will be (0, 0)
        when the movie is not playing.)

    `channel`
        The audio channel associated with this movie. When a movie file
        is played on that channel, it will be displayed in this Movie
        displayable. If this is left at the default of "movie", and `play`
        is provided, a channel name is automatically selected, using
        :var:`config.single_movie_channel` and :var:`config.auto_movie_channel`.

    `play`
        If given, this should be the path to a movie file, or a list
        of paths to movie files. These movie
        files will be automatically played on `channel` when the Movie is
        shown, and automatically stopped when the movie is hidden.

    `side_mask`
        If true, this tells Ren'Py to use the side-by-side mask mode for
        the Movie. In this case, the movie is divided in half. The left
        half is used for color information, while the right half is used
        for alpha information. The width of the displayable is half the
        width of the movie file.

        Where possible, `side_mask` should be used over `mask` as it has
        no chance of frames going out of sync.

    `mask`
        If given, this should be the path to a movie file, or a list of paths
        to movie files, that are used as
        the alpha channel of this displayable. The movie file will be
        automatically played on `movie_channel` when the Movie is shown,
        and automatically stopped when the movie is hidden.

    `mask_channel`
        The channel the alpha mask video is played on. If not given,
        defaults to `channel`\_mask. (For example, if `channel` is "sprite",
        `mask_channel` defaults to "sprite_mask".)

    `start_image`
        An image that is displayed when playback has started, but the
        first frame has not yet been decoded.

    `image`
        An image that is displayed when `play` has been given, but the
        file it refers to does not exist. (For example, this can be used
        to create a slimmed-down mobile version that does not use movie
        sprites.) Users can also choose to fall back to this image as a
        preference if video is too taxing for their system. The image will
        also be used if the video plays, and then the movie ends.

    `play_callback`
        If not None, a function that's used to start the movies playing.
        (This may do things like queue a transition between sprites, if
        desired.) It's called with the following arguments:

        `old`
            The old Movie object, or None if the movie is not playing.
        `new`
            The new Movie object.

        A movie object has the `play` parameter available as ``_play``,
        while the ``channel``, ``loop``, ``mask``, and ``mask_channel`` fields
        correspond to the given parameters.

        Generally, this will want to use :func:`renpy.music.play` to start
        the movie playing on the given channel, with synchro_start=True.
        A minimal implementation is::

            def play_callback(old, new):

                renpy.music.play(new._play, channel=new.channel, loop=new.loop, synchro_start=True)

                if new.mask:
                    renpy.music.play(new.mask, channel=new.mask_channel, loop=new.loop, synchro_start=True)

    `loop`
        If False, the movie will not loop. If `image` is defined, the image
        will be displayed when the movie ends. Otherwise, the displayable will
        become transparent.
    Fr   NTc                 C   s,   t |tƒrtj |¡S tdd„ |D ƒƒS dS )zš
        If `name` is a string, checks if that filename is loadable.
        If `name` is a list of strings, checks if any filenames is loadable.
        c                 s   s   | ]}t j |¡V  qd S ©N)r   ÚloaderÚloadable)Ú.0r2   r   r   r   Ú	<genexpr>W  ó    z%Movie.any_loadable.<locals>.<genexpr>N)Ú
isinstancer   r   rk   rl   Úany)ÚselfÚnamer   r   r   Úany_loadableN  s    
zMovie.any_loadablec                 C   s„   | j p
| j}|d ur,|  |¡r,| | _ | _nd | _|| _ | jd ur€d| jv sVd| jv r€d t¡| _td7 a| jd ur€| jd | _d S )Nú ú/ú	_movie_{}r!   Ú_mask)Ú_original_playre   rt   r   ÚformatÚmovie_channel_serialrF   )rr   r&   r   r   r   Úafter_setstateY  s    
zMovie.after_setstatec              	   C   sR   |d u rd S t jj |¡rd S | jr*d}nd}t jjj|t jjddd|dd d S )NTF)r"   Ústop_on_muter   Ú	framedropÚforce)r   r   r   Úchannel_definedrf   Úregister_channelr6   Úmovie_mixer)rr   rs   r~   r   r   r   Úensure_channelk  s    zMovie.ensure_channelé   c                    s,  t t| ƒjf i |¤Ž |dkr4|r4tjjr4tjj}n&|dkrZ|rZtjjrZd t¡}td7 a|| _	|| _
|
| _|| _|d urŠ|  |¡rŠ|| _|	r’d }|| _|d u r¨d | _n|d u r¼|d | _n|| _|	| _|  | j
¡ |  | j¡ tj |¡| _tj |¡| _|| _| j
dkr(tjjr(tjr(tdƒ‚d S )Nr   rw   r!   rx   zoMovie(channel='movie') doesn't work on mobile when config.hw_video is true. (Use a different channel argument.))Úsuperri   Ú__init__r   r6   Úsingle_movie_channelÚauto_movie_channelrz   r{   r(   r   r"   ry   rt   re   rf   rF   rG   rƒ   ÚeasyÚdisplayable_or_noneÚimageÚstart_imageÚplay_callbackÚhw_videoÚmobileÚ	Exception)rr   Úfpsr(   r   r&   rf   rF   r‹   r   rG   r"   rŒ   Ú
properties©Ú	__class__r   r   r†   z  s8    

zMovie.__init__c                 C   sÂ  | j r2tjjjdur2| t| j< |dkr2t | j¡ tj	j
 | j¡}| }| jtv rVd}| jd ur¨|r¨tjj | j||||¡}| ¡ \}}	tjj ||	¡}
|
 |d¡ |
S | jd u rpt| j| j| j| jjƒ\}}|s
|d ur
| ¡ \}}tjj ||¡}
|
 |d¡ nd|s^| jd ur^tjj | j||||¡}| ¡ \}}	tjj ||	¡}
|
 |d¡ ntjj dd¡}
n>| j\}}	|s†d }
nt| j||	ƒ}
|
d u r®tjj ||	¡}
tjj | d¡ |
S )NTr   F)r   r   gš™™™™™¹?)re   r   r#   ÚpreferencesÚvideo_image_fallbackr,   r   Úreset_channelsÚaddr   r   r1   r‹   r<   rA   r:   rS   rX   r(   rP   rF   rG   Ústyler5   rŒ   rc   Úredraw)rr   rZ   r[   ÚstÚatÚplayingÚnot_playingrI   rJ   rK   rb   rN   Ú_r   r   r   rA   §  sD    



zMovie.renderc                 C   s~   |d u rd }n|j }| j |ks&tjjrz| j rP| jd urD|  || ¡ qzt|| ƒ n*tjjj| j	d | j
rztjjj| jd d S ©Nr   )re   r   r6   Úreplay_movie_spritesr   rh   r   r   r   r   rf   rF   )rr   rg   Úold_playr   r   r   r&   ä  s    
z
Movie.playc                 C   s4   | j r0tjjj| jd | jr0tjjj| jd d S r    )re   r   r   r   r   r   rf   rF   ©rr   r   r   r   r   ø  s    z
Movie.stopc                 C   s*   t | j| jf  | ¡ tjj | d¡ d S )Nr   )r+   r   rF   Úappendr   r<   rA   rš   r£   r   r   r   Úper_interactÿ  s    zMovie.per_interactc                 C   s   | j | jgS rj   )r‹   rŒ   r£   r   r   r   Úvisit  s    zMovie.visit)r„   Nr   NNNNNFTN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   re   ry   rf   rF   rG   r‹   rŒ   r   r"   rt   r|   rƒ   r†   rA   r&   r   r¥   r¦   Ú__classcell__r   r   r“   r   ri   Þ   s*   ^-=ri   c                  C   s<   t jj d¡rdS tD ] } | \}}t jj |¡r dS qd S )Nr   T)r   r   r   r1   r+   )r2   r   Ú_mask_channelr   r   r   r     s    r   c                  C   s–   t j ¡ j} t ¡ D ]B\}}|  |d¡}|tv rDt jj	rD| 
|¡ q||ur| 
|¡ q|  ¡ D ]\}}|tvr`| ¡  q`ttƒt j ¡ _t ¡  dS )z0
    Calls play/stop on Movie displayables.
    N)r   r#   Úcontextr   r,   ÚitemsrE   r—   r6   r¡   r&   r   Údictr   )Úold_channel_movierH   Úmrg   r   r   r   Úupdate_playing  s    
r²   c                  C   sÖ   t ƒ  tjj ¡  trœd} tD ]L}|\}}tjj |¡}| ¡ sHd}  ql|rtjj |¡}| ¡ sd}  qlq| r˜t ¡ D ]}|D ]}tjj	 
|d¡ q€qxdS trÒtjs¬tjr´tjjsÒtjj d¡}| ¡ rÎdS dS dS )zn
    Called to update the video playback. Returns true if a video refresh is
    needed, false otherwise.
    TFrQ   r   )r²   r   r   Úadvance_timer+   r8   Úvideo_readyÚvaluesr<   rA   rš   r   ÚandroidÚiosr6   rŽ   )Úupdater2   r   rF   rH   ÚvÚjr   r   r   Úfrequent,  s4    r»   )TF)Nr   )NFN)2Ú
__future__r   r   r   r   r   Úrenpy.compatr   r   r	   r
   r   r   r   r   r   r   r   r   Úcollectionsr   Úcurrent_movier   r%   Úsurface_fileÚsurfacer   r*   Úmovie_start_fullscreenÚmovie_start_displayabler/   Údefaultdictr.   r+   r,   Úsetr—   r-   r3   rP   rc   rh   r{   r<   ÚcoreÚDisplayableri   r   r²   r»   r   r   r   r   Ú<module>   s:   8




2  +