
    +jF                     (   d Z ddlmZ ddlZddlmc 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  ej        d          Zg dZd Zd	 Zd
 ZddZd Z G d dej                  Z G d dej                  Z G d de          ZdefdZdS )zSCAIL / SCAIL-2 nodes: the WanSCAILToVideo conditioning node and the SAM3
preprocessing that turns video tracks into the bundle the SCAIL-2 model consumes.    )overrideN)ComfyExtensionio)unpack_masksSAM3_TRACK_DATA))        r         ?)r	   r   r   )r   r	   r   )r	   r   r	   )r   r	   r	   )r	   r	   r   c                 Z    | d         }||j         d         dk    rd S t          |          S )Npacked_masks   r   )shaper   )
track_datapackeds     8/home/wildlama/comfy/ComfyUI/comfy_extras/nodes_scail.py_unpackr      s4    'F~aA--t    c                    | d                                          }|j        d         |j        d         }}||z  }t          j        ||j        |j                                      d|          }|                    d                              d          }||z                      d          |z  }||z  	                                ||z  	                                fS )	Nr   devicedtyper   )r   r   dim)min)
floatr   torcharanger   r   viewsumclamp_tolist)
masks_boolfirstHWn_pixelsgrid_xareacxs           r   _first_frame_cx_arear+   %   s    qM!!E;r?EKOqA1uH\!ELDDDII!QOOF999""))a)00D
&.		(		+	+d	2BF??th668888r   c                     t          |           }| d         }||sd |d<   d|v rg |d<   |S |d d |f                                         |d<   |                     d          fd|D             |d<   |S )Nr   scoresc                 F    g | ]}|t                    k     |         S  )len).0ir-   s     r   
<listcomp>z&_subset_track_data.<locals>.<listcomp>:   s(    KKKq1s6{{?????r   )dict
contiguousget)r   obj_indicesoutr   r-   s       @r   _subset_track_datar9   /   s    
z

C'F~[~"Ns??CM
 K0;;==C^^H%%FKKKKKKKKHJr   blackc                     | d         }| d         \  }}t           j                                        }t           j                                        }|                    d          rdnd}||j        d         dk    rc||                     dd          n|j        d         }t          j        |||d	||
          }	|d         |d         |d         c|	d<   |	d<   |	d<   |	S |j        d         |j        d         }
}t          j	        d t          |
          D             ||
          }t          |                    |                                                    }|j        d         |j        d         }}t          j        |                    ||
z  d||          ||fd                              ||
||          dk    }|                    d          }|                    t          j                                      d          }||         }t          j	        |||j        
                              dddd	          }t          j        |                    d          ||                    |                    S )Nr   	orig_sizewhite)r	   r	   r	   )r   r   r   r   r   n_frames   r      ).r   ).r   ).r@   c                 R    g | ]$}t           |t          t                     z           %S r/   )DEFAULT_PALETTEr0   r1   r2   s     r   r3   z)_render_colored_masks.<locals>.<listcomp>K   s*    IIIqS111	2IIIr   r   r   nearestsizemodeg      ?r   )comfymodel_managementintermediate_deviceintermediate_dtype
startswithr   r6   r   emptytensorranger   tor   Finterpolater   anyuint8argmaxr   where	unsqueeze	expand_as)r   
backgroundr   r%   r&   r   r   bg_rgbTr8   N_objcolors
masks_fullHmWmany_maskobj_idx_mapcolor_overlay	bg_tensors                      r   _render_colored_masksre   >   s[   'Fk"DAq#7799F"5577E * 5 5g > >S__OF~aA---3^JNN:q)))ak!Q1V5AAA06q	6!9fQi-FS[#f+
|AQuA\IIE%LLIIIU  F fii//006688Jb!:#3B#7BE	1b"--QF  
d1eQS!J ~~!~$$H--,,333::K;'MVF-:MNNNSSTUWXZ[]^__I;x))"--}i>Q>QR_>`>`aaar   c           
      |   | j         \  }}}}d}|                     dd                                          }|ddddf         |k                                    }|ddddf         |k                                    }|ddddf         |k                                    }	d|z
  d|z
  d|	z
  }}}
