§
    ×Û¾jìE  ã                  ó,  — d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	Z	ddl
mZmZmZmZ ddlZddlmZmZmZmZmZ  ee¦  «                             ¦   «         j        j        j        Zedz  dz  d	z  d
z  ZdCdDd„Z	 dEdFd„Z	 dGdFd„Z	 	 dHdId*„ZdJdKd0„Z dLdMd4„Z!dNd6„Z"dOdPd8„Z#e$d9k    rh ej%        d:¬;¦  «        Z&e& '                    d<d=d>¬?¦  «         e& '                    d@d=dA¬?¦  «         e& (                    ¦   «         Z) e#e)j*        ¬B¦  «         dS dS )Qa!  
FreeExile 2.5D Isometric Animation Pipeline & Motion Matching Generator.
Generates multi-frame animation sprite atlases, PBR normal maps, and kinematics manifests.

Features:
- Character & Monster Kinematic Frame Synthesizer (Idle, Run, Attack, Skill, Dodge, Hurt, Death)
- Foot-Speed Synchronizer (Stride-length to Velocity motion matching to eliminate foot sliding)
- Action-Speed Scaler (Windup, Impact Hit Frame, Recovery phase alignment)
- 8-Directional Isometric Heading Resolver
- Tangent-Space Normal Map Baker for PBR dynamic lighting
é    )ÚannotationsN)ÚPath)ÚAnyÚDictÚListÚTuple)ÚImageÚ
ImageChopsÚ	ImageDrawÚImageEnhanceÚImageFilterÚclientÚwebappÚassetsÚ
animationsç      @Ú
albedo_imgúImage.ImageÚstrengthÚfloatÚreturnc                ó  — |                       d¦  «        }t          j        |t          j        ¬¦  «        dz  }t          j        |dd¬¦  «        }d|dd	…dd	…f         z  d
|dd	…dd…f         z  z   d|dd…dd	…f         z  z
  d|dd…dd…f         z  z   d
|dd…dd	…f         z  z
  d
|dd…dd…f         z  z   |z  }d|dd	…dd	…f         z  d|dd	…dd…f         z  z
  d
|dd	…dd…f         z  z
  d
|dd…dd	…f         z  z   d|dd…dd…f         z  z   d
|dd…dd…f         z  z   |z  }t          j        |¦  «        }t          j        |dz  |dz  z   |dz  z   ¦  «        }d
||dk    <   ||z  }	||z  }
||z  }|	dz  dz   dz                       t          j        ¦  «        }|
dz  dz   dz                       t          j        ¦  «        }|dz  dz   dz                       t          j        ¦  «        }| j	        dk    r|  
                    ¦   «         d         nt          j        d| j        d¦  «        }t          j        dt          j        |¦  «        t          j        |¦  «        t          j        |¦  «        |f¦  «        S )zDComputes tangent-space normal map using vectorized NumPy operations.ÚL)Údtypeg     ào@é   Úedge)Úmodeg      ð¿Néþÿÿÿç      ð?é   ç       @éÿÿÿÿr   ç      à?éÿ   ÚRGBA)ÚconvertÚnpÚarrayÚfloat32ÚpadÚ	ones_likeÚsqrtÚastypeÚuint8r   Úsplitr	   ÚnewÚsizeÚmergeÚ	fromarray)r   r   ÚgrayÚarrÚpaddedÚdxÚdyÚdzÚlen_vecÚnxÚnyÚnzÚrÚgÚbÚalphas                   ú@C:\Projects\FreeExile\tools\asset_pipeline\animation_pipeline.pyÚgenerate_sobel_normal_maprC      sé  € à×Ò˜cÑ"Ô"€DÝ
