o
    iv                  
   @   s  d dl Z d dlmZ d dlZd dlmZ d dl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mZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$ de%de&d	e'fd
dZ(G dd dZ)de*d	e)fddZ+	d'de,e de*de'd	edB fddZ-G dd dej.Z/G dd dej.Z0G dd dej.Z1G dd dej.Z2G dd  d ej.Z3G d!d" d"ej.Z4G d#d$ d$eZ5d	e5fd%d&Z6dS )(    N)BytesIO)override)IOComfyExtensionInputTypes)Hunyuan3DViewImageInputGenerateTypeResultFile3DSmartTopologyRequestTaskFile3DInputTextureEditTaskRequestTo3DPartTaskRequestTo3DProTaskCreateResponseTo3DProTaskQueryRequestTo3DProTaskRequestTo3DProTaskResultResponseTo3DUVTaskRequest)ApiEndpointbytesio_to_image_tensordownload_url_to_bytesiodownload_url_to_file_3ddownload_url_to_image_tensor"downscale_image_tensor_by_max_sidepoll_opsync_opupload_3d_model_to_comfyapiupload_image_to_comfyapivalidate_image_dimensionsvalidate_stringstatusbodyreturnc                 C   s6   | dkot |todt|di di ddv S )Ni  RequestLimitExceededResponseErrorCode )
isinstancedictstrget)r    r!    r,   =/mnt/c/Users/fbmor/ComfyUI/comfy_api_nodes/nodes_hunyuan3d.py_is_tencent_rate_limited&   s
   "r.   c                   @   sR   e Zd ZdZ				d
dejdejdB dejdB dejdB dejdB f
dd	ZdS )ObjZipResultobjtexturemetallicnormal	roughnessNr1   r2   r3   r4   r5   c                 C   s"   || _ || _|| _|| _|| _d S Nr0   )selfr1   r2   r3   r4   r5   r,   r,   r-   __init__1   s
   
zObjZipResult.__init__)NNNN)	__name__
__module____qualname__	__slots__r   File3Dr   Imager8   r,   r,   r,   r-   r/   .   s"    r/   urlc                    sn  t  }t| |I dH  |d t|s%|d ttj|dddS |d d}i }t|X}|	 D ]K}|
   drI||}q8t fddd	D r d
dd }tt ||dd}d}dddd D ]\}	}
||	r~|
} nqq|||< q8W d   n1 sw   Y  |du rtdttjt |dd|d|d|d|ddS )zThe Tencent API returns OBJ results as ZIP archives containing the .obj mesh, and texture images.

    When PBR is enabled, the ZIP may contain additional metallic, normal, and roughness maps
    identified by their filename suffixes.
    Nr   r1   )sourcefile_format)r1   z.objc                 3   s    | ]}  |V  qd S r6   )endswith).0extlowerr,   r-   	<genexpr>T   s    z/download_and_extract_obj_zip.<locals>.<genexpr>)z.pngz.jpgz.jpegz.bmpz.tiffz.webp.   RGB)moder2   r3   r4   r5   )	_metallic_normal
_roughnessz)ZIP archive does not contain an OBJ file.r0   )r   r   seekzipfile
is_zipfiler/   r   r=   ZipFilenamelistrF   rB   readanyrsplitr   items
ValueErrorr+   )r?   data	obj_bytestextureszfnamestemtensormatched_keysuffixkeyr,   rE   r-   download_and_extract_obj_zip@   sT   