t          j        ||z  |	z  ||z  |z  |
|z  |z  |
|z  |	z  ||z  |z  ||z  |	z  |
|z  |	z  gd          }||}}t          d          D ]}|dz   dz  }|dz   dz  }t          j        j                            |||fd	
          }|dz
  dz  dz   }t          j        |dd         	                    dddd          |dd         gd          }|
                    |d||          }|                    d          S )zColored RGB mask (T, H, W, 3) in [0, 1] -> SCAIL-2 28-channel binary latent
    (1, T_lat, 28, H_lat, W_lat). 7 per-color binary channels (white/r/g/b/y/m/c)
    threshold-extracted at 225/255, 8x spatial downsample, 4-frame temporal stacking.g<<<<<<?r   r   Nr   r@   r?   r   r)   rE         )r   movedimr   r   catrO   nn
functionalrR   repeatr   rW   )	rgb_videor[   r%   r&   _
_ON_THRESHmaskRGBnRnGnB
binary_7chH_latW_latT_latentpaddedr8   s                      r   _extract_mask_to_28chr}   Z   s    JAq!QJR##))++D	aaa1f
	"))++A	aaa1f
	"))++A	aaa1f
	"))++AQAq1uBB	A		B
Q
R!	A
	B

Q
   J a5E1XX ! !q q $005%.W]0^^JA!|aHY
2A2--aAq99:abb>JPQRRRF
++hE5
1
1C==r   c                   P    e Zd Zed             Ze	 	 ddej        fd            ZdS )WanSCAILToVideoc                    t          j        ddt           j                            d          t           j                            d          t           j                            d          t           j                            dddt          j        d	          t           j                            d
ddt          j        d	          t           j                            dddt          j        d	          t           j                            dddd          t           j                            ddd          t           j                            ddd          t           j	                            dddd          t           j
                            dddd d!d"#          t           j
                            d$dddd!d%#          t           j
                            d&dddd!d'#          t           j                            d(dd)          t           j                            d*dd+          t           j                            d,dd-          t           j                            d.d/d/t          j        dd0#          t           j                            d1d2dt          j        dd3#          t           j                            d4dd5          gt           j                            d6          t           j                            d6          t           j                            d7d89          t           j                            d.d:9          gd;          S )<Nr   zmodel/conditioning/video_modelspositivenegativevaewidthi       )defaultr   maxstepheighti  lengthQ   r   rg   
