§
    "Û¾j©  ã                  ó  — U d Z ddlmZ ddlZddlm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mZ dZd	ed
<    edd¬¦  «         G d„ d¦  «        ¦   «         Zd(d„Z	 d)d*d„Z	 d)d+d„Z	 	 d,d-d$„Zd.d&„Zed'k    r e¦   «          dS dS )/zè
FreeExile Level of Detail (LOD) Sprite Generator.
Generates 3-tier LOD assets (LOD-0 100%, LOD-1 50%, LOD-2 25%) using Pillow Lanczos resampling.
Guarantees LOD-2 file size <= 40% of original for mobile VRAM and bandwidth savings.
é    )ÚannotationsN)Ú	dataclass)ÚPath)ÚDictÚListÚOptionalÚTuple)ÚImage))Úlod0g      ð?)Úlod1g      à?)Úlod2g      Ð?zTuple[Tuple[str, float], ...]Ú	LOD_SPECST)ÚslotsÚfrozenc                  óF   — e Zd ZU dZded<   ded<   ded<   ded	<   d
ed<   dS )ÚLODGenerationResultz7Stores metadata and byte sizes for generated LOD tiers.r   Úsource_pathÚintÚoriginal_sizeúDict[str, Path]Ú	lod_pathszDict[str, int]Ú	lod_sizesÚfloatÚlod2_size_ratioN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__© ó    ú;C:\Projects\FreeExile\tools\asset_pipeline\lod_generator.pyr   r      sT   € € € € € € àAÐAØÐÐÑØÐÐÑØÐÐÑØÐÐÑØÐÐÑÐÐr!   r   ÚimgúImage.ImageÚout_pathr   Úscaler   Úreturnr   c           	     óè  — |dk    r|                       ¦   «         }n‹t          dt          t          | j        |z  ¦  «        ¦  «        ¦  «        }t          dt          t          | j        |z  ¦  «        ¦  «        ¦  «        }|                      ||ft          j        j	        ¦  «        }|j
                             dd¬¦  «         |                     |dd¬¦  «         |                     ¦   «         j        S )z=Downsamples image with Lanczos filter and writes to out_path.g+‡ÙÎ÷ï?é   T©ÚparentsÚexist_okÚPNG)ÚformatÚoptimize)ÚcopyÚmaxr   ÚroundÚwidthÚheightÚresizer
   Ú
ResamplingÚLANCZOSÚparentÚmkdirÚsaveÚstatÚst_size)r#   r%   r&   ÚscaledÚnew_wÚnew_hs         r"   Ú_resample_and_saver@   %   sÇ   € à�‚~€~Ø—’‘”ˆˆå�A•s�5 ¤¨UÑ!2Ñ3Ô3Ñ4Ô4Ñ5Ô5ˆÝ�A•s�5 ¤¨eÑ!3Ñ4Ô4Ñ5Ô5Ñ6Ô6ˆØ—’˜U E˜N­EÔ,<Ô,DÑEÔEˆà„O×Ò $°ÐÑ6Ô6Ð6Ø
‡K‚K� °€KÑ6Ô6Ð6Ø�=Š=‰?Œ?Ô"Ð"r!   Ú
image_pathú
Path | strÚ
output_dirúOptional[Path | str]r   c                ó²  — t          | ¦  «                             ¦   «         }|                     ¦   «         r|                     ¦   «         st	          d|› �¦  «        ‚|r!t          |¦  «                             ¦   «         n|j        }|                     dd¬¦  «         i }t          j        |¦  «        5 }|j	        dv s	d|j
        v rdnd}|                     |¦  «        }t          D ]X\  }}	||j        › d|› |j        › �z  }
t          ||
|	¦  «         |
||<   |
||                     ¦   «         <   d	|d
         › �}|
||<   ŒY	 ddd¦  «         n# 1 swxY w Y   |S )z³Generates 3 LOD levels (LOD-0 100%, LOD-1 50%, LOD-2 25%) for a sprite image.

    Returns a dictionary mapping both lowercase ('lod0') and uppercase ('LOD-0') keys to paths.
    zSource sprite image not found: Tr*   )ÚRGBAÚLAÚtransparencyrF   ÚRGBÚ_zLOD-éÿÿÿÿN)r   ÚresolveÚexistsÚis_fileÚFileNotFoundErrorr8   r9   r
   ÚopenÚmodeÚinfoÚconvertr   ÚstemÚsuffixr@   Úupper)rA   rC   ÚsrcÚ
