Merge branch 'master' into seedvr2-native-support

This commit is contained in:
Alexis Rolland 2026-06-08 02:43:43 -07:00 committed by GitHub
commit 10b3cf3730
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 60 additions and 52 deletions

View File

@ -1,27 +1,27 @@
As of the time of writing this you need a recent driver. Updating to the latest driver is recommended. As of the time of writing this you need a recent driver. Updating to the latest driver is recommended.
HOW TO RUN: HOW TO RUN:
If you have a AMD gpu: If you have a AMD gpu:
run_amd_gpu.bat run_amd_gpu.bat
If you have memory issues you can try enabling the new dynamic memory management by running comfyui with: If you have memory issues you can try enabling the new dynamic memory management by running comfyui with:
run_amd_gpu_enable_dynamic_vram.bat run_amd_gpu_enable_dynamic_vram.bat
IF YOU GET A RED ERROR IN THE UI MAKE SURE YOU HAVE A MODEL/CHECKPOINT IN: ComfyUI\models\checkpoints IF YOU GET A RED ERROR IN THE UI MAKE SURE YOU HAVE A MODEL/CHECKPOINT IN: ComfyUI\models\checkpoints
You can download the stable diffusion XL one from: https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/blob/main/sd_xl_base_1.0_0.9vae.safetensors You can download the stable diffusion XL one from: https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/blob/main/sd_xl_base_1.0_0.9vae.safetensors
RECOMMENDED WAY TO UPDATE: RECOMMENDED WAY TO UPDATE:
To update the ComfyUI code: update\update_comfyui.bat To update the ComfyUI code: update\update_comfyui.bat
TO SHARE MODELS BETWEEN COMFYUI AND ANOTHER UI: TO SHARE MODELS BETWEEN COMFYUI AND ANOTHER UI:
In the ComfyUI directory you will find a file: extra_model_paths.yaml.example In the ComfyUI directory you will find a file: extra_model_paths.yaml.example
Rename this file to: extra_model_paths.yaml and edit it with your favorite text editor. Rename this file to: extra_model_paths.yaml and edit it with your favorite text editor.

View File

@ -17,7 +17,7 @@ jobs:
- name: Check for Windows line endings (CRLF) - name: Check for Windows line endings (CRLF)
run: | run: |
# Get the list of changed files in the PR # Get the list of changed files in the PR
CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}) CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} -- ':!.ci')
# Flag to track if CRLF is found # Flag to track if CRLF is found
CRLF_FOUND=false CRLF_FOUND=false

View File