batch_sizei   )r   r   r   
pose_videoTz^Video used for pose conditioning. Will be downscaled to half the resolution of the main video.optionaltooltippose_video_maskzXSCAIL-2 only. Colored per-identity SAM3 mask video at the same resolution as pose_video.replacement_modeFzSCAIL-2 only. False = Animation Mode (pose_video_mask should have black background). True = Replacement Mode (pose_video_mask should have white background).)r   r   r   pose_strengthr	   r   g      $@g{Gz?zStrength of the pose latent.)r   r   r   r   r   
pose_startz$Start step of the pose conditioning.pose_endz"End step of the pose conditioning.reference_imagezGReference image, for multiple references composite all on single image.reference_image_maskzOSCAIL-2 only. Colored reference mask at the same resolution as reference_image.clip_vision_outputz\CLIP vision features for conditioning. Model is trained with stretch resize to aspect ratio.video_frame_offsetr   zgCumulative output frame this chunk begins at. Wire from the previous chunk's video_frame_offset output.previous_frame_count   z`Tail frames of previous_frames to anchor. SCAIL-2 trained at 5 (81-frame chunks, 76-frame step).previous_framesz}SCAIL-2 only. Full decoded output of the previous chunk. Only the last previous_frame_count are used as the extension anchor.)display_namelatentz$Empty latent of the generation size.)r   r   z3Adjusted offset + length. Wire into the next chunk.)node_idcategoryinputsoutputsis_experimental)r   SchemaConditioningInputVaeIntnodesMAX_RESOLUTIONImageBooleanFloatClipVisionOutputOutputLatentclss    r   define_schemazWanSCAILToVideo.define_schemaz   s   y%6%%j11%%j11U##Wcru?SZ\]]Xs@T[]^^Xrqe>RYZ[[\1!FF|d  Ee  f  f04  Jd  e  e
  !3UT  \z   {  {$UY  dB  C  C|ScsQU  `F  G  Gz3CSt  ^B  C  C04  JS  T  T5  O`  a  a#))*>  Xv)  w  w11!I]de  pY  Z  Z3QA5K_fg  rT  U  U04  JI  J  J', &&J&??&&J&??	  h@f gg+?I~	 !=
 
 
 	
r   FNreturnc                    t          j        |d|dz
  dz  dz   |dz  |dz  gt          j                                                  }d }| }t          j        |d|i          }t          j        |d|i          }d }|<|j        d         dk    r+|| d          }||j        d         z  }t          d|          }d }|t          j	        
                    |d d                             dd          ||d	d
                              dd          }|r|t          j	        
                    |d d                             dd          ||dd
                              dd          }|dd df                             dd          j        dk                        |j                  }||z  }|                    |d d d d d d d df                   }|4t          j        |d|gid          }t          j        |d|gid          }|.t          j        |d|i          }t          j        |d|i          }||j        d         |k    rd }n
||d          }||j        d         |k    rd }n
||d          }d ||fD             }|rAt!          t!          |          |          dz
  dz  dz  dz   }|
|d |         }|
|d |         }|t          j	        
                    |d |                             dd          |dz  |dz  dd
                              dd          }|                    |d d d d d d d df                   |z  }t          j        |d|i|	|
          }t          j        |d|i|	|
          }|t          j	        
                    |d |                             dd          |dz  |dz  dd
                              dd          }t%          |          }t          j        |d|i          }t          j        |d|i          }|t          j	        
                    |d d                             dd          ||d	d
                              dd          } t%          |           }!t          j        d|j        d         d|!j        d         |!j        d         f|!j        |!j                  }"t          j        |!|"gd          }#t          j        |d|#i          }t          j        |d|#i          }|"t          j	        
                    |                    dd          ||d	d
                              dd          }$|                    |$d d d d d d d df                   }%t!          |%j        d         |j        d                   }&|%d d d d d |&f                             |j                  |d d d d d |&f<   t          j        dd|j        d         |j        d         |j        d         f|j        |j                  }d|d d d d d |&f<   d|i}'|||'d <   t-          j        |||'||z             S )!N   r   rg      )r   ref_mask_flagr   r   bicubiccenterznearest-exact.r?   T)r   keepdimg?reference_latents)appendr   c                 ,    g | ]}||j         d         S )Nr   )r   )r1   vs     r   r3   z+WanSCAILToVideo.execute.<locals>.<listcomp>   s    QQQQ1=agaj===r   r@   r)   pose_video_latentdriving_mask_28chrh   r   r   r   ref_mask_28chr   samples