target_dirÚresult_pathsÚbase_imgrQ   r#   Úlod_namer&   Úout_fileÚ
hyphen_keys               r"   Úgenerate_sprite_lodsr^   3   s¼  € õ ˆzÑ
Ô
×
"Ò
"Ñ
$Ô
$€CØ�:Š:‰<Œ<ð I˜sŸ{š{™}œ}ð IÝÐ GÀ#Ð GÐ GÑHÔHÐHà/9ÐI•�jÑ!Ô!×)Ò)Ñ+Ô+Ð+¸s¼z€JØ×Ò˜T¨DÐÑ1Ô1Ð1à$&€LÝ	Œ�C‰Œð 0˜HØ!œ¨.Ð8Ð8¸^ÈxÌ}Ð=\Ð=\ˆvˆvÐchˆØ×Ò˜tÑ$Ô$ˆå(ð 	0ð 	0‰OˆH�eØ! s¤xÐ$HÐ$H°(Ð$H¸C¼JÐ$HÐ$HÑHˆHÝ˜s H¨eÑ4Ô4Ð4Ø%-ˆL˜Ñ"Ø-5ˆL˜ŸšÑ)Ô)Ñ*à. ¨¤Ð.Ð.ˆJØ'/ˆL˜Ñ$Ð$ð	0ð	0ð 0ð 0ñ 0ô 0ð 0ð 0ð 0ð 0ð 0ð 0øøøð 0ð 0ð 0ð 0ð Ðs   Â3BEÅEÅEc                ó  ‡— t          | ¦  «                             ¦   «         }|                     ¦   «         j        }t	          ||¦  «        Šˆfd„t
          D ¦   «         }|d         t          d|¦  «        z  }t          ||‰||¬¦  «        S )zGGenerates LODs and computes empirical file size and compression ratios.c                óV   •— i | ]%\  }}|‰|                               ¦   «         j        “Œ&S r    )r;   r<   )Ú.0ÚnamerJ   Úpathss      €r"   ú
<dictcomp>z+evaluate_lod_generation.<locals>.<dictcomp>\   s?   ø€ ð !ð !ð !Ù-4¨T°1ˆˆe�DŒk×ÒÑ Ô Ô(ð!ð !ð !r!   r   r)   )r   r   r   r   r   )r   rL   r;   r<   r^   r   r1   r   )rA   rC   rW   Ú	orig_sizer   Ú
lod2_ratiorc   s         @r"   Úevaluate_lod_generationrg   S   s¦   ø€ õ
 ˆzÑ
Ô
×
"Ò
"Ñ
$Ô
$€CØ—’‘
”
Ô"€IÝ   jÑ1Ô1€Eð!ð !ð !ð !Ý8Að!ñ !ô !€Ið ˜6Ô"¥S¨¨IÑ%6Ô%6Ñ6€JåØØØØØ"ðñ ô ð r!   ú*.pngÚ	directoryÚpatternÚstrúList[LODGenerationResult]c                ó$  ‡— t          | ¦  «                             ¦   «         }g }t          |                     |¦  «        ¦  «        D ]HŠt	          ˆfd„t
          D ¦   «         ¦  «        rŒ#t          ‰|¦  «        }|                     |¦  «         ŒI|S )z<Generates LODs for all matching textures within a directory.c              3  ó6   •K  — | ]\  }}d |› �‰j         v V — ŒdS )rJ   N)rT   )ra   ÚlodrJ   Ú	file_paths      €r"   ú	<genexpr>z&batch_generate_lods.<locals>.<genexpr>u   s4   øè è € ÐCÐC©v¨s°Aˆy�3ˆyˆy˜IœNÐ*ÐCÐCÐCÐCÐCÐCr!   )r   rL   ÚsortedÚglobÚanyr   rg   Úappend)ri   rC   rj   Úsrc_dirÚresultsÚresrp   s         @r"   Úbatch_generate_lodsry   j   s•   ø€ õ �9‰oŒo×%Ò%Ñ'Ô'€GØ)+€Gå˜GŸLšL¨Ñ1Ô1Ñ2Ô2ð ð ˆ	åÐCÐCÐCÐC½ÐCÑCÔCÑCÔCð 	ØÝ% i°Ñ<Ô<ˆØ�Š�sÑÔÐÐà€Nr!   ÚNonec            
     ó~  — t          j        d¬¦  «        } |                      ddt          d¬¦  «         |                      ddt          d	d