@ -51,6 +51,14 @@ class Load3D(IO.ComfyNode):
], ],
) )
@classmethod
def validate_inputs(cls, model_file, **kwargs) -> bool | str:
if not model_file or model_file == "none":
return True
if not folder_paths.exists_annotated_filepath(model_file):
return f"Invalid 3D model file: {model_file}"
return True
@classmethod @classmethod
def execute(cls, model_file, image, **kwargs) -> IO.NodeOutput: def execute(cls, model_file, image, **kwargs) -> IO.NodeOutput:
image_path = folder_paths.get_annotated_filepath(image['image']) image_path = folder_paths.get_annotated_filepath(image['image'])
@ -148,34 +156,34 @@ class Preview3DAdvanced(IO.ComfyNode):
], ],
tooltip="3D model file from an upstream 3D node.", tooltip="3D model file from an upstream 3D node.",
), ),
IO.Load3D.Input("image"),
IO.Load3DCamera.Input("camera_info", optional=True, advanced=True),
IO.Load3DModelInfo.Input("model_3d_info", optional=True, advanced=True), IO.Load3DModelInfo.Input("model_3d_info", optional=True, advanced=True),
IO.Load3D.Input("viewport_state"),
IO.Load3DCamera.Input("camera_info", optional=True, advanced=True),
IO.Int.Input("width", default=1024, min=1, max=4096, step=1), IO.Int.Input("width", default=1024, min=1, max=4096, step=1),
IO.Int.Input("height", default=1024, min=1, max=4096, step=1), IO.Int.Input("height", default=1024, min=1, max=4096, step=1),
], ],
outputs=[ outputs=[
IO.File3DAny.Output(display_name="model_3d"), IO.File3DAny.Output(display_name="model_3d"),
IO.Load3DCamera.Output(display_name="camera_info"),
IO.Load3DModelInfo.Output(display_name="model_3d_info"), IO.Load3DModelInfo.Output(display_name="model_3d_info"),
IO.Load3DCamera.Output(display_name="camera_info"),
IO.Int.Output(display_name="width"), IO.Int.Output(display_name="width"),
IO.Int.Output(display_name="height"), IO.Int.Output(display_name="height"),
], ],
) )
@classmethod @classmethod
def execute(cls, model_3d: Types.File3D, image, width: int, height: int, **kwargs) -> IO.NodeOutput: def execute(cls, model_3d: Types.File3D, viewport_state, width: int, height: int, **kwargs) -> IO.NodeOutput:
filename = f"preview3d_advanced_{uuid.uuid4().hex}.{model_3d.format}" filename = f"preview3d_advanced_{uuid.uuid4().hex}.{model_3d.format}"
model_3d.save_to(os.path.join(folder_paths.get_output_directory(), filename)) model_3d.save_to(os.path.join(folder_paths.get_temp_directory(), filename))
camera_info_input = kwargs.get("camera_info", None) camera_info_input = kwargs.get("camera_info", None)
camera_info = camera_info_input if camera_info_input is not None else image['camera_info'] camera_info = camera_info_input if camera_info_input is not None else viewport_state['camera_info']
model_3d_info_input = kwargs.get("model_3d_info", None) model_3d_info_input = kwargs.get("model_3d_info", None)
model_3d_info = model_3d_info_input if model_3d_info_input is not None else image.get('model_3d_info', []) model_3d_info = model_3d_info_input if model_3d_info_input is not None else viewport_state.get('model_3d_info', [])
return IO.NodeOutput( return IO.NodeOutput(
model_3d, model_3d,
camera_info,
model_3d_info, model_3d_info,
camera_info,
width, width,
height, height,
ui=UI.PreviewUI3DAdvanced(filename, camera_info, model_3d_info), ui=UI.PreviewUI3DAdvanced(filename, camera_info, model_3d_info),
@ -216,34 +224,34 @@ class PreviewGaussianSplat(IO.ComfyNode):
], ],
tooltip="A gaussian splat 3D file.", tooltip="A gaussian splat 3D file.",
), ),
IO.Load3D.Input("image"),
IO.Load3DCamera.Input("camera_info", optional=True, advanced=True),
IO.Load3DModelInfo.Input("model_3d_info", optional=True, advanced=True), IO.Load3DModelInfo.Input("model_3d_info", optional=True, advanced=True),
IO.Load3D.Input("viewport_state"),
IO.Load3DCamera.Input("camera_info", optional=True, advanced=True),
IO.Int.Input("width", default=1024, min=1, max=4096, step=1), IO.Int.Input("width", default=1024, min=1, max=4096, step=1),
IO.Int.Input("height", default=1024, min=1, max=4096, step=1), IO.Int.Input("height", default=1024, min=1, max=4096, step=1),
], ],
outputs=[ outputs=[
IO.File3DSplatAny.Output(display_name="model_3d"), IO.File3DSplatAny.Output(display_name="model_3d"),
IO.Load3DCamera.Output(display_name="camera_info"),
IO.Load3DModelInfo.Output(display_name="model_3d_info"), IO.Load3DModelInfo.Output(display_name="model_3d_info"),
IO.Load3DCamera.Output(display_name="camera_info"),
IO.Int.Output(display_name="width"), IO.Int.Output(display_name="width"),
IO.Int.Output(display_name="height"), IO.Int.Output(display_name="height"),
], ],
) )
@classmethod @classmethod
def execute(cls, model_3d: Types.File3D, image, width: int, height: int, **kwargs) -> IO.NodeOutput: def execute(cls, model_3d: Types.File3D, viewport_state, width: int, height: int, **kwargs) -> IO.NodeOutput:
filename = f"preview_splat_{uuid.uuid4().hex}.{model_3d.format}" filename = f"preview_splat_{uuid.uuid4().hex}.{model_3d.format}"
model_3d.save_to(os.path.join(folder_paths.get_output_directory(), filename)) model_3d.save_to(os.path.join(folder_paths.get_temp_directory(), filename))
camera_info_input = kwargs.get("camera_info", None) camera_info_input = kwargs.get("camera_info", None)
camera_info = camera_info_input if camera_info_input is not None else image['camera_info'] camera_info = camera_info_input if camera_info_input is not None else viewport_state['camera_info']
model_3d_info_input = kwargs.get("model_3d_info", None) model_3d_info_input = kwargs.get("model_3d_info", None)
model_3d_info = model_3d_info_input if model_3d_info_input is not None else image.get('model_3d_info', []) model_3d_info = model_3d_info_input if model_3d_info_input is not None else viewport_state.get('model_3d_info', [])
return IO.NodeOutput( return IO.NodeOutput(
model_3d, model_3d,
camera_info,
model_3d_info, model_3d_info,
camera_info,
width, width,
height, height,
ui=UI.PreviewUI3DAdvanced(filename, camera_info, model_3d_info), ui=UI.PreviewUI3DAdvanced(filename, camera_info, model_3d_info),
@ -275,34 +283,34 @@ class PreviewPointCloud(IO.ComfyNode):
], ],
tooltip="Point cloud file (.ply)", tooltip="Point cloud file (.ply)",
), ),
IO.Load3D.Input("image"),
IO.Load3DCamera.Input("camera_info", optional=True, advanced=True),
IO.Load3DModelInfo.Input("model_3d_info", optional=True, advanced=True), IO.Load3DModelInfo.Input("model_3d_info", optional=True, advanced=True),
IO.Load3D.Input("viewport_state"),
IO.Load3DCamera.Input("camera_info", optional=True, advanced=True),
IO.Int.Input("width", default=1024, min=1, max=4096, step=1), IO.Int.Input("width", default=1024, min=1, max=4096, step=1),
IO.Int.Input("height", default=1024, min=1, max=4096, step=1), IO.Int.Input("height", default=1024, min=1, max=4096, step=1),
], ],
outputs=[ outputs=[
IO.File3DPointCloudAny.Output(display_name="model_3d"), IO.File3DPointCloudAny.Output(display_name="model_3d"),
IO.Load3DCamera.Output(display_name="camera_info"),
IO.Load3DModelInfo.Output(display_name="model_3d_info"), IO.Load3DModelInfo.Output(display_name="model_3d_info"),
IO.Load3DCamera.Output(display_name="camera_info"),
IO.Int.Output(display_name="width"), IO.Int.Output(display_name="width"),
IO.Int.Output(display_name="height"), IO.Int.Output(display_name="height"),
], ],
) )
@classmethod @classmethod
def execute(cls, model_3d: Types.File3D, image, width: int, height: int, **kwargs) -> IO.NodeOutput: def execute(cls, model_3d: Types.File3D, viewport_state, width: int, height: int, **kwargs) -> IO.NodeOutput:
filename = f"preview_pointcloud_{uuid.uuid4().hex}.{model_3d.format}" filename = f"preview_pointcloud_{uuid.uuid4().hex}.{model_3d.format}"
model_3d.save_to(os.path.join(folder_paths.get_output_directory(), filename)) model_3d.save_to(os.path.join(folder_paths.get_temp_directory(), filename))
camera_info_input = kwargs.get("camera_info", None) camera_info_input = kwargs.get("camera_info", None)
camera_info = camera_info_input if camera_info_input is not None else image['camera_info'] camera_info = camera_info_input if camera_info_input is not None else viewport_state['camera_info']
model_3d_info_input = kwargs.get("model_3d_info", None) model_3d_info_input = kwargs.get("model_3d_info", None)
model_3d_info = model_3d_info_input if model_3d_info_input is not None else image.get('model_3d_info', []) model_3d_info = model_3d_info_input if model_3d_info_input is not None else viewport_state.get('model_3d_info', [])
return IO.NodeOutput( return IO.NodeOutput(
model_3d, model_3d,
camera_info,
model_3d_info, model_3d_info,
camera_info,
width, width,
height, height,
ui=UI.PreviewUI3DAdvanced(filename, camera_info, model_3d_info), ui=UI.PreviewUI3DAdvanced(filename, camera_info, model_3d_info),