§
    yi½j%  ã                  ób  — 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m	Z	 ddl
mZmZmZmZ  eej        d¦  «        rej                             d¬¦  «         ej                             ej                             ej                             e¦  «        d	d	¦  «        ¦  «        Zej                             de¦  «         	 dd
lmZ dZn# e$ r dZY nw xY wh d£Z ed¬¦  «         G d„ d¦  «        ¦   «         Zd"d„Zd#d„Z d#d„Z!d$d%d„Z"d&d „Z#e$d!k    r ej%         e#¦   «         ¦  «         dS dS )'a®  
Asset & Apple Metal Shader Quality Assurance Linter for FreeExile.
Verifies:
1. Power-of-2 (2^n) texture dimensions (32, 64, 128, 256, 512, 1024, 2048).
2. RGBA Alpha Channel fringing and dirty border artifacts.
3. Apple Metal Compute Shader struct alignment (SIMD16 / float4 16-byte bounds).
4. VRAM mobile memory footprint budgeting (budget <= 80MB per zone).
Adheres to Clean Architecture, Zero-Drift, and <= 350 lines limit.
é    )ÚannotationsN)Ú	dataclassÚfield)ÚListÚDictÚTupleÚSetÚreconfigureúutf-8)Úencodingz..)ÚImageTF>	   é   é   é   é   é   é   é    é@   é€   )Úslotsc                  ó    — e Zd ZU dZded<    ee¬¦  «        Zded<    ee¬¦  «        Zded<   dZ	d	ed
<    ee¬¦  «        Z
ded<   dZded<   dS )ÚAssetQaReportr   ÚintÚtotal_images_scanned)Údefault_factoryz	List[str]Únon_power_of_twoÚalpha_fringing_warningsg        ÚfloatÚtotal_estimated_vram_mbÚmetal_alignment_warningsTÚboolÚis_compliantN)Ú__name__Ú
__module__Ú__qualname__r   Ú__annotations__r   Úlistr   r   r    r!   r#   © ó    ú9C:\Projects\FreeExile\tools\lint\verify_asset_pipeline.pyr   r   #   s¤   € € € € € € à !ÐÐ!Ð!Ð!Ñ!Ø"' %¸Ð"=Ñ"=Ô"=ÐÐ=Ð=Ð=Ñ=Ø).¨¸tÐ)DÑ)DÔ)DÐÐDÐDÐDÑDØ%(ÐÐ(Ð(Ð(Ñ(Ø*/¨%ÀÐ*EÑ*EÔ*EÐÐEÐEÐEÑEØ€LÐÐÐÑÐÐr*   r   Úvalr   Úreturnr"   c                ó8   — | t           v p| dk    o| | dz
  z  dk    S )Nr   é   )ÚPOWER_OF_TWO_VALUES)r,   s    r+   Úis_power_of_twor1   -   s)   € ØÕ%Ð%ÐM¨#°ª'Ð*L°s¸cÀA¹g±È1Ò6LÐMr*   Ú	file_pathÚstrÚreportÚNonec           
     ó„  — t           sdS 	 t          j        | ¦  «        5 }|j        \  }}|xj        dz  c_        t          |¦  «        rt          |¦  «        sF|j                             t          j	         
                    | t          ¦  «        › d|› d|› d�¦  «         ||z  dz  }|xj        |dz  z  c_        |j        dk    rÌ|d	k    rÆ|d	k    rÀd
}|                     ¦   «         }t          d|t!          d|dz  ¦  «        ¦  «        D ]E}d|dz
  fD ]7}	|||	f         \  }
}}}d|cxk     rdk     rn Œ!|
dk     r|dk     r
|dk     rd} nŒ8|r nŒF|r@|j                             t          j	         
                    | t          ¦  «        › d�¦  «         ddd¦  «         dS # 1 swxY w Y   dS # t$          $ r}Y d}~dS d}~ww xY w)zDInspects image dimensions, alpha channel, and VRAM memory footprint.Nr/   z: Úxz
 (Not 2^n)é   i   ÚRGBAr   Fr   é
   éÈ   é   Tz,: Semi-transparent dark fringing on borders.)ÚHAS_PILr   ÚopenÚsizer   r1   r   ÚappendÚosÚpathÚrelpathÚPROJECT_ROOTr    ÚmodeÚloadÚrangeÚmaxr   Ú	Exception)r2   r4   ÚimgÚwÚhÚ