rc   Tresponse_objs	file_typeraise_if_not_foundc                 C   s<   | D ]}|j  | kr|  S q|rtd| dd S )N'z)' file type is not found in the response.)TyperF   rX   )rd   re   rf   ir,   r,   r-   get_file_from_responsel   s   rj   c                   @   s@   e Zd Zedd Zededededededej	fd	d
Z
dS )TencentTextToModelNodec                 C   s*  t jddddt jjdddgdd	t jjd
ddddt jjdddddt jjdt jdt jjdddgt jdt jjdddgdt jjdddgt jdg gdt jjdd d d!t j	j
dd"d#gt jjd$d%t jjd&d%t jjd'd%t jjd(d%gt jjt jjt jjgddt jt jg d)d*d+d,d-
S ).Nrk   zHunyuan3D: Text to Modelapi node/3d/Tencent3Dmodel3.03.16The LowPoly option is unavailable for the `3.1` model.optionstooltippromptTr'   zSupports up to 1024 characters.	multilinedefaultrt   
face_count    ` rx   minmaxgenerate_typeNormalpbrFrx   LowPolypolygon_typetrianglequadrilateralrs   Geometryseedr   _Seed controls whether the node should re-run; results are non-deterministic regardless of seed.rx   r~   r   display_modecontrol_after_generatert   
model_filedisplay_nameGLBOBJtexture_imager   zgenerate_type.pbrry   )widgetsaw  
                (
                  $base := widgets.generate_type = "normal" ? 25 : widgets.generate_type = "lowpoly" ? 30 : 15;
                  $pbr := $lookup(widgets, "generate_type.pbr") ? 10 : 0;
                  $face := widgets.face_count != 500000 ? 10 : 0;
                  {"type":"usd","usd": ($base + $pbr + $face) * 0.02}
                )
                
depends_onexpr
node_idr   categoryessentials_categoryinputsoutputshiddenis_api_nodeis_output_nodeprice_badge)r   SchemaCombor   StringIntDynamicComboOptionBooleanNumberDisplaynumberOutput	File3DGLB	File3DOBJr>   Hiddenauth_token_comfy_orgapi_key_comfy_org	unique_id
PriceBadgePriceBadgeDependsclsr,   r,   r-   define_schemay   sd   "z$TencentTextToModelNode.define_schemarn   ru   ry   r   r   r"   c                    s  |}t |dddd |dkr|d  dkrtdt| td	d
dtt||||d |dd |dd dtdI d H }|j	rNtd|j	j
 d|j	j |j}t| tdd
dt|dtdd dI d H }	tt|	jdjI d H }
t| dtt|	jdjd|dI d H |
j|
jS )Nru   rI      
field_name
min_length
max_lengthrp   r   lowpoly>The LowPoly option is currently unavailable for the 3.1 model./proxy/tencent/hunyuan/3d-proPOSTpathmethodr   r   )ModelPrompt	FaceCountGenerateType	EnablePBRPolygonTyperesponse_modelrY   is_rate_limitedTask creation failed with code : #/proxy/tencent/hunyuan/3d-pro/queryJobIdc                 S      | j S r6   Statusrr,   r,   r-   <lambda>       z0TencentTextToModelNode.execute.<locals>.<lambda>rY   r   status_extractorr1   .glbglbtask_id)r   rF   rX   r   r   r   r   r+   r.   r%   r&   Messager   r   r   r   rc   rj   ResultFile3DsUrlr   
NodeOutputr   r1   r2   )r   rn   ru   ry   r   r   _responser   result
obj_resultr,   r,   r-   execute   sL   	




zTencentTextToModelNode.executeN)r9   r:   r;   classmethodr   r*   intr	   r   r   r   r,   r,   r,   r-   rk   w   s"    
Ark   c                   @   sh   e Zd Zedd Ze			ddedejdede	ded	ejdB d
ejdB dejdB de
jfddZdS )TencentImageToModelNodec                 C   sv  t jddddt jjdddgdd	t jd
t jjdddt jjdddt jjdddt jjdddddt jjdt jdt jjdddgt jdt jjdddgdt jjdddgt jdg gdt jjd d!d!d"t j	j
dd#d$gt jjd%d&t jjd'd&t jjd(d&t jjd)d&t jjd*d&t jjd+d&t jjd,d&gt jjt jjt jjgddt jt jg d-g d.d/d0d1d2
S )3Nr   zHunyuan3D: Image(s) to Modelrl   rm   rn   ro   rp   rq   rr   image
image_leftT)optionalimage_right
image_backry   rz   r{   r|   r}   r   r   r   Fr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   optional_metallicoptional_normaloptional_roughnessr   )r   r   r   )r   r   a3  
                (
                  $base := widgets.generate_type = "normal" ? 25 : widgets.generate_type = "lowpoly" ? 30 : 15;
                  $multiview := (
                    inputs.image_left.connected or inputs.image_right.connected or inputs.image_back.connected
                  ) ? 10 : 0;
                  $pbr := $lookup(widgets, "generate_type.pbr") ? 10 : 0;
                  $face := widgets.face_count != 500000 ? 10 : 0;
                  {"type":"usd","usd": ($base + $multiview + $pbr + $face) * 0.02}
                )
                r   r   )r   r   r   r   r>   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r,   r,   r-   r      sv   
%
z%TencentImageToModelNode.define_schemaNrn   r   ry   r   r   r   r   r   r"   c	                    s  |}	|dkr|d   dkrtdt|ddd g }
|||d D ]&\}}|d u r-q$t|ddd |
t|t| t|dd	d
ddI d H d q$t| t	dddt
t|||d t| t|dd	d
ddI d H |
rk|
nd |dd |dd dtdI d H }|jrtd|jj d|jj |j}t| t	dddt|dtdd dI d H }tt|jdjI d H }t| dtt|jdjd|dI d H |j|j|jd ur|jnt d d d d!|j!d ur|j!nt d d d d!|j"d ur|j"S t d d d d!S )"Nrp   r   r   r      )	min_width
min_height)leftrightbacki$  )max_sidez
image/webpi]n)	mime_typetotal_pixels)ViewTypeViewImageUrlr   r   r   r   r   )r   r   r   ImageUrlMultiViewImagesr   r   r   r   r   r   r   c                 S   r   r6   r   r   r,   r,   r-   r   {  r   z1TencentImageToModelNode.execute.<locals>.<lambda>r   r1   r   r   r   rI      )#rF   rX   r   rW   appendr   r   r   r   r   r   r   r+   r.   r%   r&   r   r   r   r   r   rc   rj   r   r   r   r   r   r1   r2   r3   torchzerosr4   r5   )r   rn   r   ry   r   r   r   r   r   r   multiview_imageskvr   r   r   r   r,   r,   r-   r   ;  s   










	zTencentImageToModelNode.execute)NNN)r9   r:   r;   r   r   r*   r   r>   r   r	   r   r   r   r,   r,   r,   r-   r      s4    
M	
r   c                   @   s>   e Zd Zedd Zh dZedejdede	j
fddZd	S )
TencentModelTo3DUVNodec                 C   s   t jddddt jjdt jt jt jt jgddt jjdd	d
dt j	j
dddgt jjddt jjddt jjddgt jjt jjt jjgdt jddd	S )Nr	  zHunyuan3D: Model to UVrl   zgPerform UV unfolding on a 3D model to generate UV texture. Input model must have less than 30000 faces.model_3dz!Input 3D model (GLB, OBJ, or FBX)typesrt   r   rI   r   r   Tr   r   r   r   FBXuv_imagez{"type":"usd","usd":0.2}r   	r   r   r   descriptionr   r   r   r   r   )r   r   	MultiTyper   r   r   	File3DFBX	File3DAnyr   r   r   r   r>   r   r   r   r   r   r   r,   r,   r-   r     s>   
z$TencentModelTo3DUVNode.define_schema>   fbxr   r1   r
  r   r"   c           	         s<  |}|j  }|| jvrtd| ddt| j dt| tdddtt	t
| t| ||I d H dd	td
I d H }|jrOtd|jj d|jj t| tdddt|jdtdd dI d H }t|jddd}|d uryt|jI d H ntdddd}ttt|jdjdI d H tt|jdjdI d H |S )NUnsupported file format: 'z'. Supported formats: , rH   z/proxy/tencent/hunyuan/3d-uvr   r   rh   r   Filer   r   r   z"/proxy/tencent/hunyuan/3d-uv/queryr   c                 S   r   r6   r   r   r,   r,   r-   r     r   z0TencentModelTo3DUVNode.execute.<locals>.<lambda>r   r  F)rf   rI   r  r1   r  )formatrF   SUPPORTED_FORMATSrX   joinsortedr   r   r   r   r   upperr   r.   r%   r&   r   r   r   r   r   rj   r   r   r   r  r  r   r   r   )	r   r
  r   r   rA   r   r   uv_image_filer  r,   r,   r-   r     sP   




zTencentModelTo3DUVNode.executeN)r9   r:   r;   r   r   r  r   r=   r   r   r   r   r,   r,   r,   r-   r	    s    
&r	  c                	   @   s:   e Zd Zedd Zedejdedede	j
fddZd	S )
Tencent3DTextureEditNodec                 C   s   t jddddt jjdt jt jgddt jjdd	d
ddt jjddddt jj	d	ddgt j
jddt jjddt jjddgt jjt jjt jjgd	t jddd	S )Nr!  zHunyuan3D: 3D Texture Editrl   zAAfter inputting the 3D model, perform 3D model texture redrawing.r
  zA3D model in FBX format. Model should have less than 100000 faces.r  ru   Tr'   z@Describes texture editing. Supports up to 1024 UTF-8 characters.rv   r   r   r   r   r   r   r   r   r   z{"type":"usd","usd": 0.6}r  r  )r   r   r  r   r  r  r   r   r   r   r   r   r   r>   r   r   r   r   r   r   r,   r,   r-   r     sN   
z&Tencent3DTextureEditNode.define_schemar
  ru   r   r"   c           	   	      s  |}|j  }|dkrtd| dt|dddd t| ||I d H }t| tdd	d
ttt	|
 |d|ddtdI d H }|jrQtd|jj d|jj t| tdd	d
t|jdtdd dI d H }ttt|jdjdI d H tt|jdjdI d H tt|jdjI d H S )Nr  r   '. Only FBX format is supported.ru   rI   r   r   z&/proxy/tencent/hunyuan/3d-texture-editr   r   r  T)r=   r   r   r   r   r   z,/proxy/tencent/hunyuan/3d-texture-edit/queryr   c                 S   r   r6   r   r   r,   r,   r-   r   5  r   z2Tencent3DTextureEditNode.execute.<locals>.<lambda>r   r   r1   r   )r  rF   rX   r   r   r   r   r   r   r   r  r.   r%   r&   r   r   r   r   r   r   r   r   rj   r   r   r   )	r   r
  ru   r   r   rA   	model_urlr   r   r,   r,   r-   r     s@   



z Tencent3DTextureEditNode.executeN)r9   r:   r;   r   r   r   r=   r*   r   r   r   r   r,   r,   r,   r-   r!    s    
-r!  c                   @   s6   e Zd Zedd Zedejdedej	fddZ
dS )	Tencent3DPartNodec                 C   sv   t jddddt jjdt jt jgddt jjdd	d	d
t jjdddgt jj	ddgt j
jt j
jt j
jgdt jddd	S )Nr$  zHunyuan3D: 3D Partrl   z[Automatically perform component identification and generation based on the model structure.r
  z@3D model in FBX format. Model should have less than 30000 faces.r  r   r   r   Tr   r   r  r   z{"type":"usd","usd":0.6}r  r  )r   r   r  r   r  r  r   r   r   r   r   r   r   r   r   r   r,   r,   r-   r   @  s:   

zTencent3DPartNode.define_schemar
  r   r"   c              	      s   |}|j  }|dkrtd| dt| ||I d H }t| tdddttt|	 |ddt
d	I d H }|jrGtd
|jj d|jj t| tdddt|jdtdd dI d H }ttt|jdjdI d H S )Nr  r  r"  z/proxy/tencent/hunyuan/3d-partr   r   r  r  r   r   r   z$/proxy/tencent/hunyuan/3d-part/queryr   c                 S   r   r6   r   r   r,   r,   r-   r     r   z+Tencent3DPartNode.execute.<locals>.<lambda>r   )r  rF   rX   r   r   r   r   r   r   r  r.   r%   r&   r   r   r   r   r   r   r   r   rj   r   r   )r   r
  r   r   rA   r#  r   r   r,   r,   r-   r   d  s6   

	

zTencent3DPartNode.executeN)r9   r:   r;   r   r   r   r=   r   r   r   r   r,   r,   r,   r-   r$  >  s    
#r$  c                   @   sF   e Zd Zedd ZddhZedejdedede	d	e
jf
d
dZdS )TencentSmartTopologyNodec                 C   s   t jddddt jjdt jt jt jgddt jjdd	d
gddt jjdg dddt jjddddt j	j
dddgt jjddgt jjt jjt jjgdt jddd	S )Nr%  zHunyuan3D: Smart Topologyrl   znPerform smart retopology on a 3D model. Supports GLB/OBJ formats; max 200MB; recommended for high-poly models.r
  zInput 3D model (GLB or OBJ)r  r   r   r   zSurface composition type.rr   
face_level)mediumhighlowzPolygon reduction level.r   r   r   Tr   r   r   r   z{"type":"usd","usd":1.0}r  r  )r   r   r  r   r   r   r  r   r   r   r   r   r   r   r   r   r   r   r,   r,   r-   r     sN   
z&TencentSmartTopologyNode.define_schemar   r1   r
  r   r&  r   r"   c           
   	      s   |}|j  }|| jvrtd| ddt| j dt| ||I d H }t| tdddt	t
t| |d||d	td
I d H }|jrStd|jj d|jj t| tdddt|jdtdd dI d H }	ttt|	jdjdI d H S )Nr  z'. Supported: r  rH   z(/proxy/tencent/hunyuan/3d-smart-topologyr   r   r  )r=   r   	FaceLevelr   zTask creation failed: [z] z./proxy/tencent/hunyuan/3d-smart-topology/queryr   c                 S   r   r6   r   r   r,   r,   r-   r     r   z2TencentSmartTopologyNode.execute.<locals>.<lambda>r   r1   )r  rF   r  rX   r  r  r   r   r   r   r   r   r  r.   r%   r&   r   r   r   r   r   r   r   r   rj   r   r   )
r   r
  r   r&  r   r   rA   r#  r   r   r,   r,   r-   r     s>   




z TencentSmartTopologyNode.executeN)r9   r:   r;   r   r   r  r   r=   r*   r   r   r   r   r,   r,   r,   r-   r%    s     
.r%  c                   @   s(   e Zd Zedeeej  fddZdS )TencentHunyuan3DExtensionr"   c                    s   t tttttgS r6   )rk   r   r	  r!  r$  r%  )r7   r,   r,   r-   get_node_list  s   z'TencentHunyuan3DExtension.get_node_listN)	r9   r:   r;   r   listtyper   	ComfyNoder,  r,   r,   r,   r-   r+    s    r+  c                      s   t  S r6   )r+  r,   r,   r,   r-   comfy_entrypoint  s   r0  )T)7rP   ior   r  typing_extensionsr   comfy_api.latestr   r   r   r   comfy_api_nodes.apis.hunyuan3dr   r	   r
   r   r   r   r   r   r   r   r   r   comfy_api_nodes.utilr   r   r   r   r   r   r   r   r   r   r   r   r   objectboolr.   r/   r*   rc   r-  rj   r/  rk   r   r	  r!  r$  r%  r+  r0  r,   r,   r,   r-   <module>   s:    88-
t !ZYH[