a
    V$cp                     @   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mZ d dlZd dlZd dlmZ zd dlm  mZ W n ey   dZY n0 d dlZd dlZd dlZd dl Z da!dd Z"da#d	d
 Z$dd Z%dd Z&G dd de'Z(G dd de'Z)i Z*G dd de'Z+e ,e+Z-dd Z.G dd dej/j0j1Z2da3dd Z4dS )    )divisionabsolute_importwith_statementprint_functionunicode_literals)PY2
basestringbchrbordchropenpystrrangeroundstrtobytesunicode)AnyN)register_shaderFc                  C   s~   t rd S tjrd} ntjr d} nd} tjtjtj	| }tj
|rL|} tsZ| d} tjj| svtd| da d S )NzLive2DCubismCore.dllzlibLive2DCubismCore.dylibzlibLive2DCubismCore.sozutf-8z(Could not load Live2D. {} was not found.T)did_onetime_initrenpywindows	macintoshospathjoindirnamesys
executableexistsr   encodegl2live2dmodelload	Exceptionformat)dllfn r(   renpy/gl2\live2d.pyonetime_init-   s    
r*   c                   C   sr   t rdS tdu rtdtjjs(tdt  tddddd td	ddd
d tdddd tjj	t
 da dS )z1
    Called to initialize Live2D, if needed.
    NzLive2D has not been built.z(Live2D requires that config.gl2 be True.zlive2d.maskz
        uniform sampler2D tex0;
        uniform sampler2D tex1;
        attribute vec4 a_position;
        attribute vec2 a_tex_coord;
        varying vec2 v_tex_coord;
        varying vec2 v_mask_coord;
    zx
        v_tex_coord = a_tex_coord;
        v_mask_coord = vec2(a_position.x / 2.0 + .5, -a_position.y / 2.0 + .5);
    z
        vec4 color = texture2D(tex0, v_tex_coord);
        vec4 mask = texture2D(tex1, v_mask_coord);
        gl_FragColor = color * mask.a;
    )	variables
vertex_200fragment_200zlive2d.inverted_maskz
        vec4 color = texture2D(tex0, v_tex_coord);
        vec4 mask = texture2D(tex1, v_mask_coord);
        gl_FragColor = color * (1.0 - mask.a);
    zlive2d.flip_texturez'
        varying vec2 v_tex_coord;
    z2
        v_tex_coord.y = 1.0 - v_tex_coord.y;
    )r+   
vertex_250T)did_initr"   r$   r   configr!   r*   r   interact_callbacksappendupdate_statesr(   r(   r(   r)   initJ   s(    r4   c                   C   s   da t  dS )z<
    Resets this module when Ren'Py reloads the script.
    FN)r/   common_cacheclearr(   r(   r(   r)   reset   s    r7   c                   C   s   t   dS )zA
    Resets the Live2D states when Ren'Py restarts the game.
    N)statesr6   r(   r(   r(   r)   reset_states   s    r9   c                   @   s   e Zd ZdZdd ZdS )Live2DExpressionz2
    The data corresponding to an expression.
    c                 C   s   || _ || _|| _d S N)
parametersfadeinfadeout)selfr<   r=   r>   r(   r(   r)   __init__   s    zLive2DExpression.__init__N)__name__
__module____qualname____doc__r@   r(   r(   r(   r)   r:      s   r:   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )Live2DCommona  
    This object stores information that is common to all of the Live2D
    displayables that use the same .model3.json file, so this information
    only needs to be loaded once. This should not leak into the save games,
    but is loaded at init time.
    c              	      s  t   |ds.|dd }|d | d }tjjrFtjjd| tj	
