o
    i^                  	   @   sv  d dl mZ d dl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mZmZmZmZmZ d dlmZmZmZmZmZ dedefddZ		d"d
e ej! dede"d	B dej#fddZ$G dd dej!Z%G dd dej!Z&G dd dej!Z'G dd dej!Z(G dd dej!Z)G dd dej!Z*G dd dej!Z+G dd dej!Z,G dd deZ-de-fd d!Z.d	S )#    )override)IOComfyExtensionInput)TripoAnimateRetargetRequestTripoAnimateRigRequestTripoConvertModelRequestTripoFileEmptyReferenceTripoFileReferenceTripoImageToModelRequestTripoModelVersionTripoMultiviewToModelRequestTripoOrientationTripoRefineModelRequest
TripoStyleTripoTaskResponseTripoTaskStatusTripoTaskTypeTripoTextToModelRequestTripoTextureModelRequestTripoUrlReference)ApiEndpointdownload_url_to_file_3dpoll_opsync_opupload_images_to_comfyapiresponsereturnc                 C   sH   | j d urdD ]}t| j j|d d urt| j j|  S qtd|  )N)	pbr_modelmodel
base_modelz'Failed to get model url from response: )datagetattroutputRuntimeError)r   key r&   9/mnt/c/Users/fbmor/ComfyUI/comfy_api_nodes/nodes_tripo.pyget_model_url_from_response    s   
r(   Nnode_clsaverage_durationc              
      s   |j dkrtd|j |jj}t| td| dttj	gtj