vram_bytesÚsample_dirtyÚpixelsr7   ÚyÚrÚgÚbÚaÚexcs                  r+   Úaudit_image_filerV   1   ss  € åð Øˆð"ÝŒZ˜	Ñ"Ô"ð 	 cØ”8‰DˆAˆqØÐ'Ô'¨1Ñ,Ð'Ô'õ # 1Ñ%Ô%ð q­_¸QÑ-?Ô-?ð qØÔ'×.Ò.µ"´'·/²/À)Í\Ñ2ZÔ2ZÐ/oÐ/oÐ^_Ð/oÐ/oÐbcÐ/oÐ/oÐ/oÑpÔpÐpð ˜Q™ ™ˆJØÐ*Ô*¨j¸KÑ.HÑHÐ*Ô*ð Œx˜6Ò!Ð! a¨2¢g g°!°r²'°'à$�ØŸš™œ�å˜q !¥S¨¨A°©G¡_¤_Ñ5Ô5ð ð �AØ  Q¡˜Zð "ð "˜Ø%+¨A¨q¨D¤\™
˜˜1˜a Ø˜q˜;˜;š;˜; 3š;˜;˜;˜;˜;¨1¨rª6¨6°a¸"²f°fÀÀRÂÀØ+/˜LØ!˜EøØ#ð Ø˜ðð  ð ØÔ2×9Ò9Ýœ7Ÿ?š?¨9µlÑCÔCÐqÐqÐqñô ð ð9	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	øõ@ ð ð ð Øˆˆˆˆˆøøøøðøøøs5   ‹F* ŸE1FÆF* ÆF!Æ!F* Æ$F!Æ%F* Æ*
F?Æ:F?c                óÀ  — 	 t          | ddd¬¦  «        5 }|                     ¦   «         }ddd¦  «         n# 1 swxY w Y   t          j        d|t          j        ¦  «        }|D ]i\  }}d|v r`d|vr\d	|vrXt          j        d
|¦  «        rC|j                             t          j	         
                    | t          ¦  «        › d|› d�¦  «         ŒjdS # t          $ r Y dS w xY w)zLChecks Metal shader structs for unpadded float3 or misaligned SIMD16 bounds.rQ   r   Úignore)r   ÚerrorsNz&struct\s+([A-Za-z0-9_]+)\s*\{([^}]+)\}Úfloat3Úpacked_float3Úsimd_float3z0float3\s+[A-Za-z0-9_]+;\s*float\s+[A-Za-z0-9_]+;z