Œ(�4�rœzÐ
*Ñ
*Ô
*¨UÑ
2€CÝŒV�C˜ Ð(Ñ(Ô(€Fð 	ˆv�c�r�c˜3˜B˜3�hÔÑ #¨¨s°¨s°A°B°B¨w¬Ñ"7Ñ7Ø
��q˜�t˜S˜b˜S�yÔ!Ñ
!ñ	"Ø$'¨&°°2°°q°r°r°Ô*:Ñ$:ñ	;à
��q�r�r˜3˜B˜3�w”Ñ
ñ	 à"%¨¨q¨r¨r°1°2°2¨v¬Ñ"6ñ	7ð 	ñ	
€Bð 	ˆv�c�r�c˜3˜B˜3�hÔÑ #¨¨s°¨s°A°b°D¨yÔ(9Ñ"9Ñ9¸CÀ&ÈÈ"ÈÈaÈbÈbÈÄ/Ñ<QÑQØ
��q�r�r˜3˜B˜3�w”Ñ
ñ	 Ø"%¨¨q¨r¨r°1°R°4¨xÔ(8Ñ"8ñ	9Ø;>ÀÈÈÈÈAÈBÈBÈÄÑ;Oñ	Pàñ
€Bõ
 
Œ�cÑ	Ô	€BÝŒg�b˜!‘e˜b !™e‘m b¨!¡eÑ+Ñ,Ô,€GØ€GˆG�qŠLÑØ	ˆg‰€BØ	ˆg‰€BØ	ˆg‰€Bà
ˆs‰(�S‰.˜CÑ	×'Ò'­¬Ñ1Ô1€AØ
ˆs‰(�S‰.˜CÑ	×'Ò'­¬Ñ1Ô1€AØ
ˆs‰(�S‰.˜CÑ	×'Ò'­¬Ñ1Ô1€Aà&0¤o¸Ò&?Ð&?ˆJ×ÒÑÔ˜rÔ"Ð"ÅUÄYÈsÐT^ÔTcÐehÑEiÔEi€EÝŒ;�v¥¤°Ñ 2Ô 2µE´OÀAÑ4FÔ4FÍÌÐXYÑHZÔHZÐ\aÐbÑcÔcÐcó    ©é    éÀ   Úbase_imgÚ	anim_nameÚstrÚ	frame_idxÚintÚtotal_framesÚ
frame_sizeúTuple[int, int]c                ó¸	  — |\  }}t          j        d||fd¦  «        }| j        | j        z  }t	          |dz  ¦  «        }	t	          |	|z  ¦  «        }
|                      |
|	ft           j        j        ¦  «        }|t          d|¦  «        z  }|t          j
        z  dz  }||
z
  dz  }||	z
  dz
  }d}d}d	}d
}d
}|dk    r8t          j        |¦  «        }d|dz  z   }d|dz  z
  }t	          |dz  ¦  «        }�n�|dk    r´t          j        |dz  ¦  «        dz  }t	          |¦  «        }t          j        |¦  «        dz  }dt          t          j        |¦  «        ¦  «        dz  z
  }dt          t          j        |¦  «        ¦  «        dz  z   }t	          t          j        |¦  «        dz  ¦  «        }�nÇ|dk    rP|d
k    rd}d}d}�n³|dk    r
d}d}d}d}�n£|dk    rd}d}d}d}d}�n‘|d k    rd!}d"}d}�nƒ|dk    rd#}d$}�nwd	}d}�nq|d%k    r‰|t          j
        z  dz  }t          j        |¦  «        }t          |¦  «        d&k    rt          |¦  «        nd&}t	          t          j        |dz  ¦  «        dz  ¦  «        }t          j        |¦  «        d'z  }nâ|d(k    rz|d)z  }|d*k     r|nd	}d+t          j        |t          j
        z  ¦  «        d,z  z   }t	          |dz  ¦  «        }t	          t          j        |t          j
        z  ¦  «        d-z  ¦  «        }nb|d.k    r\t          j        |t          j
        z  ¦  «        }t	          | d/z  ¦  «        }t	          |dz  ¦  «        }| d/z  }d|d0z  z
  }d|d1z  z   }t          d"t	          |
|z  ¦  «        ¦  «        }t          d"t	          |	|z  ¦  «        ¦  «        }|                     ||ft           j        j        ¦  «        }t          |¦  «        d2k    r'|                     |t           j        j        d3¬4¦  «        }||z   |
|j        z
  dz  z   }||z   |	|j        z
  z   }|                     |||f|¦  «         |dk    r�|dk    r{t#          j        |¦  «        } ||j        dz  z   d"z
  }!|d5z   }"|!d6z   }#|"d7z   }$|                      |!|"|#|$gd8d6d9d:¬;¦  «         |                      |!dz   |"dz   |#dz
  |$dz
  gd8d6d<d¬;¦  «         |S )=z_Synthesizes an animation frame for the Savage Primal Hero with kinematically sound deformation.r%   ©r   r   r   r   g=