|s`td||dd dd  }|dd | _| jr|  jd7  _tj	|}t|| _W d    n1 s0    Y  tjj| j| jd	 d
  | _g | _| jd	 d D ] }| jtj| j|  qi }i }tj D ]n}|| jsVq@|dr|t| jd  }d|i||< n*|dr@|t| jd  }d|i||< q@ fdd  | jd	 di |  | jd	 di | t ddg| _!dtjj"# i| _$|% D ]}|d  dd dd }	|	d\}
}}|
|krV|}	tj	
| j|d  rtjjrtjjd|	|d  tjj"&| j|d  |d||d|| j$|	< | j!'|	 qdt(g ddi| _)|% D ]}|d  dd dd }	|	d\}
}}|
|kr.|}	tj	
| j|d  rtjjrftjjd|	|d  |	| j!v rtd|	tj	| j|d  }t|}W d    n1 s0    Y  t(|dg |d||d|| j)|	< | j!'|	 q| jdg D ]L}|d }	|d }|d  d!kr:|| jj*|	< n|d  d"kr
|| jj+|	< q
t,| j)| _-i | _.d#| _/d | _0d | _1d | _2d S )$Nz.json/   z.model3.jsonzLoading Live2D from %r.zLive2D model {} does not exist..r   FileReferencesMocTextureszmotion3.jsonFilez
.exp3.jsonc                    sV   t | tr"| D ]} || qd S d| v r:| || d < d S |  D ]} || qBd S )NrL   )
isinstancelistvalues)odiwalk_json_filesr(   r)   rT      s    
z.Live2DCommon.__init__.<locals>.walk_json_filesMotionsExpressionsstillnull_z - motion %s -> %s
FadeInTimeFadeOutTime        z - expression %s -> %sz+Name {!r} is already specified as a motion.
ParametersGroupsNameIdsTarget	ParameterOpacityF)3r4   endswith
rpartitionr   r0   log_live2d_loadingdisplaylogwriteloaderloadabler$   r%   	partitionlowerbaser#   json
model_jsonr!   r"   Live2DModelmodeltexturesr2   easydisplayableexports
list_files
startswithlengetset
attributeslive2dmotion
NullMotionmotionsrO   Motionaddr:   expressionsparameter_groupsopacity_groupsdictall_expressionsnonexclusiveseamlessattribute_functionattribute_filterupdate_function)r?   filenamedefault_fadesuffix
model_namefrR   motion_filesexpression_filesnameprefixrY   expression_jsonidsr(   rS   r)   r@      s    
*  




 

*



zLive2DCommon.__init__c                 C   s   |  D ]\}}d }d}|| jv r*| j}n:|| jv r@| j}d}n$|| jv rV| j}d}ntd|||v rztd||| ||< |r|| | j|< qd S )NFTz.Name {!r} is not a known motion or expression.z9Name {!r} is already specified as a motion or expression.)itemsr   r   r   r$   r%   r   )r?   aliaseskvtarget
expressionr(   r(   r)   apply_aliasesF  s"    


zLive2DCommon.apply_aliasesc                 C   s8   |D ].}|| j vr td|| j || j|< qd S )Nz$Name {!r} is not a known expression.)r   r$   r%   popr   )r?   r   rR   r(   r(   r)   apply_nonexclusiveb  s    
zLive2DCommon.apply_nonexclusivec                 C   s
   || _ d S r;   r   )r?   valuer(   r(   r)   apply_seamlessi  s    zLive2DCommon.apply_seamlessc                 C   s*   | j du rdS | j du rdS || j v S d S )NTFr   )r?   motionr(   r(   r)   is_seamlessl  s
    

zLive2DCommon.is_seamlessN)	rA   rB   rC   rD   r@   r   r   r   r   r(   r(   r(   r)   rE      s    rE   c                   @   s   e Zd Zdd Zdd ZdS )Live2DStatec                 C   s4   d| _ d| _d | _d | _d| _d| _g | _g | _d S )NFr   )mark	cycle_newoldnewold_base_timenew_base_timer   old_expressionsr?   r(   r(   r)   r@   {  s    zLive2DState.__init__c                    sx   t dd | jD  fdd| jD fdd| jD  | _fdd| jD | _|  j fddD 7  _dS )	z
        Updates the lists of new and old expressions.

        `expressions`
            A list of strings giving expression names.

        `now`
            The time the current displayable started showing.
        c                 s   s   | ]\}}|V  qd S r;   r(   ).0r   rY   r(   r(   r)   	<genexpr>      z1Live2DState.update_expressions.<locals>.<genexpr>c                    s$   g | ]\}}}| vr|||fqS r(   r(   r   r   shownhiddenr   r(   r)   
<listcomp>  r   z2Live2DState.update_expressions.<locals>.<listcomp>c                    s"   g | ]\}}| vr||fqS r(   r(   r   r   r   )r   nowr(   r)   r     r   c                    s    g | ]\}}| v r||fqS r(   r(   r   r   r(   r)   r     r   c                    s   g | ]}| vr|fqS r(   r(   )r   r   )currentr   r(   r)   r     r   N)r{   r   r   )r?   r   r   r(   )r   r   r   r)   update_expressions  s    zLive2DState.update_expressionsN)rA   rB   rC   r@   r   r(   r(   r(   r)   r   y  s   r   c                  C   s\   dd } t jj }|jddD ]}|dur ||  q t D ]}|jsPd|_	d|_q@dS )zo
    Called once per interact to walk the tree of displayables and find
    the old and new live2d states.
    c                 S   s   t | tsd S | jd u rd S t| j }|jr0d S d|_|j| u rDd S |j| u rRd S |jrj|j|_|j|_	nd |_d |_	g |_
g |_| |_| jr|j	|_nd |_d|_d S )NT)rM   Live2Dr   r8   r   r   r   r   r   r   r   r   sustain)rQ   stater(   r(   r)   visit  s0    






zupdate_states.<locals>.visitT)r   NF)
r   rg   corescene_listsget_all_displayables	visit_allr8   rO   r   r   )r   slsrQ   sr(   r(   r)   r3     s    'r3   c                       s   e Zd ZdgZdZdZdZdddZedd Z	dd	ddd
i ddddddd
ddddf fdd	Z
dd Zdd Zdd Zdd Zdd ZdddZdd Zdd Z  ZS )r   r5   NT      ?c                 C   s6   t | jd }|d u r,t| j|}|t | j< || _ |S r;   )r5   rz   r   rE   )r?   r   rvr(   r(   r)   create_common  s    
zLive2D.create_commonc                 C   s   | j d ur| j S | | jS r;   )r5   r   r   r   r(   r(   r)   common  s    
zLive2D.commonr\   Fc                    s   t t| jf i | || _|	| _|
| _|| _|| _|| _|| _	|| _
|| _|| _|| _d | _| |}|rv|| |r|| |d ur|| |d ur||_|d ur||_|d ur||_d S r;   )superr   r@   r   r   r   used_nonexclusivezoomtoprn   heightloopfader   r   r   r   r   r   r   r   r   )r?   r   r   r   rn   r   r   r   r   r   r   r   r   r   r   r   r   r   r   
propertiesr   	__class__r(   r)   r@     s4    



zLive2D.__init__c           
      C   s$  | j s
| S |s| S | j}g }g }d }d}d|jv rLtdd |jD }d}n|j}|jd urf||}|D ]z}||jv r|| qj||jv r|| qj||jv r|d urt	d
d|j|||}qjt	d
d|j|qjt| j|| j| j| j| j| j| j|||d	}	|j|	_d|	_ |	S )
NF_sustainc                 s   s   | ]}|d kr|V  qdS )r   Nr(   r   rR   r(   r(   r)   r   O  r   z$Live2D._duplicate.<locals>.<genexpr>Tz7When showing {}, {} and {} are both live2d expressions. z-When showing {}, {} is not a known attribute.)
r   r   r   rn   r   r   r   r   r   r   )_duplicatabler   argstupler   r   r2   r   r   r$   r%   r   r   r   r   r   r   rn   r   r   r   )
r?   r   r   r   r   r   r   r|   rR   r   r(   r(   r)   
_duplicate?  sX    







zLive2D._duplicatec                    sR   | j }t|j |D ]}||jv r t|j8  q t|O   fdd|jD S )Nc                    s   g | ]}| v r|qS r(   r(   r   	availabler(   r)   r     r   z+Live2D._list_attributes.<locals>.<listcomp>)r   r{   r|   r   )r?   tagr|   r   rR   r(   r   r)   _list_attributes|  s    

zLive2D._list_attributesc                    s   | j   fdd|D }|s4d} fdd|D }nd}t|t| D ]}| jv rH|d|  qhqHt|t| D ]}| jv rx|| qxt|} jr |}t|tst|}|rd| }|S )Nc                    s   g | ]}| j v r|qS r(   r   r   r   r(   r)   r     r   z-Live2D._choose_attributes.<locals>.<listcomp>Tc                    s   g | ]}| j v r|qS r(   r   r   r   r(   r)   r     r   Fr   )r   )	r   rN   r   insertr   r2   r   r   rM   )r?   r   r|   optionalr   r   rR   r(   r   r)   _choose_attributes  s*    



zLive2D._choose_attributesc                 C   sx  | j s
dS d}d}d}d}d}|}	|dur2|| }	| j D ]d}
|j |
d}|du rTq8|j|krf q
n|j|	kr||
s q
|	|j8 }	||j8 }|d7 }q8|du rdS | j d }
| jr|js|j}d}n>|dur
||
s
|	|	|j  }|| |jkr
|j}d}|du rdS |t| j k r4| j | }n
| j d }|dkrX| j |d  }nd}|t| j d k r| j |d  }n| jr| j d }nd}||kr||rd}||kr||r|du rd}|||||}| D ]j\}}|\}}|\}}|dkr |j|| n6|dkr<|j	||| n|d	kr|j	||| q|rddS |
||||S dS )
z
        This updates the common model with the information taken from the
        motions associated with this object. It returns the delay until
        Ren'Py needs to cause a redraw to occur, or None if no delay
        should occur.
        NTFr      PartOpacityrb   Model)r   rz   durationr   r   ry   r   rr   set_part_opacityset_parameterwait)r?   r   stst_fade
do_fade_indo_fade_out
last_framecurrent_indexr   	motion_stmmotion_startcurrent_name	last_name	next_namemotion_datar   r   kindkeyfactorr   r(   r(   r)   update  s|    








 


zLive2D.updatec                    s  | j   j}t| j }tjjj fdd|jD |_t	| j
}| jrT|| j |||  d }|jD ]\}}}d}	 j| }
|
jdkr| |
jk rt|	| |
j }	d}|
jdkr| |
jk rt|	d| |
j  }	d}|
jD ]"}|j|d |d |d |	d qqn|jD ]x\}}d}	 j| }
|
jdkrf| |
jk rft|	| |
j }	d}|
jD ]$}|j|d |d |d |	d qlq|S )	Nc                    s0   g | ](\}}}|  j | jk r|||fqS r(   )r   r>   r   r   r   r(   r)   r   1  r   z-Live2D.update_expressions.<locals>.<listcomp>r   r   IdBlendValue)weight)r   rr   r8   r   r   rg   	interface
frame_timer   rN   r   r   r2   r   r   r=   minr>   r<   blend_parameterr   )r?   r   rr   r   r   redrawr   r   r   r   erR   r(   r   r)   r   (  s<    




"

&zLive2D.update_expressionsc                 C   s.   |dvrt d|| jj|||| d S )N)AddMultiply	OverwritezUnknown blend mode {!r})r$   r%   r   rr   r  )r?   r   blendr   r   r(   r(   r)   r  Z  s    zLive2D.blend_parameterc                    s  | j }|j}| jd ur| jntjj}| js.d}|rt| j }|j| urJd}|j	d u rdtj
jj |_	|jd u rtd}n"|jd u rd}n|jj | j urd}|  |rtj
jj|j	 }	n}	| ||	d }
|r|j|tj
jj|j }nd }|  | }|jd u rd }n|| }|
|||g}dd |D }|rPtj
j| t|  fdd|jD }| \}| j}fdd}|d u r|| j}|| j}t|| d}d| j tjj | }n}d}|||}tj !|| || }|"|d| | f |S )	NFc                 S   s   g | ]}|d ur|qS r;   r(   r   r(   r(   r)   r     r   z!Live2D.render.<locals>.<listcomp>c              	      s"   g | ]}t jj| qS r(   )r   rg   render)r   rQ   )atr   r   widthr(   r)   r     r   c                    s   t | tr|   S | S d S r;   )rM   float)n)shr(   r)   r     s    
zLive2D.render.<locals>.sr   r   )#r   rr   r   r   store_live2d_fader   r8   r   r   rg   r   r  r   r   reset_parametersr   finish_parametersr   r   r
  r  r  rs   get_sizer   r   rn   maxr   r0   screen_heightrv   Renderblit)r?   r  r   r   r  r   rr   r   r   t
new_redraw
old_redrawexpression_redrawuser_redrawredrawsrs   swr   r   r   rn   sizerendr   r(   )r  r   r  r   r  r)   r
  `  sb    








zLive2D.renderc                 C   s   | j jS r;   )r   rs   r   r(   r(   r)   r     s    zLive2D.visit)r   )r   )rA   rB   rC   nosaver5   r   r   r   propertyr   r@   r   r   r   r   r   r  r
  r   __classcell__r(   r(   r   r)   r     sB   


==%y2
^r   c                   C   s2   t du r.zt  da W n ty,   da Y n0 t S )zq
    :doc: live2d

    Returns True if Live2d is supported on the current platform, and
    False otherwise.
    NTF)_has_live2dr4   r$   r(   r(   r(   r)   
has_live2d  s    

r&  )5
__future__r   r   r   r   r   renpy.compatr   r   r	   r
   r   r   r   r   r   r   r   r   typingr   r   renpy.gl2.live2dmotionrenpy.gl2.gl2shadercacher   renpy.gl2.live2dmodelr!   r"   ImportErrorr   r   ro   collectionsr   r*   r/   r4   r7   r9   objectr:   rE   r5   r   defaultdictr8   r3   rg   r   Displayabler   r%  r&  r(   r(   r(   r)   <module>   s@   8
= R0
:   `