: struct 'z€' has unpadded 'float3' followed by 'float'. On Apple Silicon Metal, float3 occupies 16 bytes. Use simd_float3 or packed_float3.)r>   ÚreadÚreÚfindallÚ	MULTILINEÚsearchr!   r@   rA   rB   rC   rD   rI   )r2   r4   ÚfÚcodeÚstruct_matchesÚsnameÚsbodys          r+   Úaudit_metal_shader_coderg   [   s]  € ðÝ�)˜S¨7¸8ÐDÑDÔDð 	ÈØ—6’6‘8”8ˆDð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	õ œÐ$MÈtÕUWÔUaÑbÔbˆØ*ð 	ð 	‰LˆE�5à˜5Ð Ð  _¸EÐ%AÐ%AÀmÐ[`ÐF`ÐF`Ý”9ÐPÐRWÑXÔXð ØÔ3×:Ò:Ýœ7Ÿ?š?¨9µlÑCÔCð nð nÈuð nð nð nñô ð øð		ð 	øõ ð ð ð Øˆˆðøøøs-   ‚C •6ªC ¶:ºC ½:¾BC Ã
CÃCÚ
assets_dirÚshaders_dirúOptional[str]c           	     óT  — t          ¦   «         }t          j                             | ¦  «        rut          j        | ¦  «        D ]`\  }}}|D ]W}|                     ¦   «                              d¦  «        r.t          t          j                             ||¦  «        |¦  «         ŒXŒa|r|gnIt          j                             t          d¦  «        t          j                             t          d¦  «        g}|D ]–}t          j                             |¦  «        rut          j        |¦  «        D ]`\  }}}|D ]W}|                     ¦   «                              d¦  «        r.t          t          j                             ||¦  «        |¦  «         ŒXŒaŒ—t          |j        ¦  «        dk    |_        |S )N)z.pngz.webpz.jpgz.tgaÚclientÚ
server_cpp)z.metalz.hz.hppz.cppr   )r   rA   rB   ÚexistsÚwalkÚlowerÚendswithrV   ÚjoinrD   rg   Úlenr!   r#   )	rh   ri   r4   ÚrootÚ_ÚfilesÚfileÚtarget_shader_dirsÚsdirs	            r+   Úrun_asset_qarz   o   sœ  € Ý‰_Œ_€Fõ 
„w‡~‚~�jÑ!Ô!ð GÝ œg jÑ1Ô1ð 	Gð 	G‰NˆD�!�UØð Gð G�Ø—:’:‘<”<×(Ò(Ð)JÑKÔKð GÝ$¥R¤W§\¢\°$¸Ñ%=Ô%=¸vÑFÔFÐFøðGð
 +6ð ˜+˜˜Ý
Œ�Š•\ 8Ñ,Ô,Ý
Œ�Š•\ <Ñ0Ô0ð<Ðð #ð Rð RˆÝŒ7�>Š>˜$ÑÔð 	RÝ"$¤'¨$¡-¤-ð Rð R‘��a˜Ø!ð Rð R�DØ—z’z‘|”|×,Ò,Ð-MÑNÔNð RÝ/µ´·²¸TÀ4Ñ0HÔ0HÈ&ÑQÔQÐQøðRøõ ˜vÔ>Ñ?Ô?À1ÒD€FÔØ€Mr*   c                 ó¶  — t          j        d¬¦  «        } |                      dt          j                             t          d¦  «        d¬¦  «         |                      ddd	¬
¦  «         |                      ¦   «         }t          |j	        ¦  «        }t          d¦  «         t          d¦  «         t          d¦  «         t          d|j        rdnd› �¦  «         t          d|j        › �¦  «         t          d|j        d›d�¦  «         t          dt          |j        ¦  «        › �¦  «         t          dt          |j        ¦  «        › �¦  «         t          dt          |j        ¦  «        › �¦  «         t          d¦  «         |j        r3t          d¦  «         |j        d d…         D ]}t          d|› �¦  «         Œ|j        r3t          d¦  «         |j        d d…         D ]}t          d|› �¦  «         Œ|j        r<t          d¦  «         |j        D ]}t          d|› �¦  «         Œt          d¦  «         dS t          d¦  «         t          d¦  «         d S )!NzAsset & Metal Shader QA Linter.)Údescriptionz--assets-dirÚassetszAssets directory.)ÚdefaultÚhelpz--strictÚ
store_truez,Fail if non-power-of-two textures are found.)Úactionr   zD====================================================================z8 FREEEXILE ASSET PIPELINE & APPLE METAL SHADER QA AUDIT zStatus:               z[PASS]z[FAIL]zImages Scanned:       zEstimated Total VRAM: z.2fz MBzNon-Power-of-2 (2^n): zAlpha Fringing Warns: zMetal Alignment Warns:zD--------------------------------------------------------------------z+[WARN] NON-POWER-OF-TWO TEXTURES (First 5):é   z   * z*[WARN] ALPHA FRINGING ARTIFACTS (First 5):z1[ERROR] METAL SHADER STRUCT ALIGNMENT VIOLATIONS:z   ! r/   zDSUCCESS: Assets and Metal Shaders meet 120Hz Apple Silicon standard.r   )ÚargparseÚArgumentParserÚadd_argumentrA   rB   rr   rD   Ú
parse_argsrz   rh   Úprintr#   r   r    rs   r   r   r!   )ÚparserÚargsr4   Úitems       r+   Úmainr‹   ‰   s{  € ÝÔ$Ð1RÐSÑSÔS€FØ
×Ò˜µ´·²½\È8Ñ0TÔ0TÐ[nÐÑoÔoÐoØ
×Ò˜
¨<Ð>lÐÑmÔmÐmØ×ÒÑÔ€Då˜$œ/Ñ*Ô*€Få	ˆ(�O„O€OÝ	Ð
DÑEÔEÐEÝ	ˆ(�O„O€OÝ	Ð
R¨vÔ/BÐ#P 8 8ÈÐ
RÐ
RÑSÔSÐSÝ	Ð
@ 6Ô#>Ð
@Ð
@ÑAÔAÐAÝ	Ð
J 6Ô#AÐ
JÐ
JÐ
JÐ
JÑKÔKÐKÝ	Ð
A¥3 vÔ'>Ñ#?Ô#?Ð
AÐ
AÑBÔBÐBÝ	Ð
H¥3 vÔ'EÑ#FÔ#FÐ
HÐ
HÑIÔIÐIÝ	Ð
I¥3 vÔ'FÑ#GÔ#GÐ
IÐ
IÑJÔJÐJÝ	ˆ(�O„O€OàÔð "ÝÐ;Ñ<Ô<Ð<ØÔ+¨B¨Q¨BÔ/ð 	"ð 	"ˆDÝ�.˜$�.�.Ñ!Ô!Ð!Ð!àÔ%ð "ÝÐ:Ñ;Ô;Ð;ØÔ2°2°A°2Ô6ð 	"ð 	"ˆDÝ�.˜$�.�.Ñ!Ô!Ð!Ð!àÔ&ð ÝÐAÑBÔBÐBØÔ3ð 	"ð 	"ˆDÝ�.˜$�.�.Ñ!Ô!Ð!Ð!Ýˆh‰ŒˆØˆqå	ˆ(�O„O€OÝ	Ð
PÑQÔQÐQØˆ1r*   Ú__main__)r,   r   r-   r"   )r2   r3   r4   r   r-   r5   )N)rh   r3   ri   rj   r-   r   )r-   r   )&Ú__doc__Ú
__future__r   ÚsysrA   r^   rƒ   Údataclassesr   r   Útypingr   r   r   r	   ÚhasattrÚstdoutr
   rB   Úabspathrr   ÚdirnameÚ__file__rD   ÚinsertÚPILr   r=   ÚImportErrorr0   r   r1   rV   rg   rz   r‹   r$   Úexitr)   r*   r+   ú<module>r›      s0  ððð ð #Ð "Ð "Ð "Ð "Ð "Ø 
€
€
€
Ø 	€	€	€	Ø 	€	€	€	Ø €€€Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )à
€7ˆ3Œ:�}Ñ%Ô%ð -Ø„J×Ò GÐÑ,Ô,Ð,àŒw�Š˜rœwŸ|š|¨B¬G¯OªO¸HÑ,EÔ,EÀtÈTÑRÔRÑSÔS€Ø „‡‚��<Ñ  Ô  Ð  ðØÐÐÐÐÐØ€G€GøØð ð ð Ø€G€G€Gðøøøð DÐCÐCÐ ð €�ÐÑÔðð ð ð ð ñ ô ñ ÔððNð Nð Nð Nð'ð 'ð 'ð 'ðTð ð ð ð(ð ð ð ð ð4&ð &ð &ð &ðR ˆzÒÐØ€C„HˆTˆT‰VŒVÑÔÐÐÐð Ðs   ÃC
 Ã
CÃC