×£p=ê?r   r!   r    é   r   ç        r   Úidlegš™™™™™™?g¸…ëQ¸Ž?r   Úrunç      @g      @g{®Gáz¤?ç¸…ëQ¸ž?ç      @Úattack_slashg       Àéüÿÿÿr   g      ,Àiøÿÿÿgffffffî?ç      2@é   gHáz®Gñ?g®Gázî?é   ç      $@é
   ç      @é   Úskill_whirlwindçš™™™™™¹?g      @Údodgeç     €v@çš™™™™™é?ç      è?g333333Ã?g       @Úhurtç      (@g{®Gáz´?çš™™™™™©?r#   T©ÚresampleÚexpandé   éF   éK   i  )éï   éD   rr   éÜ   é   )ÚstartÚendÚfillÚwidth)éþ   éÊ   rz   r$   )r	   r0   rx   ÚheightrL   ÚresizeÚ
ResamplingÚLANCZOSÚmaxÚmathÚpiÚsinÚcosÚabsÚBILINEARÚrotateÚpaster   ÚDrawÚarc)%rH   rI   rK   rM   rN   ÚfwÚfhÚframeÚaspectÚtarget_hÚtarget_wÚscaled_heroÚtÚphaseÚoxÚoyÚsquash_xÚsquash_yÚrot_degÚshift_xÚshift_yÚbreatheÚ
pelvis_bobÚangleÚscale_xÚ
roll_angleÚrecoilÚw_deformÚh_deformÚdeformedÚpaste_xÚpaste_yÚdrawÚarc_x0Úarc_y0Úarc_x1Úarc_y1s%                                        rB   Úsynthesize_hero_framerª   @   s@  € ð �F€BˆÝŒI�f˜r 2˜h¨Ñ5Ô5€Eð Œ^˜hœoÑ-€FÝ�2˜‘9‰~Œ~€HÝ�8˜fÑ$Ñ%Ô%€HØ—/’/ 8¨XÐ"6½Ô8HÔ8PÑQÔQ€Kà•C˜˜<Ñ(Ô(Ñ(€AØ•”‰K˜#Ñ€Eà
ˆx‰-˜AÑ	€BØ	ˆh‰˜Ñ	€Bà€HØ€HØ€GØ€GØ€Gà�FÒÐå”(˜5‘/”/ˆØ˜ 5™Ñ(ˆØ˜ 5™Ñ(ˆÝ�g ‘mÑ$Ô$ˆ‰à	�eÒ	Ð	õ ”X˜e c™kÑ*Ô*¨SÑ0ˆ
Ý�j‘/”/ˆÝ”(˜5‘/”/ CÑ'ˆØ��TœX e™_œ_Ñ-Ô-°Ñ4Ñ4ˆØ��TœX e™_œ_Ñ-Ô-°Ñ4Ñ4ˆÝ•d”h˜u‘o”o¨Ñ+Ñ,Ô,ˆ‰à	�nÒ	$Ð	$ð
 ˜Š>ˆ>ØˆGØˆGØˆG‰GØ˜!Š^ˆ^ØˆGØˆGØˆGØˆH‰HØ˜!Š^ˆ^ØˆGØˆGØˆGØˆHØˆH‰HØ˜!Š^ˆ^ØˆGØˆGØˆG‰GØ˜!Š^ˆ^ØˆGØˆG‰GàˆGØˆG‰Gà	Ð'Ò	'Ð	'à•D”G‘˜cÑ!ˆÝ”(˜5‘/”/ˆÝ#& w¡<¤<°#Ò#5Ð#5•3�w‘<”<�<¸3ˆÝ•d”h˜u s™{Ñ+Ô+¨cÑ1Ñ2Ô2ˆÝ”(˜5‘/”/ CÑ'ˆˆà	�gÒ	Ð	à˜‘Yˆ
Ø ! C¢ �*�*¨SˆØ�$œ( 1¥t¤w¡;Ñ/Ô/°$Ñ6Ñ6ˆÝ�a˜$‘h‘-”-ˆÝ•d”h˜q¥4¤7™{Ñ+Ô+¨cÑ1Ñ2Ô2ˆˆà	�fÒ	Ð	å”˜!�dœg™+Ñ&Ô&ˆÝ�v�g ‘nÑ%Ô%ˆÝ�f˜s‘lÑ#Ô#ˆØ�'˜D‘.ˆØ˜ $™Ñ&ˆØ˜ $™Ñ&ˆõ �2•s˜8 hÑ.Ñ/Ô/Ñ0Ô0€HÝ�2•s˜8 hÑ.Ñ/Ô/Ñ0Ô0€HØ×!Ò! 8¨XÐ"6½Ô8HÔ8QÑRÔR€Hå
ˆ7�|„|�cÒÐØ—?’? 7µUÔ5EÔ5NÐW[�?Ñ\Ô\ˆð �7‰l˜h¨¬Ñ7¸AÑ=Ñ=€GØ�7‰l˜h¨¬Ñ8Ñ9€GØ	‡K‚K�˜7 GÐ,¨hÑ7Ô7Ð7ð �NÒ"Ð" y°A¢~ ~ÝŒ~˜eÑ$Ô$ˆØ˜8œ>¨QÑ.Ñ.°Ñ3ˆØ˜2‘ˆØ˜"‘ˆØ˜"‘ˆØ�Š�&˜& &¨&Ð1¸À"ÐK]ÐefˆÑgÔgÐgØ�Š�&˜1‘*˜f q™j¨&°1©*°f¸q±jÐAÈÐRTÐ[oÐwxˆÑyÔyÐyà€LrD   ©rF   rF   c                ó  ‡— |\  }}t          j        d||fd¦  «        }| j        | j        z  }t	          |dz  ¦  «        }	t	          |	|z  ¦  «        }
|                      |
|	ft           j        j        ¦  «        }|t          d|¦  «        z  }|t          j
        z  dz  }||
z
  dz  }||	z
  dz
  }d}d}d	}d
}d
}|dk    r8t          j        |¦  «        }d|dz  z   }d|dz  z
  }t	          |dz  ¦  «        }�nL|dk    r}t          j        |¦  «        }t	          t          j        |dz  ¦  «        dz  ¦  «        }|dz  }dt          |¦  «        dz  z   }dt          |¦  «        dz  z
  }t	          |dz  ¦  «        }nÉ|dk    r=|d