tjtjtjtjgdd dd |dI d	H }|jjtj	krVt|}t|d
|dI d	H }t| d||S td| )z`Polls the Tripo API endpoint until the task reaches a terminal state, then returns the response.r   zFailed to generate mesh: z/proxy/tripo/v2/openapi/task/)pathc                 S      | j jS N)r!   statusxr&   r&   r'   <lambda>=       z%poll_until_finished.<locals>.<lambda>c                 S   r,   r-   )r!   progressr/   r&   r&   r'   r1   >   r2   )poll_endpointresponse_modelcompleted_statusesfailed_statusesstatus_extractorprogress_extractorestimated_durationNglb)task_idz.glb)coder$   errorr!   r<   r   r   r   r   SUCCESSFAILED	CANCELLEDUNKNOWNBANNEDEXPIREDr.   r(   r   r   
NodeOutput)r)   r   r*   r<   response_pollurlfile_glbr&   r&   r'   poll_until_finished(   s0   
rI   c                   @   s   e Zd ZdZedd Ze												ddededB dedB dedB d	edB d
edB dedB dedB dedB dedB dedB dedB de	j
fddZdS )TripoTextToModelNodezU
    Generates 3D models synchronously based on a text prompt using Tripo's API.
    c                 C   s^  t jdddt jjdddt jjddddt jjd	ttjdd
t jjdtddd
t jjddddt jjddddt j	jdddddt j	jdddddt j	jdddddt jjddddgdddt j	jdddddddt jjdddddt jjddddgdddgt jj
d d!t d"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 )*NrJ   zTripo: Text to Modelapi node/3d/TripopromptT)	multilinenegative_prompt)rM   optionalmodel_versionoptionsdefaultrO   styleNonetexturerS   rO   pbr
image_seed*   rS   rO   advanced
model_seedtexture_seedtexture_qualitystandarddetailedrS   rR   rO   r\   
face_limit逄 rS   minmaxrO   r\   quadFgeometry_quality
model_filedisplay_nameMODEL_TASK_IDmodel task_idGLBrP   rT   rV   rX   ri   r_   rj   widgetsab  
                (
                  $isV14 := $contains(widgets.model_version,"v1.4");
                  $style := widgets.style;
                  $hasStyle := ($style != "" and $style != "none");
                  $withTexture := widgets.texture or widgets.pbr;
                  $isHdTexture := (widgets.texture_quality = "detailed");
                  $isDetailedGeometry := (widgets.geometry_quality = "detailed");
                  $baseCredits :=
                    $isV14 ? 20 : ($withTexture ? 20 : 10);
                  $credits :=
                    $baseCredits
                    + ($hasStyle ? 5 : 0)
                    + (widgets.quad ? 5 : 0)
                    + ($isHdTexture ? 10 : 0)
                    + ($isDetailedGeometry ? 20 : 0);
                  {"type":"usd","usd": $round($credits * 0.01, 2)}
                )
                
depends_onexpr	node_idrm   categoryinputsoutputshiddenis_api_nodeis_output_nodeprice_badge)r   SchemaStringr   Combor   v2_5_20250123r   BooleanIntOutputCustom	File3DGLBHiddenauth_token_comfy_orgapi_key_comfy_org	unique_id
PriceBadgePriceBadgeDependsclsr&   r&   r'   define_schemaM   sJ   
z"TripoTextToModelNode.define_schemaNrL   rN   rT   rV   rX   rY   r]   r^   r_   rj   rc   ri   r   c                    s   |dkrd n|}|st dt| tdddtttj||r|nd |||||||	|
|dkr.|nd |d|dd	I d H }t| |d
dI d H S )NrU   zPrompt is required/proxy/tripo/v2/openapi/taskPOSTr+   methodrd   T)typerL   rN   rP   rT   rV   rX   rY   r]   r^   r_   rc   rj   	auto_sizeri   endpointr5   r!   P   r*   )r$   r   r   r   r   r   TEXT_TO_MODELrI   )r   rL   rN   rP   rT   rV   rX   rY   r]   r^   r_   rj   rc   ri   
style_enumr   r&   r&   r'   execute   s6   

zTripoTextToModelNode.executeNNNNNNNNNNNN)__name__
__module____qualname____doc__classmethodr   strboolintr   rE   r   r&   r&   r&   r'   rJ   H   sX    
D	
rJ   c                   @   s   e Zd ZdZedd Ze												ddejdedB dedB de	dB d	e	dB d
e
dB de
dB dedB dedB dedB de
dB de	dB dejfddZdS )TripoImageToModelNodezV
    Generates 3D models synchronously based on a single image using Tripo's API.
    c                 C   sd  t jdddt jdt jjdtdddt jjd	td
ddt jjddddt jjddddt jjdddddt jjdt	t	j
dddt jjdddddt jjddddgdddt jjddddgdddt jjdddddddt jjd d!dddt jjd"dddgdddgt jjd#d$t d%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 )-Nr   zTripo: Image to ModelrK   imagerP   'The model version to use for generationT)rR   tooltiprO   rT   rU   rQ   rV   rW   rX   r]   rZ   r[   orientationrR   rS   rO   r\   r^   r_   r`   ra   rb   texture_alignmentoriginal_imagegeometryrc   rd     rf   ri   Frj   rk   rl   rn   ro   rp   rq   rr   ab  
                (
                  $isV14 := $contains(widgets.model_version,"v1.4");
                  $style := widgets.style;
                  $hasStyle := ($style != "" and $style != "none");
                  $withTexture := widgets.texture or widgets.pbr;
                  $isHdTexture := (widgets.texture_quality = "detailed");
                  $isDetailedGeometry := (widgets.geometry_quality = "detailed");
                  $baseCredits :=
                    $isV14 ? 30 : ($withTexture ? 30 : 20);
                  $credits :=
                    $baseCredits
                    + ($hasStyle ? 5 : 0)
                    + (widgets.quad ? 5 : 0)
                    + ($isHdTexture ? 10 : 0)
                    + ($isDetailedGeometry ? 20 : 0);
                  {"type":"usd","usd": $round($credits * 0.01, 2)}
                )
                rt   rw   )r   r   Imager   r   r   r   r   r   r   DEFAULTr   r   r   r   r   r   r   r   r   r   r   r&   r&   r'   r      sX   
z#TripoImageToModelNode.define_schemaNr   rP   rT   rV   rX   r]   r^   r_   rj   r   rc   ri   r   c                    s   |dkrd n|}|d u rt dttt| |ddI d H d ddd}t| td	d
dtttj	||||||||
|||	|dkr@|nd d|ddI d H }t
| |ddI d H S )NrU   zImage is required   
max_imagesr   jpegrG   r   rootr   r   r   rd   T)r   filerP   rT   rV   rX   r]   r   rj   r   r^   r_   rc   r   ri   r   r   r   )r$   r
   r   r   r   r   r   r   r   IMAGE_TO_MODELrI   )r   r   rP   rT   rV   rX   r]   r   r^   r_   rj   r   rc   ri   r   