¬¦  «         |                      ddt          d	d¬¦  «         |                      dt          dd¬¦  «         |                      ddd¬¦  «         |                      ¦   «         }|j        rèt          |j        |j        ¦  «        }|j	        dz  }t          d|j        j        › �¦  «         t          d|j        › d�¦  «         |j                             ¦   «         D ]*\  }}t          d|› d|› d||j        z  dz  d›d�¦  «         Œ+|j        rA|j	        d k    r8t          d!|d"›d#�t"          j        ¬$¦  «         t#          j        d%¦  «         d	S d	S d	S |j        rwt+          |j        |j        |j        ¦  «        }t          d&t/          |¦  «        › d'|j        › �¦  «         |D ]+}t          d|j        j        › d(|j	        dz  d›d#�¦  «         Œ,d	S |                      ¦   «          d	S ))z#CLI entry point for LOD generation.zFreeExile Sprite LOD Generator)Údescriptionz--inputz-izSource PNG file)ÚtypeÚhelpz--output-dirz-oNzOutput directory)r}   Údefaultr~   z--batchz-bzBatch directory of PNGsz	--patternrh   zGlob pattern for batchz--verify-budgetÚ
store_truezAssert LOD-2 <= 40% size)Úactionr~   g      Y@zProcessed: z  Original: z bytesz  z: z bytes (éd   z.1fz%)gš™™™™™Ù?z"[ERROR] LOD-2 exceeds 40% budget: z.2fú%)Úfiler)   zBatch processed z textures in z -> LOD-2: )ÚargparseÚArgumentParserÚadd_argumentr   rk   Ú
parse_argsÚinputrg   rC   r   Úprintr   rb   r   r   ÚitemsÚverify_budgetÚsysÚstderrÚexitÚbatchry   rj   ÚlenÚ
print_help)ÚparserÚargsrx   ÚpctÚkÚvrw   Úrs           r"   Úmainr™   }   s–  € åÔ$Ð1QÐRÑRÔR€FØ
×Ò˜	 4­dÐ9JÐÑKÔKÐKØ
×Ò˜¨µ4ÀÐL^ÐÑ_Ô_Ð_Ø
×Ò˜	 4­d¸DÐG`ÐÑaÔaÐaØ
×Ò˜­#°wÐE]ÐÑ^Ô^Ð^Ø
×ÒÐ)°,ÐE_ÐÑ`Ô`Ð`Ø×ÒÑÔ€Dà„zð Ý% d¤j°$´/ÑBÔBˆØÔ! EÑ)ˆÝÐ2˜CœOÔ0Ð2Ð2Ñ3Ô3Ð3ÝÐ6˜SÔ.Ð6Ð6Ð6Ñ7Ô7Ð7Ø”M×'Ò'Ñ)Ô)ð 	Lð 	L‰DˆAˆqÝÐJ�qÐJÐJ˜AÐJÐJ q¨3Ô+<Ñ'<¸sÑ'BÐJÐJÐJÐJÑKÔKÐKÐKØÔð 	 #Ô"5¸Ò"<Ð"<ÝÐA°sÐAÐAÐAÐAÍÌ
ÐSÑSÔSÐSÝŒH�Q‰KŒKˆKˆKˆKð	ð 	Ð"<Ð"<ð 
Œð Ý% d¤j°$´/À4Ä<ÑPÔPˆÝÐH¥ W¡¤ÐHÐH¸D¼JÐHÐHÑIÔIÐIØð 	Vð 	VˆAÝÐT�q”}Ô)ÐTÐT°aÔ6GÈ#Ñ6MÐTÐTÐTÐTÑUÔUÐUÐUð	Vð 	Vð 	×ÒÑÔÐÐÐr!   Ú__main__)r#   r$   r%   r   r&   r   r'   r   )N)rA   rB   rC   rD   r'   r   )rA   rB   rC   rD   r'   r   )Nrh   )ri   rB   rC   rD   rj   rk   r'   rl   )r'   rz   )r   Ú
__future__r   r…   Údataclassesr   ÚosÚpathlibr   r�   Útypingr   r   r   r	   ÚPILr
   r   r   r   r@   r^   rg   ry   r™   r   r    r!   r"   ú<module>r¡      s¦  ððð ð ð #Ð "Ð "Ð "Ð "Ð "à €€€Ø !Ð !Ð !Ð !Ð !Ð !Ø 	€	€	€	Ø Ð Ð Ð Ð Ð Ø 
€
€
€
Ø .Ð .Ð .Ð .Ð .Ð .Ð .Ð .Ð .Ð .Ð .Ð .à Ð Ð Ð Ð Ð ð,€	ð ð ð ñ ð €�˜dÐ#Ñ#Ô#ðð ð ð ð ñ ô ñ $Ô#ðð#ð #ð #ð #ð  (,ðð ð ð ð ðD (,ðð ð ð ð ð2 (,Øðð ð ð ð ð&ð ð ð ð: ˆzÒÐØ€D�F„F€F€F€Fð Ðr!   