k    rd}d}d}n¶|dk    rd}d}d}n©|dk    r	d}d}d}d}nš|dk    r	d}d}d }d!}n‹d	}d}n†|d"k    rMt          j        |t          j
        z  ¦  «        }t	          | d#z  ¦  «        }t	          |dz  ¦  «        }| d$z  }n3|d%k    r-t          d&d|d'z  z
  ¦  «        }t	          |d(z  ¦  «        }|dz  }t          dt	          |
|z  ¦  «        ¦  «        }t          dt	          |	|z  ¦  «        ¦  «        }|                     ||ft           j        j        ¦  «        }t          |¦  «        d)k    r'|                     |t           j        j        d*¬+¦  «        }||z   |
|j        z
  dz  z   }||z   |	|j        z
  z   }|d%k    r]|                     ¦   «         d,         }t          d-d|d.z  z
  ¦  «        Š|                     ˆfd/„¦  «        }|                     |¦  «         |                     |||f|¦  «         |S )0zMSynthesizes animation frames for feral monsters (quadruped/beast kinematics).r%   rQ   gö(\�Âõè?r   r!   r    r_   r   rS   r   rT   rW   g{®Gáz”?rU   g      @rV   gìQ¸…ë±?rj   r`   Úattackg      ÀéûÿÿÿçÍÌÌÌÌÌì?g      (Àiöÿÿÿg333333ë?g      .@é   iúÿÿÿgffffffò?r]   r\   gq=
×£pí?rh   g      ,@r^   Údeathçš™™™™™É?rg   r[   r#   Trk   r"   rc   rf   c                ó(   •— t          | ‰z  ¦  «        S )N)rL   )ÚpÚfade_factors    €rB   ú<lambda>z*synthesize_monster_frame.<locals>.<lambda>%  s   ø€ ¥c¨!¨k©/Ñ&:Ô&:€ rD   )r	   r0   rx   r{   rL   r|   r}   r~   r   r€   r�   r‚   rƒ   r„   r…   r†   r/   ÚpointÚputalphar‡   )rH   rI   rK   rM   rN   rŠ   r‹   rŒ   r�   rŽ   r�   Ú
scaled_mobr‘   r’   r“   r”   r•   r–   r—   r˜   r™   ÚpantÚgalloprŸ   r    r¡   r¢   r£   r¤   rA   rµ   s                                 @rB   Úsynthesize_monster_framer¼   Á   sã  ø€ ð �F€BˆÝŒI�f˜r 2˜h¨Ñ5Ô5€EàŒ^˜hœoÑ-€FÝ�2˜‘9‰~Œ~€HÝ�8˜fÑ$Ñ%Ô%€HØ—’ (¨HÐ!5µuÔ7GÔ7OÑPÔP€Jà•C˜˜<Ñ(Ô(Ñ(€AØ•”‰K˜#Ñ€Eà
ˆx‰-˜AÑ	€BØ	ˆh‰˜Ñ	€Bà€HØ€HØ€GØ€GØ€Gà�FÒÐåŒx˜‰ŒˆØ˜ ™Ñ$ˆØ˜ ™Ñ$ˆÝ�d˜S‘j‘/”/ˆ‰à	�eÒ	Ð	õ ”˜%‘”ˆÝ•d”h˜u s™{Ñ+Ô+¨cÑ1Ñ2Ô2ˆØ˜3‘,ˆØ�˜V™œ tÑ+Ñ+ˆØ�˜V™œ tÑ+Ñ+ˆÝ�f˜s‘lÑ#Ô#ˆˆà	�hÒ	Ð	ð ˜Š>ˆ>ØˆGØˆGØˆHˆHØ˜!Š^ˆ^ØˆGØˆGØˆHˆHØ˜!Š^ˆ^ØˆGØˆGØˆGØˆHˆHØ˜!Š^ˆ^ØˆGØˆGØˆGØˆHˆHàˆGØˆGˆGà	�fÒ	Ð	Ý”˜!�dœg™+Ñ&Ô&ˆÝ�v�g ‘nÑ%Ô%ˆÝ�f˜s‘lÑ#Ô#ˆØ�'˜D‘.ˆˆà	�gÒ	Ð	å�s˜C ! d¡(™NÑ+Ô+ˆÝ�a˜$‘h‘-”-ˆØ�d‘(ˆå�2•s˜8 hÑ.Ñ/Ô/Ñ0Ô0€HÝ�2•s˜8 hÑ.Ñ/Ô/Ñ0Ô0€HØ× Ò  (¨HÐ!5µuÔ7GÔ7PÑQÔQ€Hå
ˆ7�|„|�cÒÐØ—?’? 7µUÔ5EÔ5NÐW[�?Ñ\Ô\ˆà�7‰l˜h¨¬Ñ7¸AÑ=Ñ=€GØ�7‰l˜h¨¬Ñ8Ñ9€Gð �GÒÐØ—’Ñ Ô  Ô$ˆÝ˜#˜s Q¨¡W™}Ñ-Ô-ˆØ—’Ð:Ð:Ð:Ð:Ñ;Ô;ˆØ×Ò˜%Ñ Ô Ð à	‡K‚K�˜7 GÐ,¨hÑ7Ô7Ð7Ø€LrD   TFÚ	entity_idÚbase_image_pathr   Úanim_configsúDict[str, Dict[str, Any]]Ú
output_dirÚis_heroÚboolÚgenerate_mipmapsúTuple[Path, Path, Path]c                ó–  — |                      dd¬¦  «         |                     ¦   «         st          d|› �¦  «        ‚t          j        |¦  «                             d¦  «        }|\  }}	t          d„ |                     ¦   «         D ¦   «         ¦  «        }
t          d|
¦  «        }t          j
        |
|z  ¦  «        }||z  }||	z  }t          j        d||fd¦  «        }i }i }d}|                     ¦   «         D �]\  }}|d	         }g }t          |¦  «        D ]†}||z  }||z  }||z  }||	z  }|rt          |||||¦  «        }nt          |||||¦  «        }|                     |||f|¦  «         |› d
|› �}|                     |¦  «         ||||	ddgdœ||<   |dz  }Œ‡||d         |                     dd¦  «        |                     dd¦  «        |                     dd¦  «        |                     dg ¦  «        |                     dd¦  «        dœ||<   �Œ|| › d�z  }|                     |dd¬¦  «         t)          |d¬¦  «        }|| › d�z  } |                     | dd¬¦  «         | ||||	dddd d!œ||d"œ}!|| › d#�z  }"|r!dd$lm}#  |#||¦  «        }$d%„ |$D ¦   «         |!d&<   t	          |"d'd(¬)¦  «        5 }%t/          j        |!|%d*d+¬,¦  «         ddd¦  «         n# 1 swxY w Y   t3          d-| › d.�¦  «         t3          d/|› d0|› d1|› d2�¦  «         t3          d3| › �¦  «         t3          d4|"› d0t5          |¦  «        › d5�¦  «         || |"fS )6zSBakes multi-frame animation sequences into an atlas, normal map, and JSON manifest.T)ÚparentsÚexist_okzBase sprite image not found: r%   c              3  ó&   K  — | ]}|d          V — ŒdS )ÚframesN© )Ú.0Úcfgs     rB   ú	<genexpr>z+build_atlas_and_manifest.<locals>.<genexpr>?  s&   è è € ÐLÐL¨s˜S œ]ÐLÐLÐLÐLÐLÐLrD   é   rQ   r   rÊ   Ú_r#   r¯   )ÚxÚyÚwÚhÚpivotr   ÚfpsÚloopÚstride_length_worldçffffff@Ú	hit_frameNÚ	footstepsÚaction_speed_scale)rÊ   rÖ   r×   rØ   rÚ   rÛ   rÜ   z_anim_atlas.pngÚPNG)Úoptimizeçš™™™™™@)r   z_anim_atlas_normal.pngçÍÌÌÌÌÌ@z>playback_fps = base_fps * (current_velocity / base_move_speed)g×£p=
×2@)Úbase_move_speedrØ   Úfoot_speed_sync_formulaÚturn_rate_rad_per_sec)r½   Útexture_widthÚtexture_heightÚframe_widthÚframe_heightÚ
kinematicsrÊ   r   z_anim_manifest.json)Úgenerate_and_save_mipmapsc                ó   — g | ]	}|j         ‘Œ
S rË   )Úname)rÌ   r´   s     rB   ú
<listcomp>z,build_atlas_and_manifest.<locals>.<listcomp>Ž  s   € Ð#9Ð#9Ð#9¨q A¤FÐ#9Ð#9Ð#9rD   ÚmipmapsrÓ   zutf-8)Úencodingr    F)ÚindentÚensure_asciiz[+] Successfully baked z animation atlas:z    - Albedo:   z (rÑ   ú)z    - Normal:   z    - Manifest: z frames))ÚmkdirÚexistsÚFileNotFoundErrorr	   Úopenr&   ÚsumÚvaluesÚminr€   Úceilr0   ÚitemsÚrangerª   r¼   r‡   ÚappendÚgetÚsaverC   Ú!tools.asset_pipeline.mipmap_utilsré   ÚjsonÚdumpÚprintÚlen)&r½   r¾   r¿   rÁ   rN   rÂ   rÄ   rH   rŠ   r‹   Útotal_frames_countÚcolsÚrowsÚatlas_wÚatlas_hÚ	atlas_imgÚmanifest_framesÚmanifest_animsÚcur_idxrI   rÍ   Ú
num_framesÚ
frame_keysÚf_idxÚcolÚrowrÑ   rÒ   Ú
frame_surfÚf_keyÚ
atlas_pathÚ
normal_imgÚnormal_pathÚmanifest_dataÚmanifest_pathré   ÚmipsÚfs&                                         rB   Úbuild_atlas_and_manifestr  ,  s¥  € ð ×Ò˜T¨DÐÑ1Ô1Ð1à×!Ò!Ñ#Ô#ð SÝÐ QÀÐ QÐ QÑRÔRÐRåŒz˜/Ñ*Ô*×2Ò2°6Ñ:Ô:€HØ�F€Bˆõ ÐLÐL°l×6IÒ6IÑ6KÔ6KÐLÑLÔLÑLÔLÐÝˆqÐ$Ñ%Ô%€DÝŒ9Ð'¨$Ñ.Ñ/Ô/€Dà�R‰i€GØ�R‰i€GÝ”	˜& 7¨GÐ"4°lÑCÔC€Ià13€OØ02€Nà€GØ&×,Ò,Ñ.Ô.ð $
ñ $
‰ˆ	�3Ø˜”]ˆ
Øˆ
å˜:Ñ&Ô&ð 	ð 	ˆEØ˜D‘.ˆCØ˜T‘/ˆCØ�b‘ˆAØ�b‘ˆAàð jÝ2°8¸YÈÈzÐ[eÑfÔf�
�
å5°hÀ	È5ÐR\Ð^hÑiÔi�
à�OŠO˜J¨¨A¨°
Ñ;Ô;Ð;à Ð*Ð* 5Ð*Ð*ˆEØ×Ò˜eÑ$Ô$Ð$àØØØØ˜t˜ð&ð &ˆO˜EÑ"ð �q‰LˆGˆGð !Ø�u”:Ø—G’G˜F DÑ)Ô)Ø#&§7¢7Ð+@À#Ñ#FÔ#FØŸš ¨dÑ3Ô3ØŸš ¨bÑ1Ô1Ø"%§'¢'Ð*>ÀÑ"EÔ"Eð%
ð %
ˆ�yÑ!Ñ!ð  Ð;Ð;Ð;Ñ;€JØ‡N‚N�:˜u¨t€NÑ4Ô4Ð4õ +¨9¸sÐCÑCÔC€JØ )ÐCÐCÐCÑC€KØ‡O‚O�K °€OÑ6Ô6Ð6ð Ø Ø!ØØà"Ø#&Ø'gØ%*ð	
ð 
ð "Ø$ðð €Mð  IÐ!BÐ!BÐ!BÑB€MØð :ØOÐOÐOÐOÐOÐOØ(Ð(¨°ZÑ@Ô@ˆØ#9Ð#9°DÐ#9Ñ#9Ô#9ˆ�iÑ Ý	ˆm˜S¨7Ð	3Ñ	3Ô	3ð B°qÝŒ	�- ¨1¸5ÐAÑAÔAÐAðBð Bð Bñ Bô Bð Bð Bð Bð Bð Bð Bøøøð Bð Bð Bð Bõ 
Ð
@ IÐ
@Ð
@Ð
@ÑAÔAÐAÝ	Ð
?˜ZÐ
?Ð
?¨7Ð
?Ð
?°WÐ
?Ð
?Ð
?Ñ@Ô@Ð@Ý	Ð
*˜[Ð
*Ð
*Ñ+Ô+Ð+Ý	Ð
L˜]Ð
LÐ
L­c°/Ñ.BÔ.BÐ
LÐ
LÐ
LÑMÔMÐMà�{ MÐ1Ð1s   Ê5KËKË!Krà   ri   ÚvelocityÚ
base_speedÚbase_fpsc                óJ   — |dk    s| dk    rdS t          d|| |z  z  ¦  «        S )z?Calculates motion-matched frame rate to eliminate foot sliding.rS   g{®Gáz„?rX   ©r   )r  r  r  s      rB   Úcalculate_stride_fpsr!  š  s6   € à�SÒÐ˜H¨Ò,Ð,ØˆsÝˆs�H ¨:Ñ 5Ñ6Ñ7Ô7Ð7rD   r   Úbase_durationÚaction_speedc                ó,   — t          d|¦  «        }| |z  S )zGCalculates skill action duration inversely scaled by attack/cast speed.r²   r   )r"  r#  Úspeeds      rB   Úcalculate_action_durationr&  ¡  s   € å��\Ñ"Ô"€EØ˜5Ñ Ð rD   Údegc                ó˜   — | dz  dz   dz  }|dk    s|dk     rdS |dk     rdS |dk     rdS |d	k     rd
S |dk     rdS |dk     rdS |dk     rdS dS )z9Maps 360-degree angle to 8-directional isometric heading.re   g     u@g     €6@ÚEg     àP@ÚSEg      \@ÚSg     °c@ÚSWg     Pi@ÚWg     ðn@ÚNWg     Hr@ÚNÚNErË   )r'  Únorm_degs     rB   Úresolve_heading_8dirr2  §  s�   € à�e‘˜eÑ# uÑ,€HØ�5ÒÐ˜H tšO˜OØˆsØ	�DŠˆØˆtØ	�EÒ	Ð	ØˆsØ	�EÒ	Ð	ØˆtØ	�EÒ	Ð	ØˆsØ	�EÒ	Ð	ØˆtØ	�EÒ	Ð	ØˆsØˆ4rD   ÚNonec           
     óš  — t          d¦  «         t          dz  dz  dz  dz  }t          dz  dz  dz  dz  }ddd	d
œddd	dddgdœddddd	dœddd	d	dœdddd
œdddd
œdœ}g d¢}|D ]y}||› d�z  }|                     ¦   «         s|dk    r|dz  }|                     ¦   «         r<t          |||t          dd	| ¬¦  «         |dk    rt          d||t          dd	| ¬¦  «         Œzdd d	d
œdd!d	d"d#dgdœd dddd	dœdddd
œd d!dd
œd$œ}d%D ]9}||› d�z  }	|	                     ¦   «         rt          ||	|t          d&d| ¬¦  «         Œ:t          d'¦  «         d(S ))zVExecutes animation asset generation for 5 Martial Character Classes and Core Monsters.z3=== FREEEXILE 2.5D ISOMETRIC ANIMATION PIPELINE ===r   r   r   Ú
charactersÚmonstersr\   rt   T)rÊ   rÖ   r×   rÏ   é   rÙ   r   )rÊ   rÖ   r×   rØ   rÛ   é   Fr    )rÊ   rÖ   r×   rÚ   rÜ   r°   )rÊ   rÖ   r×   rÜ   rn   r]   )rT   rU   rY   rb   rd   rh   )Úchar_sword_masterÚchar_sword_maidenÚchar_feral_berserkerÚchar_wild_archerÚchar_glacial_lancerÚchar_shadow_assassinz.pngr9  zsavage_primal_exile.pngrE   )rÂ   rÄ   Úherora   r_   rß   r   )rT   rU   r­   rh   r±   )Úmob_feral_hellhoundÚmob_skeleton_warriorr«   z>[*] All animation atlases baked and synchronized successfully!N)r  ÚWORKSPACE_ROOTró   r  ÚANIMATIONS_OUT_DIR)
rÄ   Ú	chars_dirÚmobs_dirÚchar_cfgÚchar_classesÚcidÚc_baseÚmob_cfgÚmidÚm_bases
             rB   Úrun_pipelinerM  »  se  € å	Ð
?Ñ@Ô@Ð@Ý Ñ)¨HÑ4°xÑ?À,ÑN€IÝ Ñ(¨8Ñ3°hÑ>ÀÑK€Hð  Q°Ð5Ð5Ø B°ÈSÐ`aÐcdÐ_eÐfÐfØ#$¨R¸ÈQÐfjÐkÐkØ&'°¸DÐX\Ð]Ð]Ø b°%Ð8Ð8Ø R°Ð7Ð7ðð €Hðð ð €Lð ð Tð TˆØ ˜\˜\˜\Ñ)ˆØ�}Š}‰Œð 	; 3Ð*=Ò#=Ð#=ØÐ!:Ñ:ˆFØ�=Š=‰?Œ?ð 	TÝ$ S¨&°(Õ<NÐPZÐdhð  |Lð  Mñ  Mô  Mð  MØÐ)Ò)Ð)Ý(¨°¸ÕCUÐWaÐkoð  CSð  Tñ  Tô  Tð  Tøð  Q°Ð5Ð5Ø B°ÈSÐ`aÐcdÐ_eÐfÐfØ r°5ÀqÐ`dÐeÐeØ R°Ð7Ð7Ø b°%Ð8Ð8ðð €Gð ?ð Mð MˆØ˜s˜L˜L˜LÑ(ˆØ�=Š=‰?Œ?ð 	MÝ$ S¨&°'Õ;MÈzÐchð  |Lð  Mñ  Mô  Mð  Møå	Ð
JÑKÔKÐKÐKÐKrD   Ú__main__z"FreeExile Animation Pipeline Baker)Údescriptionz--generate-allÚ
store_truezGenerate all animation atlases)ÚactionÚhelpz--generate-mipmapsz"Generate mipmap chains for atlases)rÄ   )r   )r   r   r   r   r   r   )rE   )rH   r   rI   rJ   rK   rL   rM   rL   rN   rO   r   r   )r«   )TF)r½   rJ   r¾   r   r¿   rÀ   rÁ   r   rN   rO   rÂ   rÃ   rÄ   rÃ   r   rÅ   )rà   ri   )r  r   r  r   r  r   r   r   )r   )r"  r   r#  r   r   r   )r'  r   r   rJ   )F)rÄ   rÃ   r   r3  )+Ú__doc__Ú
__future__r   Úargparser   r€   ÚosÚpathlibr   ÚsysÚtypingr   r   r   r   Únumpyr'   ÚPILr	   r
   r   r   r   Ú__file__ÚresolveÚparentrB  rC  rC   rª   r¼   r  r!  r&  r2  rM  Ú__name__ÚArgumentParserÚparserÚadd_argumentÚ
parse_argsÚargsrÄ   rË   rD   rB   ú<module>re     s}  ðð
ð 
ð #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø €€€Ø 	€	€	€	Ø Ð Ð Ð Ð Ð Ø 
€
€
€
Ø )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )à Ð Ð Ð Ø GÐ GÐ GÐ GÐ GÐ GÐ GÐ GÐ GÐ GÐ GÐ GÐ GÐ Gà��h‘”×'Ò'Ñ)Ô)Ô0Ô7Ô>€Ø# hÑ.°Ñ9¸HÑDÀ|ÑSÐ ðdð dð dð dð dðL #-ð~ð ~ð ~ð ~ð ~ðL #-ðhð hð hð hð hðb Ø"ðk2ð k2ð k2ð k2ð k2ð\8ð 8ð 8ð 8ð 8ð!ð !ð !ð !ð !ðð ð ð ð((Lð (Lð (Lð (Lð (LðV ˆzÒÐØ$ˆXÔ$Ð1UÐVÑVÔV€FØ
×ÒÐ(°ÐDdÐÑeÔeÐeØ
×ÒÐ,°\ÐHlÐÑmÔmÐmØ×ÒÑÔ€DØ€L $Ô"7Ð8Ñ8Ô8Ð8Ð8Ð8ð ÐrD   