tripo_filer   r&   r&   r'   r     sB   
zTripoImageToModelNode.executer   r   r   r   r   r   r   r   r   r   r   r   r   rE   r   r&   r&   r&   r'   r      sX    
K	
r   c                "   @   s   e Zd ZdZedd Ze														ddejdejdB dejdB dejdB d	edB d
edB de	dB de	dB de
dB de
dB dedB dedB dedB de
dB de	dB dejf ddZdS )TripoMultiviewToModelNodezt
    Generates 3D models synchronously based on up to four images (front, left, back, right) using Tripo's API.
    c                 C   s|  t jd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
tdddt jjdttjdddt jjddddt jjddddt j	jdddddt j	jdddddt jjddddgdddt jjddddgdddt j	jddddddd t jjd!d"dddt jjd#dddgdddgt j
jd$d%t d&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 ).Nr   zTripo: Multiview to ModelrK   r   
image_leftT)rO   
image_backimage_rightrP   r   )rR   rO   r   r   r   rV   rW   rX   r]   rZ   r[   r^   r_   r`   ra   rb   r   r   r   rc   rd   r   rf   ri   Frj   rk   rl   rn   ro   rp   )rP   rV   rX   ri   r_   rj   rr   a  
                (
                  $isV14 := $contains(widgets.model_version,"v1.4");
                  $withTexture := widgets.texture or widgets.pbr;
                  $isHdTexture := (widgets.texture_quality = "detailed");
                  $isDetailedGeometry := (widgets.geometry_quality = "detailed");
                  $baseCredits :=
                    $isV14 ? 30 : ($withTexture ? 30 : 20);
                  $credits :=
                    $baseCredits
                    + (widgets.quad ? 5 : 0)
                    + ($isHdTexture ? 10 : 0)
                    + ($isDetailedGeometry ? 20 : 0);
                  {"type":"usd","usd": $round($credits * 0.01, 2)}
                )
                rt   rw   )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   H  sd   

z'TripoMultiviewToModelNode.define_schemaNr   r   r   r   rP   r   rV   rX   r]   r^   r_   rj   r   rc   ri   r   c                    s   |d u r	t dg }||||d}|d u r"|d u r"|d u r"t ddD ]'}|| }|d urE|ttt| |ddI d H d ddd	 q$|t  q$t| td
ddtt	t
j||||||	|
||||dkrg|nd |ddI d H }t| |ddI d H S )Nz%front image for multiview is required)r   r   r   r   zIAt least one of left, back, or right image must be provided for multiviewr   r   r   r   r   r   r   r   r   rd   )r   filesrP   r   rV   rX   r]   r^   r_   rj   r   rc   ri   )r5   r!   r   r   )r$   appendr
   r   r   r	   r   r   r   r   r   MULTIVIEW_TO_MODELrI   )r   r   r   r   r   rP   r   rV   rX   r]   r^   r_   rj   r   rc   ri   images
image_dict
image_nameimage_r   r&   r&   r'   r     sN   
z!TripoMultiviewToModelNode.execute)NNNNNNNNNNNNNNr   r&   r&   r&   r'   r   C  sh    
M	
r   c                   @   s`   e Zd Zedd Ze					ddedB dedB dedB dedB dedB d	ej	fd
dZ
dS )TripoTextureNodec                 C   s   t jdddt ddt jjddddt jjd	dddt jjd
ddddt jjddddgdddt jjddddgdddgt jjddt d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dgdddd	S )Nr   zTripo: Texture modelrK   rn   model_task_idrV   TrW   rX   r^   rZ   r[   r_   r`   ra   rb   r   r   r   rk   rl   ro   rp   rr   z
                (
                  $tq := widgets.texture_quality;
                  {"type":"usd","usd": ($contains($tq,"detailed") ? 0.2 : 0.1)}
                )
                rt   rw   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r&   r&   r'   r     s8   zTripoTextureNode.define_schemaNrV   rX   r^   r_   r   r   c                    sD   t | tdddtt||||||ddI d H }t| |ddI d H S )Nr   r   r   )original_model_task_idrV   rX   r^   r_   r   r   r   r   )r   r   r   r   rI   )r   r   rV   rX   r^   r_   r   r   r&   r&   r'   r     s   

zTripoTextureNode.execute)NNNNN)r   r   r   r   r   r   r   r   r   rE   r   r&   r&   r&   r'   r     s,    
&r   c                   @   ,   e Zd Zedd ZedejfddZdS )TripoRefineNodec                 C   sr   t jddddt djdddgt jjd	d
t djdd
t jjdd
gt jjt jj	t jj
gddt jddd
S )Nr   zTripo: Refine Draft modelrK   z7Refine a draft model created by v1.4 Tripo models only.rn   r   zMust be a v1.4 Tripo model)r   rk   rl   ro   rp   Tz{"type":"usd","usd":0.3}rv   )
rx   rm   ry   descriptionrz   r{   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r&   r&   r'   r     s*   zTripoRefineNode.define_schemar   c                    s:   t | tdddtt|ddI d H }t| |ddI d H S )Nr   r   r   )draft_model_task_idr      r   )r   r   r   r   rI   )r   r   r   r&   r&   r'   r   2  s   
zTripoRefineNode.executeNr   r   r   r   r   r   rE   r   r&   r&   r&   r'   r     s
    
r   c                   @   r   )TripoRigNodec                 C   sl   t jdddt ddgt jjddt djd	dt jjd
dgt jjt jj	t jj
gddt jddd	S )Nr   zTripo: Rig modelrK   rn   r   rk   rl   RIG_TASK_IDzrig task_idrp   Tz{"type":"usd","usd":0.25}r   rw   r   r   r&   r&   r'   r   ?  s&   zTripoRigNode.define_schemar   c              	      s>   t | tdddtt|ddddI d H }t| |dd	I d H S )
Nr   r   r   r;   tripo)r   
out_formatspecr      r   )r   r   r   r   rI   )r   r   r   r&   r&   r'   r   W  s   
zTripoRigNode.executeNr   r&   r&   r&   r'   r   =  s
    
r   c                   @   s0   e Zd Zedd ZededejfddZdS )TripoRetargetNodec                 C   s~   t jdddt ddt jjdg ddgt jjd	d
t djdd
t jjdd
gt jj	t jj
t jjgddt jddd	S )Nr   zTripo: Retarget rigged modelrK   r   r   	animation)zpreset:idlezpreset:walkz
preset:runzpreset:divezpreset:climbzpreset:jumpzpreset:slashzpreset:shootzpreset:hurtzpreset:fallzpreset:turnzpreset:quadruped:walkzpreset:hexapod:walkzpreset:octopod:walkzpreset:serpentine:marchzpreset:aquatic:marchrR   rk   rl   RETARGET_TASK_IDzretarget task_idrp   Tz{"type":"usd","usd":0.1}r   rw   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r&   r&   r'   r   d  s0   zTripoRetargetNode.define_schemar   r   c              
      s@   t | tdddtt||ddddI d H }t| |dd	I d H S )
Nr   r   r   r;   T)r   r   r   bake_animationr      r   )r   r   r   r   rI   )r   r   r   r   r&   r&   r'   r     s   
zTripoRetargetNode.executeN)	r   r   r   r   r   r   r   rE   r   r&   r&   r&   r'   r   b  s
    
.r   c                '   @   s   e Zd Zedd Zedd Zededededed	ed
e	dededede	dedededededededede
jf&ddZdS )TripoConversionNodec                 C   s  t jdddt ddt jjdg ddt jjd	d
dddt jjdddddddt jjdddddddt jjdg dddddt jjdd
dddt jjdd
dddt jjdddddddt jjdd
dddt jjddddddt jjd d
dddt jjd!d
dddt jjd"d
dddt jjd#d$dddt jjd%g d&d'dddt jjd(d
dddt jjd)d*d+gd+dddt jjd,d
dddgg t j	j
t j	jt j	jgddt jt jg d-d.d/d0d1	S )2Nr   zTripo: Convert modelrK   z*MODEL_TASK_ID,RIG_TASK_ID,RETARGET_TASK_IDr   format)GLTFUSDZFBXOBJSTL3MFr   ri   FTr[   rc   rd   re   rf   texture_size      texture_format)	BMPDPXHDRJPEGOPEN_EXRPNGTARGATIFFWEBPr   r   force_symmetryflatten_bottomflatten_bottom_threshold              ?pivot_to_center_bottomscale_factor)rS   rg   rO   r\   with_animationpack_uvbake
part_names 
fbx_preset)blendermixamo3dsmaxr  export_vertex_colorsexport_orientationalign_imagerS   animate_in_place)ri   rc   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r	  rr   al  
                (
                    $face := (widgets.face_limit != null) ? widgets.face_limit : -1;
                    $texSize := (widgets.texture_size != null) ? widgets.texture_size : 4096;
                    $flatThresh := (widgets.flatten_bottom_threshold != null) ? widgets.flatten_bottom_threshold : 0;
                    $scale := (widgets.scale_factor != null) ? widgets.scale_factor : 1;
                    $texFmt := (widgets.texture_format != "" ? widgets.texture_format : "jpeg");
                    $part := widgets.part_names;
                    $fbx := (widgets.fbx_preset != "" ? widgets.fbx_preset : "blender");
                    $orient := (widgets.export_orientation != "" ? widgets.export_orientation : "default");
                    $advanced :=
                      widgets.quad or
                      widgets.force_symmetry or
                      widgets.flatten_bottom or
                      widgets.pivot_to_center_bottom or
                      widgets.with_animation or
                      widgets.pack_uv or
                      widgets.bake or
                      widgets.export_vertex_colors or
                      widgets.animate_in_place or
                      ($face != -1) or
                      ($texSize != 4096) or
                      ($flatThresh != 0) or
                      ($scale != 1) or
                      ($texFmt != "jpeg") or
                      ($part != "") or
                      ($fbx != "blender") or
                      ($orient != "default");
                    {"type":"usd","usd": ($advanced ? 0.1 : 0.05)}
                )
                rt   rw   )r   r   r   r   r   r   r   Floatr   r   r   r   r   r   r   r   r&   r&   r'   r     s   Bz!TripoConversionNode.define_schemac                 C   s   |d dvrdS dS )Nr   )rn   r   r   zRoriginal_model_task_id must be MODEL_TASK_ID, RIG_TASK_ID or RETARGET_TASK_ID typeTr&   )r   input_typesr&   r&   r'   validate_inputs-  s   z#TripoConversionNode.validate_inputsr   ri   r   rc   r   r   r   r   r   r   r   r   r   r   r  r  r  r	  r   c              
      s  |st dd }|r| rdd |dD }t| tdddttd%i d|d	|d
|r/|nd d|r6|nd d|dkr?|nd d|rF|nd d|dkrO|nd d|dkrX|nd d|	dkra|	nd d|
rh|
nd d|dkrq|nd d|rx|nd d|r|nd d|r|nd d|d|dkr|nd d|r|nd d|d kr|nd d!|r|nd d"I d H }t| |d#d$I d H S d"I d H }t| |d#d$I d H S )&Nz"original_model_task_id is requiredc                 S   s   g | ]
}|  r|  qS r&   )strip).0namer&   r&   r'   
<listcomp>R  s    z/TripoConversionNode.execute.<locals>.<listcomp>,r   r   r   r   r   ri   r   rc   rd   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  rS   r	  r   r   r   r&   )r$   r  splitr   r   r   r   rI   )r   r   r   ri   r   rc   r   r   r   r   r   r   r   r   r   r   r  r  r  r	  part_names_listr   r&   r&   r'   r   5  s   



	





zTripoConversionNode.executeN)r   r   r   r   r   r  r   r   r   floatr   rE   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 )TripoExtensionr   c                    s   t tttttttgS r-   )rJ   r   r   r   r   r   r   r   )selfr&   r&   r'   get_node_listr  s   zTripoExtension.get_node_listN)	r   r   r   r   listr   r   	ComfyNoder  r&   r&   r&   r'   r  q  s    r  c                      s   t  S r-   )r  r&   r&   r&   r'   comfy_entrypoint  s   r  r-   )/typing_extensionsr   comfy_api.latestr   r   r   comfy_api_nodes.apis.tripor   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   comfy_api_nodes.utilr   r   r   r   r   r   r(   r   r  r   rE   rI   rJ   r   r   r   r   r   r   r   r  r  r&   r&   r&   r'   <module>   s8    L	
 w  C(%A O