update Rodin3D nodes to use File3DGLB
Some checks are pending
Python Linting / Run Ruff (push) Waiting to run
Python Linting / Run Pylint (push) Waiting to run

This commit is contained in:
bigcat88 2026-02-02 13:33:45 +02:00
parent be8676e500
commit c18aed33d6

View File

@ -10,7 +10,6 @@ import folder_paths as comfy_paths
import os import os
import logging import logging
import math import math
from typing import Optional
from io import BytesIO from io import BytesIO
from typing_extensions import override from typing_extensions import override
from PIL import Image from PIL import Image
@ -28,8 +27,9 @@ from comfy_api_nodes.util import (
poll_op, poll_op,
ApiEndpoint, ApiEndpoint,
download_url_to_bytesio, download_url_to_bytesio,
download_url_to_file_3d,
) )
from comfy_api.latest import ComfyExtension, IO from comfy_api.latest import ComfyExtension, IO, Types
COMMON_PARAMETERS = [ COMMON_PARAMETERS = [
@ -177,7 +177,7 @@ def check_rodin_status(response: Rodin3DCheckStatusResponse) -> str:
return "DONE" return "DONE"
return "Generating" return "Generating"
def extract_progress(response: Rodin3DCheckStatusResponse) -> Optional[int]: def extract_progress(response: Rodin3DCheckStatusResponse) -> int | None:
if not response.jobs: if not response.jobs:
return None return None
completed_count = sum(1 for job in response.jobs if job.status == JobStatus.Done) completed_count = sum(1 for job in response.jobs if job.status == JobStatus.Done)
@ -207,17 +207,25 @@ async def get_rodin_download_list(uuid: str, cls: type[IO.ComfyNode]) -> Rodin3D
) )
async def download_files(url_list, task_uuid: str): async def download_files(url_list, task_uuid: str) -> tuple[str | None, Types.File3D | None]:
result_folder_name = f"Rodin3D_{task_uuid}" result_folder_name = f"Rodin3D_{task_uuid}"
save_path = os.path.join(comfy_paths.get_output_directory(), result_folder_name) save_path = os.path.join(comfy_paths.get_output_directory(), result_folder_name)
os.makedirs(save_path, exist_ok=True) os.makedirs(save_path, exist_ok=True)
model_file_path = None model_file_path = None
file_3d = None
for i in url_list.list: for i in url_list.list:
file_path = os.path.join(save_path, i.name) file_path = os.path.join(save_path, i.name)
if file_path.endswith(".glb"): if i.name.endswith(".glb"):
model_file_path = os.path.join(result_folder_name, i.name) model_file_path = os.path.join(result_folder_name, i.name)
await download_url_to_bytesio(i.url, file_path) file_3d = await download_url_to_file_3d(i.url, "glb")
return model_file_path # Save to disk for backward compatibility
with open(file_path, "wb") as f:
f.write(file_3d.get_bytes())
else:
await download_url_to_bytesio(i.url, file_path)
return model_file_path, file_3d
class Rodin3D_Regular(IO.ComfyNode): class Rodin3D_Regular(IO.ComfyNode):
@ -234,7 +242,10 @@ class Rodin3D_Regular(IO.ComfyNode):
IO.Image.Input("Images"), IO.Image.Input("Images"),
*COMMON_PARAMETERS, *COMMON_PARAMETERS,
], ],
outputs=[IO.String.Output(display_name="3D Model Path")], outputs=[
IO.String.Output(display_name="3D Model Path"), # for backward compatibility only
IO.File3DGLB.Output(display_name="GLB"),
],
hidden=[ hidden=[
IO.Hidden.auth_token_comfy_org, IO.Hidden.auth_token_comfy_org,
IO.Hidden.api_key_comfy_org, IO.Hidden.api_key_comfy_org,
@ -271,9 +282,9 @@ class Rodin3D_Regular(IO.ComfyNode):
) )
await poll_for_task_status(subscription_key, cls) await poll_for_task_status(subscription_key, cls)
download_list = await get_rodin_download_list(task_uuid, cls) download_list = await get_rodin_download_list(task_uuid, cls)
model = await download_files(download_list, task_uuid) model_path, file_3d = await download_files(download_list, task_uuid)
return IO.NodeOutput(model) return IO.NodeOutput(model_path, file_3d)
class Rodin3D_Detail(IO.ComfyNode): class Rodin3D_Detail(IO.ComfyNode):
@ -290,7 +301,10 @@ class Rodin3D_Detail(IO.ComfyNode):
IO.Image.Input("Images"), IO.Image.Input("Images"),
*COMMON_PARAMETERS, *COMMON_PARAMETERS,
], ],
outputs=[IO.String.Output(display_name="3D Model Path")], outputs=[
IO.String.Output(display_name="3D Model Path"), # for backward compatibility only
IO.File3DGLB.Output(display_name="GLB"),
],
hidden=[ hidden=[
IO.Hidden.auth_token_comfy_org, IO.Hidden.auth_token_comfy_org,
IO.Hidden.api_key_comfy_org, IO.Hidden.api_key_comfy_org,
@ -327,9 +341,9 @@ class Rodin3D_Detail(IO.ComfyNode):
) )
await poll_for_task_status(subscription_key, cls) await poll_for_task_status(subscription_key, cls)
download_list = await get_rodin_download_list(task_uuid, cls) download_list = await get_rodin_download_list(task_uuid, cls)
model = await download_files(download_list, task_uuid) model_path, file_3d = await download_files(download_list, task_uuid)
return IO.NodeOutput(model) return IO.NodeOutput(model_path, file_3d)
class Rodin3D_Smooth(IO.ComfyNode): class Rodin3D_Smooth(IO.ComfyNode):
@ -346,7 +360,10 @@ class Rodin3D_Smooth(IO.ComfyNode):
IO.Image.Input("Images"), IO.Image.Input("Images"),
*COMMON_PARAMETERS, *COMMON_PARAMETERS,
], ],
outputs=[IO.String.Output(display_name="3D Model Path")], outputs=[
IO.String.Output(display_name="3D Model Path"), # for backward compatibility only
IO.File3DGLB.Output(display_name="GLB"),
],
hidden=[ hidden=[
IO.Hidden.auth_token_comfy_org, IO.Hidden.auth_token_comfy_org,
IO.Hidden.api_key_comfy_org, IO.Hidden.api_key_comfy_org,
@ -382,9 +399,9 @@ class Rodin3D_Smooth(IO.ComfyNode):
) )
await poll_for_task_status(subscription_key, cls) await poll_for_task_status(subscription_key, cls)
download_list = await get_rodin_download_list(task_uuid, cls) download_list = await get_rodin_download_list(task_uuid, cls)
model = await download_files(download_list, task_uuid) model_path, file_3d = await download_files(download_list, task_uuid)
return IO.NodeOutput(model) return IO.NodeOutput(model_path, file_3d)
class Rodin3D_Sketch(IO.ComfyNode): class Rodin3D_Sketch(IO.ComfyNode):
@ -408,7 +425,10 @@ class Rodin3D_Sketch(IO.ComfyNode):
optional=True, optional=True,
), ),
], ],
outputs=[IO.String.Output(display_name="3D Model Path")], outputs=[
IO.String.Output(display_name="3D Model Path"), # for backward compatibility only
IO.File3DGLB.Output(display_name="GLB"),
],
hidden=[ hidden=[
IO.Hidden.auth_token_comfy_org, IO.Hidden.auth_token_comfy_org,
IO.Hidden.api_key_comfy_org, IO.Hidden.api_key_comfy_org,
@ -441,9 +461,9 @@ class Rodin3D_Sketch(IO.ComfyNode):
) )
await poll_for_task_status(subscription_key, cls) await poll_for_task_status(subscription_key, cls)
download_list = await get_rodin_download_list(task_uuid, cls) download_list = await get_rodin_download_list(task_uuid, cls)
model = await download_files(download_list, task_uuid) model_path, file_3d = await download_files(download_list, task_uuid)
return IO.NodeOutput(model) return IO.NodeOutput(model_path, file_3d)
class Rodin3D_Gen2(IO.ComfyNode): class Rodin3D_Gen2(IO.ComfyNode):
@ -475,7 +495,10 @@ class Rodin3D_Gen2(IO.ComfyNode):
), ),
IO.Boolean.Input("TAPose", default=False), IO.Boolean.Input("TAPose", default=False),
], ],
outputs=[IO.String.Output(display_name="3D Model Path")], outputs=[
IO.String.Output(display_name="3D Model Path"), # for backward compatibility only
IO.File3DGLB.Output(display_name="GLB"),
],
hidden=[ hidden=[
IO.Hidden.auth_token_comfy_org, IO.Hidden.auth_token_comfy_org,
IO.Hidden.api_key_comfy_org, IO.Hidden.api_key_comfy_org,
@ -511,9 +534,9 @@ class Rodin3D_Gen2(IO.ComfyNode):
) )
await poll_for_task_status(subscription_key, cls) await poll_for_task_status(subscription_key, cls)
download_list = await get_rodin_download_list(task_uuid, cls) download_list = await get_rodin_download_list(task_uuid, cls)
model = await download_files(download_list, task_uuid) model_path, file_3d = await download_files(download_list, task_uuid)
return IO.NodeOutput(model) return IO.NodeOutput(model_path, file_3d)
class Rodin3DExtension(ComfyExtension): class Rodin3DExtension(ComfyExtension):