noise_mask)r   zerosrH   rI   rJ   node_helpersconditioning_set_valuesr   r   utilscommon_upscaleri   valuesrP   r   encoder   +conditioning_set_values_with_timestep_ranger}   r   rj   onesr   
NodeOutput)(r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   prev_trimmed
ref_latentrmis_chartsT_keptr   mask_video_hwr   ref_mask_hwref_mask_1fr   r   pfprev_latentprev_latent_frames
out_latents(                                           r   executezWanSCAILToVideo.execute   s4    j"
q/@A.EvQR{TY]^T^_hmh~  iS  iS  iU  iU  V  V  V
,,7?TaBbcc7?TaBbcc&?+@+Ca+G+G*,@+@+A+ABL,"4Q"77!$Q(:!;!;
&#k88!9L9T9TUWYZ9[9[]bdjluw  A  A  I  I  JK  MO  P  PO <$8$D[//0DRaR0H0P0PQSUV0W0WY^`fhw  zB  C  C  K  K  LM  OQ  R  Rc2A2g;??r4?@@G#MQQRaRghh"1G";OAAAqqq!!!RaRK$@AAJ!#;HGZ]g\hFirvwwwH#;HGZ]g\hFirvwwwH)#;HG[]oFpqqH#;HG[]oFpqqH!"&888!

'(:(;(;<
&$Q'+==="&"12D2E2E"F RQ:"?QQQ 	;3r77F++a/A5:Q>F%'0
*"1'6'":!33Jww4G4O4OPRTU4V4VX]abXbdjnodoqw  zB  C  C  K  K  LM  OQ  R  RJ #

:aaaAAArrk+B C Cm S#OPX[n  qB  [C  EO  QY  Z  ZH#OPX[n  qB  [C  EO  QY  Z  ZH&!K66ww7O7W7WXZ\]7^7^`eij`jlrvwlwy  BJ  K  K  S  S  TU  WY  Z  ZM 5m D D#;HGZ\mFnooH#;HGZ\mFnooH++445I"1"5M5U5UVXZ[5\5\^cekmv  yA  B  B  J  J  KL  NP  Q  QK/<<KKFLOR9J29NP[PabdPe foz  pB  JU  J[  \  \  \E!I{E&:BBBM#;HXeFfggH#;HXeFfggH#++L,@,@Q,G,GPVXackllttuvxz{{B**R111aaa!_55K"%k&7&:FLO"L"L0;AAAqqqBUCUBU<U0V0Y0YZ`Zf0g0gF111aaa,,,,-Q6<?FL<Lfl[]N^$_hnhu  ~D  ~J  K  K  KJ47Jqqq!!!00001(
!'1J|$}Xx=ORX=XYYYr   )FNNNNNN)__name__
__module____qualname__classmethodr   r   r   r   r/   r   r   r   r   y   sx         
  
 [ 
D  MQQUUZ UZZ\ZgUZ UZ UZ [UZ UZ UZr   r   c                   @    e Zd ZdZed             Zedd            ZdS )SCAIL2ColoredMaska  Render SAM3 tracks for the driving pose video and (optionally) the reference
    image into the two colored masks WanSCAILToVideo consumes. Shared `sort_by`
    across both outputs guarantees identity K maps to the same color on both
    sides, for multi-person workflow consistency.
    reference_image_mask is always rendered black-bg (model convention)
    pose_video_mask bg follows replacement_mode: black = Animation Mode, white = Replacement Mode
    c                    t          j        dddt                              dd          t                              ddd	
          t           j                            ddd          t           j                            dg ddd          t           j                            ddd          gt           j                            d          t           j                            d          gd          S )Nr   zCreate SCAIL-2 Colored Maskzconditioning/video_models/scaildriving_track_datazWSAM3 track of the driving pose video. Will be rendered into the pose_video_mask output.)r   ref_track_dataTz"SAM3 track of the reference image.r   object_indices z~Comma-separated list of person indices to include (e.g. '0,2,3'). Applied to both reference and pose video masks. Empty = all.)r   r   sort_by)noneleft_to_rightr)   r   aD  Order in which palette colors are assigned to the tracked objects (applied to both reference and pose video so each identity keeps the same color). left_to_right = leftmost object (by first-frame centroid) gets the first color; area = biggest object (by first-frame mask area) gets the first color; none = keep SAM3's order.)optionsr   r   r   FzFalse = Animation Mode (pose_video_mask has black background, reference_image_mask has white background). True = Replacement Mode (pose_video_mask has white background, reference_image_mask has black background).r   r   )r   r   r   r   r   r   )	r   r   SAM3TrackDatar   StringCombor   r   r   r   s    r   r   zSCAIL2ColoredMask.define_schema   s   y'66##$8  C\#  ]  ]##$4t,P $ R R	 0" )i   j jy2S2S2S]l (n  o o
  !3U*V ! W W  122 677 !)
 
 
 	
