mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2025-04-18 18:33:30 +00:00

* Allow disabling pe in flux code for some other models. * Initial Hunyuan3Dv2 implementation. Supports the multiview, mini, turbo models and VAEs. * Fix orientation of hunyuan 3d model. * A few fixes for the hunyuan3d models. * Update frontend to 1.13 (#7331) * Add backend primitive nodes (#7328) * Add backend primitive nodes * Add control after generate to int primitive * Nodes to convert images to YUV and back. Can be used to convert an image to black and white. * Update frontend to 1.14 (#7343) * Native LotusD Implementation (#7125) * draft pass at a native comfy implementation of Lotus-D depth and normal est * fix model_sampling kludges * fix ruff --------- Co-authored-by: comfyanonymous <121283862+comfyanonymous@users.noreply.github.com> * Automatically set the right sampling type for lotus. * support output normal and lineart once (#7290) * [nit] Format error strings (#7345) * ComfyUI version v0.3.27 * Fallback to pytorch attention if sage attention fails. * Add model merging node for WAN 2.1 * Add Hunyuan3D to readme. * Support more float8 types. * Add CFGZeroStar node. Works on all models that use a negative prompt but is meant for rectified flow models. * Support the WAN 2.1 fun control models. Use the new WanFunControlToVideo node. * Add WanFunInpaintToVideo node for the Wan fun inpaint models. * Update frontend to 1.14.6 (#7416) Cherry-pick the fix: https://github.com/Comfy-Org/ComfyUI_frontend/pull/3252 * Don't error if wan concat image has extra channels. * ltxv: fix preprocessing exception when compression is 0. (#7431) * Remove useless code. * Fix latent composite node not working when source has alpha. * Fix alpha channel mismatch on destination in ImageCompositeMasked * Add option to store TE in bf16 (#7461) * User missing (#7439) * Ensuring a 401 error is returned when user data is not found in multi-user context. * Returning a 401 error when provided comfy-user does not exists on server side. * Fix comment. This function does not support quads. * MLU memory optimization (#7470) Co-authored-by: huzhan <huzhan@cambricon.com> * Fix alpha image issue in more nodes. * Fix problem. * Disable partial offloading of audio VAE. * Add activations_shape info in UNet models (#7482) * Add activations_shape info in UNet models * activations_shape should be a list * Support 512 siglip model. * Show a proper error to the user when a vision model file is invalid. * Support the wan fun reward loras. --------- Co-authored-by: comfyanonymous <comfyanonymous@protonmail.com> Co-authored-by: Chenlei Hu <hcl@comfy.org> Co-authored-by: thot experiment <94414189+thot-experiment@users.noreply.github.com> Co-authored-by: comfyanonymous <121283862+comfyanonymous@users.noreply.github.com> Co-authored-by: Terry Jia <terryjia88@gmail.com> Co-authored-by: Michael Kupchick <michael@lightricks.com> Co-authored-by: BVH <82035780+bvhari@users.noreply.github.com> Co-authored-by: Laurent Erignoux <lerignoux@gmail.com> Co-authored-by: BiologicalExplosion <49753622+BiologicalExplosion@users.noreply.github.com> Co-authored-by: huzhan <huzhan@cambricon.com> Co-authored-by: Raphael Walker <slickytail.mc@gmail.com>
131 lines
4.3 KiB
Python
131 lines
4.3 KiB
Python
import nodes
|
|
import folder_paths
|
|
import os
|
|
|
|
def normalize_path(path):
|
|
return path.replace('\\', '/')
|
|
|
|
class Load3D():
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
input_dir = os.path.join(folder_paths.get_input_directory(), "3d")
|
|
|
|
os.makedirs(input_dir, exist_ok=True)
|
|
|
|
files = [normalize_path(os.path.join("3d", f)) for f in os.listdir(input_dir) if f.endswith(('.gltf', '.glb', '.obj', '.mtl', '.fbx', '.stl'))]
|
|
|
|
return {"required": {
|
|
"model_file": (sorted(files), {"file_upload": True}),
|
|
"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", "IMAGE")
|
|
RETURN_NAMES = ("image", "mask", "mesh_path", "normal", "lineart")
|
|
|
|
FUNCTION = "process"
|
|
EXPERIMENTAL = True
|
|
|
|
CATEGORY = "3d"
|
|
|
|
def process(self, model_file, image, **kwargs):
|
|
image_path = folder_paths.get_annotated_filepath(image['image'])
|
|
mask_path = folder_paths.get_annotated_filepath(image['mask'])
|
|
normal_path = folder_paths.get_annotated_filepath(image['normal'])
|
|
lineart_path = folder_paths.get_annotated_filepath(image['lineart'])
|
|
|
|
load_image_node = nodes.LoadImage()
|
|
output_image, ignore_mask = load_image_node.load_image(image=image_path)
|
|
ignore_image, output_mask = load_image_node.load_image(image=mask_path)
|
|
normal_image, ignore_mask2 = load_image_node.load_image(image=normal_path)
|
|
lineart_image, ignore_mask3 = load_image_node.load_image(image=lineart_path)
|
|
|
|
return output_image, output_mask, model_file, normal_image, lineart_image
|
|
|
|
class Load3DAnimation():
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
input_dir = os.path.join(folder_paths.get_input_directory(), "3d")
|
|
|
|
os.makedirs(input_dir, exist_ok=True)
|
|
|
|
files = [normalize_path(os.path.join("3d", f)) for f in os.listdir(input_dir) if f.endswith(('.gltf', '.glb', '.fbx'))]
|
|
|
|
return {"required": {
|
|
"model_file": (sorted(files), {"file_upload": True}),
|
|
"image": ("LOAD_3D_ANIMATION", {}),
|
|
"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")
|
|
RETURN_NAMES = ("image", "mask", "mesh_path", "normal")
|
|
|
|
FUNCTION = "process"
|
|
EXPERIMENTAL = True
|
|
|
|
CATEGORY = "3d"
|
|
|
|
def process(self, model_file, image, **kwargs):
|
|
image_path = folder_paths.get_annotated_filepath(image['image'])
|
|
mask_path = folder_paths.get_annotated_filepath(image['mask'])
|
|
normal_path = folder_paths.get_annotated_filepath(image['normal'])
|
|
|
|
load_image_node = nodes.LoadImage()
|
|
output_image, ignore_mask = load_image_node.load_image(image=image_path)
|
|
ignore_image, output_mask = load_image_node.load_image(image=mask_path)
|
|
normal_image, ignore_mask2 = load_image_node.load_image(image=normal_path)
|
|
|
|
return output_image, output_mask, model_file, normal_image
|
|
|
|
class Preview3D():
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required": {
|
|
"model_file": ("STRING", {"default": "", "multiline": False}),
|
|
}}
|
|
|
|
OUTPUT_NODE = True
|
|
RETURN_TYPES = ()
|
|
|
|
CATEGORY = "3d"
|
|
|
|
FUNCTION = "process"
|
|
EXPERIMENTAL = True
|
|
|
|
def process(self, model_file, **kwargs):
|
|
return {"ui": {"model_file": [model_file]}, "result": ()}
|
|
|
|
class Preview3DAnimation():
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required": {
|
|
"model_file": ("STRING", {"default": "", "multiline": False}),
|
|
}}
|
|
|
|
OUTPUT_NODE = True
|
|
RETURN_TYPES = ()
|
|
|
|
CATEGORY = "3d"
|
|
|
|
FUNCTION = "process"
|
|
EXPERIMENTAL = True
|
|
|
|
def process(self, model_file, **kwargs):
|
|
return {"ui": {"model_file": [model_file]}, "result": ()}
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"Load3D": Load3D,
|
|
"Load3DAnimation": Load3DAnimation,
|
|
"Preview3D": Preview3D,
|
|
"Preview3DAnimation": Preview3DAnimation
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"Load3D": "Load 3D",
|
|
"Load3DAnimation": "Load 3D - Animation",
|
|
"Preview3D": "Preview 3D",
|
|
"Preview3DAnimation": "Preview 3D - Animation"
|
|
}
|