mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2025-12-16 17:42:58 +08:00
convert nodes_load_3d.py to V3 schema (#10990)
This commit is contained in:
parent
87c104bfc1
commit
440268d394
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
import uuid
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
@ -436,9 +437,19 @@ class PreviewUI3D(_UIOutput):
|
|||||||
def __init__(self, model_file, camera_info, **kwargs):
|
def __init__(self, model_file, camera_info, **kwargs):
|
||||||
self.model_file = model_file
|
self.model_file = model_file
|
||||||
self.camera_info = camera_info
|
self.camera_info = camera_info
|
||||||
|
self.bg_image_path = None
|
||||||
|
bg_image = kwargs.get("bg_image", None)
|
||||||
|
if bg_image is not None:
|
||||||
|
img_array = (bg_image[0].cpu().numpy() * 255).astype(np.uint8)
|
||||||
|
img = PILImage.fromarray(img_array)
|
||||||
|
temp_dir = folder_paths.get_temp_directory()
|
||||||
|
filename = f"bg_{uuid.uuid4().hex}.png"
|
||||||
|
bg_image_path = os.path.join(temp_dir, filename)
|
||||||
|
img.save(bg_image_path, compress_level=1)
|
||||||
|
self.bg_image_path = f"temp/{filename}"
|
||||||
|
|
||||||
def as_dict(self):
|
def as_dict(self):
|
||||||
return {"result": [self.model_file, self.camera_info]}
|
return {"result": [self.model_file, self.camera_info, self.bg_image_path]}
|
||||||
|
|
||||||
|
|
||||||
class PreviewText(_UIOutput):
|
class PreviewText(_UIOutput):
|
||||||
|
|||||||
@ -2,22 +2,18 @@ import nodes
|
|||||||
import folder_paths
|
import folder_paths
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from comfy.comfy_types import IO
|
from typing_extensions import override
|
||||||
from comfy_api.input_impl import VideoFromFile
|
from comfy_api.latest import IO, ComfyExtension, InputImpl, UI
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from PIL import Image
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
def normalize_path(path):
|
def normalize_path(path):
|
||||||
return path.replace('\\', '/')
|
return path.replace('\\', '/')
|
||||||
|
|
||||||
class Load3D():
|
class Load3D(IO.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls):
|
||||||
input_dir = os.path.join(folder_paths.get_input_directory(), "3d")
|
input_dir = os.path.join(folder_paths.get_input_directory(), "3d")
|
||||||
|
|
||||||
os.makedirs(input_dir, exist_ok=True)
|
os.makedirs(input_dir, exist_ok=True)
|
||||||
@ -30,23 +26,29 @@ class Load3D():
|
|||||||
for file_path in input_path.rglob("*")
|
for file_path in input_path.rglob("*")
|
||||||
if file_path.suffix.lower() in {'.gltf', '.glb', '.obj', '.fbx', '.stl'}
|
if file_path.suffix.lower() in {'.gltf', '.glb', '.obj', '.fbx', '.stl'}
|
||||||
]
|
]
|
||||||
|
return IO.Schema(
|
||||||
|
node_id="Load3D",
|
||||||
|
display_name="Load 3D & Animation",
|
||||||
|
category="3d",
|
||||||
|
is_experimental=True,
|
||||||
|
inputs=[
|
||||||
|
IO.Combo.Input("model_file", options=sorted(files), upload=IO.UploadType.model),
|
||||||
|
IO.Load3D.Input("image"),
|
||||||
|
IO.Int.Input("width", default=1024, min=1, max=4096, step=1),
|
||||||
|
IO.Int.Input("height", default=1024, min=1, max=4096, step=1),
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
IO.Image.Output(display_name="image"),
|
||||||
|
IO.Mask.Output(display_name="mask"),
|
||||||
|
IO.String.Output(display_name="mesh_path"),
|
||||||
|
IO.Image.Output(display_name="normal"),
|
||||||
|
IO.Load3DCamera.Output(display_name="camera_info"),
|
||||||
|
IO.Video.Output(display_name="recording_video"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
return {"required": {
|
@classmethod
|
||||||
"model_file": (sorted(files), {"file_upload": True}),
|
def execute(cls, model_file, image, **kwargs) -> IO.NodeOutput:
|
||||||
"image": ("LOAD_3D", {}),
|
|
||||||
"width": ("INT", {"default": 1024, "min": 1, "max": 4096, "step": 1}),
|
|
||||||
"height": ("INT", {"default": 1024, "min": 1, "max": 4096, "step": 1}),
|
|
||||||
}}
|
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE", "MASK", "STRING", "IMAGE", "LOAD3D_CAMERA", IO.VIDEO)
|
|
||||||
RETURN_NAMES = ("image", "mask", "mesh_path", "normal", "camera_info", "recording_video")
|
|
||||||
|
|
||||||
FUNCTION = "process"
|
|
||||||
EXPERIMENTAL = True
|
|
||||||
|
|
||||||
CATEGORY = "3d"
|
|
||||||
|
|
||||||
def process(self, model_file, image, **kwargs):
|
|
||||||
image_path = folder_paths.get_annotated_filepath(image['image'])
|
image_path = folder_paths.get_annotated_filepath(image['image'])
|
||||||
mask_path = folder_paths.get_annotated_filepath(image['mask'])
|
mask_path = folder_paths.get_annotated_filepath(image['mask'])
|
||||||
normal_path = folder_paths.get_annotated_filepath(image['normal'])
|
normal_path = folder_paths.get_annotated_filepath(image['normal'])
|
||||||
@ -61,58 +63,47 @@ class Load3D():
|
|||||||
if image['recording'] != "":
|
if image['recording'] != "":
|
||||||
recording_video_path = folder_paths.get_annotated_filepath(image['recording'])
|
recording_video_path = folder_paths.get_annotated_filepath(image['recording'])
|
||||||
|
|
||||||
video = VideoFromFile(recording_video_path)
|
video = InputImpl.VideoFromFile(recording_video_path)
|
||||||
|
|
||||||
return output_image, output_mask, model_file, normal_image, image['camera_info'], video
|
return IO.NodeOutput(output_image, output_mask, model_file, normal_image, image['camera_info'], video)
|
||||||
|
|
||||||
class Preview3D():
|
process = execute # TODO: remove
|
||||||
|
|
||||||
|
|
||||||
|
class Preview3D(IO.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls):
|
||||||
return {"required": {
|
return IO.Schema(
|
||||||
"model_file": ("STRING", {"default": "", "multiline": False}),
|
node_id="Preview3D",
|
||||||
},
|
display_name="Preview 3D & Animation",
|
||||||
"optional": {
|
category="3d",
|
||||||
"camera_info": ("LOAD3D_CAMERA", {}),
|
is_experimental=True,
|
||||||
"bg_image": ("IMAGE", {})
|
is_output_node=True,
|
||||||
}}
|
inputs=[
|
||||||
|
IO.String.Input("model_file", default="", multiline=False),
|
||||||
|
IO.Load3DCamera.Input("camera_info", optional=True),
|
||||||
|
IO.Image.Input("bg_image", optional=True),
|
||||||
|
],
|
||||||
|
outputs=[],
|
||||||
|
)
|
||||||
|
|
||||||
OUTPUT_NODE = True
|
@classmethod
|
||||||
RETURN_TYPES = ()
|
def execute(cls, model_file, **kwargs) -> IO.NodeOutput:
|
||||||
|
|
||||||
CATEGORY = "3d"
|
|
||||||
|
|
||||||
FUNCTION = "process"
|
|
||||||
EXPERIMENTAL = True
|
|
||||||
|
|
||||||
def process(self, model_file, **kwargs):
|
|
||||||
camera_info = kwargs.get("camera_info", None)
|
camera_info = kwargs.get("camera_info", None)
|
||||||
bg_image = kwargs.get("bg_image", None)
|
bg_image = kwargs.get("bg_image", None)
|
||||||
|
return IO.NodeOutput(ui=UI.PreviewUI3D(model_file, camera_info, bg_image=bg_image))
|
||||||
|
|
||||||
bg_image_path = None
|
process = execute # TODO: remove
|
||||||
if bg_image is not None:
|
|
||||||
|
|
||||||
img_array = (bg_image[0].cpu().numpy() * 255).astype(np.uint8)
|
|
||||||
img = Image.fromarray(img_array)
|
|
||||||
|
|
||||||
temp_dir = folder_paths.get_temp_directory()
|
class Load3DExtension(ComfyExtension):
|
||||||
filename = f"bg_{uuid.uuid4().hex}.png"
|
@override
|
||||||
bg_image_path = os.path.join(temp_dir, filename)
|
async def get_node_list(self) -> list[type[IO.ComfyNode]]:
|
||||||
img.save(bg_image_path, compress_level=1)
|
return [
|
||||||
|
Load3D,
|
||||||
|
Preview3D,
|
||||||
|
]
|
||||||
|
|
||||||
bg_image_path = f"temp/{filename}"
|
|
||||||
|
|
||||||
return {
|
async def comfy_entrypoint() -> Load3DExtension:
|
||||||
"ui": {
|
return Load3DExtension()
|
||||||
"result": [model_file, camera_info, bg_image_path]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
|
||||||
"Load3D": Load3D,
|
|
||||||
"Preview3D": Preview3D,
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
"Load3D": "Load 3D & Animation",
|
|
||||||
"Preview3D": "Preview 3D & Animation",
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user