r   Nc                    fd} ||          }t          ||rdnd          }|rdnd}	| ||          }
t          |
|	          }ni|d         \  }}|	dk    rdnd}t          j        d||df|t          j                                        t          j                                        	          }t          j        ||          S )
Nc                 4   t          |           }	dk    r|t          |          \  	dk    r/t          t          t	                              fd          }n.t          t          t	                              fd          }t          | |          }                                 rcd                     d          D             }|                     d          }||j	        d	         nd
fd|D             }t          | |          } | S )Nr   r   c                     |          S Nr/   )r2   r*   s    r   <lambda>z:SCAIL2ColoredMask.execute.<locals>._prep.<locals>.<lambda>  s    A r   )keyc                     |           S r   r/   )r2   r)   s    r   r   z:SCAIL2ColoredMask.execute.<locals>._prep.<locals>.<lambda>!  s    DG8 r   c                     g | ]I}|                                                                 (t          |                                           JS r/   )stripisdigitintrC   s     r   r3   z<SCAIL2ColoredMask.execute.<locals>._prep.<locals>.<listcomp>$  sD    dddaPQPWPWPYPYPaPaPcPcd3qwwyy>>dddr   ,r   r   r   c                 4    g | ]}d |cxk    rk     n n|S )r   r/   )r1   r2   n_objs     r   r3   z<SCAIL2ColoredMask.execute.<locals>._prep.<locals>.<listcomp>'  s.    @@@a%1r   )
r   r+   sortedrO   r0   r9   r   splitr6   r   )
tdr#   orderindicesr   r)   r*   r   r   r   s
        @@@r   _prepz(SCAIL2ColoredMask.execute.<locals>._prep  s#    J&  Z%;/
;;Do--"5R>>GGGEE"5T#3#39K9K9K9KLLLE'E22##%% 5dd>3G3G3L3Lddd//+1+=Q1@@@@g@@@'G44Ir   r=   r:   r<   r	   r   r   r?   r   )	re   r   fullrH   rI   rJ   rK   r   r   )r   r   r   r   r   r   r  drv
mask_videoref_bgrefr   r%   r&   
fill_values     ``           r   r   zSCAIL2ColoredMask.execute  s   	 	 	 	 	 	" e&''*3;K0XQXYY
,9'%%''C#8f#E#E  {#DAq &' 1 1sJ#(:q!QlJuOeOyOyO{O{  DI  DZ  Dm  Dm  Do  Do  $p  $p  $p }Z)=>>>r   r   )r   r   r   __doc__r   r   r   r/   r   r   r   r      sY          
 
 [
0 ? ? ? [? ? ?r   r   c                   L    e Zd Zedeeej                          fd            ZdS )SCAILExtensionr   c                 "   K   t           t          gS r   )r   r   )selfs    r   get_node_listzSCAILExtension.get_node_list<  s       
 	
r   N)	r   r   r   r   listtyper   	ComfyNoder  r/   r   r   r  r  ;  sE        
T$r|*<%= 
 
 
 X
 
 
r   r  r   c                  "   K   t                      S r   )r  r/   r   r   comfy_entrypointr  D  s      r   )r:   )r	  typing_extensionsr   r   torch.nn.functionalrk   rl   rQ   r   r   comfy.model_managementrH   comfy.utilscomfy_api.latestr   r   comfy.ldm.sam3.trackerr   Customr   rB   r   r+   r9   re   r}   r  r   r   r  r  r/   r   r   <module>r     s  U U ' & & & & &                        / / / / / / / / / / / / / /	+,,       9 9 9  b b b b8  >zZ zZ zZ zZ zZbl zZ zZ zZzB? B? B? B? B? B? B? B?J
 
 
 
 
^ 
 
 
      r   