mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-06-16 21:09:48 +08:00
Add cache no cascade property
This commit is contained in:
parent
d3767dae9e
commit
513d9e995f
@ -1600,6 +1600,8 @@ class Schema:
|
|||||||
"""Optional client-evaluated pricing badge declaration for this node."""
|
"""Optional client-evaluated pricing badge declaration for this node."""
|
||||||
not_idempotent: bool=False
|
not_idempotent: bool=False
|
||||||
"""Flags a node as not idempotent; when True, the node will run and not reuse the cached outputs when identical inputs are provided on a different node in the graph."""
|
"""Flags a node as not idempotent; when True, the node will run and not reuse the cached outputs when identical inputs are provided on a different node in the graph."""
|
||||||
|
cache_no_cascade: bool=False
|
||||||
|
"""When True, changes to this node's widget inputs re-run this node but do not invalidate the caches of downstream nodes. Use for passthrough nodes whose widget inputs only affect side effects (e.g. a save node's filename), not the data passed to its outputs."""
|
||||||
enable_expand: bool=False
|
enable_expand: bool=False
|
||||||
"""Flags a node as expandable, allowing NodeOutput to include 'expand' property."""
|
"""Flags a node as expandable, allowing NodeOutput to include 'expand' property."""
|
||||||
accept_all_inputs: bool=False
|
accept_all_inputs: bool=False
|
||||||
@ -2065,6 +2067,14 @@ class _ComfyNodeBaseInternal(_ComfyNodeInternal):
|
|||||||
cls.GET_SCHEMA()
|
cls.GET_SCHEMA()
|
||||||
return cls._NOT_IDEMPOTENT
|
return cls._NOT_IDEMPOTENT
|
||||||
|
|
||||||
|
_CACHE_NO_CASCADE = None
|
||||||
|
@final
|
||||||
|
@classproperty
|
||||||
|
def CACHE_NO_CASCADE(cls): # noqa
|
||||||
|
if cls._CACHE_NO_CASCADE is None:
|
||||||
|
cls.GET_SCHEMA()
|
||||||
|
return cls._CACHE_NO_CASCADE
|
||||||
|
|
||||||
_ACCEPT_ALL_INPUTS = None
|
_ACCEPT_ALL_INPUTS = None
|
||||||
@final
|
@final
|
||||||
@classproperty
|
@classproperty
|
||||||
@ -2115,6 +2125,8 @@ class _ComfyNodeBaseInternal(_ComfyNodeInternal):
|
|||||||
cls._INPUT_IS_LIST = schema.is_input_list
|
cls._INPUT_IS_LIST = schema.is_input_list
|
||||||
if cls._NOT_IDEMPOTENT is None:
|
if cls._NOT_IDEMPOTENT is None:
|
||||||
cls._NOT_IDEMPOTENT = schema.not_idempotent
|
cls._NOT_IDEMPOTENT = schema.not_idempotent
|
||||||
|
if cls._CACHE_NO_CASCADE is None:
|
||||||
|
cls._CACHE_NO_CASCADE = schema.cache_no_cascade
|
||||||
if cls._ACCEPT_ALL_INPUTS is None:
|
if cls._ACCEPT_ALL_INPUTS is None:
|
||||||
cls._ACCEPT_ALL_INPUTS = schema.accept_all_inputs
|
cls._ACCEPT_ALL_INPUTS = schema.accept_all_inputs
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import nodes
|
|||||||
from comfy_execution.graph_utils import is_link
|
from comfy_execution.graph_utils import is_link
|
||||||
|
|
||||||
NODE_CLASS_CONTAINS_UNIQUE_ID: Dict[str, bool] = {}
|
NODE_CLASS_CONTAINS_UNIQUE_ID: Dict[str, bool] = {}
|
||||||
|
NODE_CLASS_CACHE_NO_CASCADE: Dict[str, bool] = {}
|
||||||
|
|
||||||
|
|
||||||
def include_unique_id_in_input(class_type: str) -> bool:
|
def include_unique_id_in_input(class_type: str) -> bool:
|
||||||
@ -23,6 +24,16 @@ def include_unique_id_in_input(class_type: str) -> bool:
|
|||||||
NODE_CLASS_CONTAINS_UNIQUE_ID[class_type] = "UNIQUE_ID" in class_def.INPUT_TYPES().get("hidden", {}).values()
|
NODE_CLASS_CONTAINS_UNIQUE_ID[class_type] = "UNIQUE_ID" in class_def.INPUT_TYPES().get("hidden", {}).values()
|
||||||
return NODE_CLASS_CONTAINS_UNIQUE_ID[class_type]
|
return NODE_CLASS_CONTAINS_UNIQUE_ID[class_type]
|
||||||
|
|
||||||
|
|
||||||
|
def is_cache_no_cascade(class_type: str) -> bool:
|
||||||
|
"""Whether changes to this node's widget inputs should not invalidate downstream caches."""
|
||||||
|
if class_type in NODE_CLASS_CACHE_NO_CASCADE:
|
||||||
|
return NODE_CLASS_CACHE_NO_CASCADE[class_type]
|
||||||
|
class_def = nodes.NODE_CLASS_MAPPINGS[class_type]
|
||||||
|
NODE_CLASS_CACHE_NO_CASCADE[class_type] = bool(getattr(class_def, "CACHE_NO_CASCADE", False))
|
||||||
|
return NODE_CLASS_CACHE_NO_CASCADE[class_type]
|
||||||
|
|
||||||
|
|
||||||
class CacheKeySet(ABC):
|
class CacheKeySet(ABC):
|
||||||
def __init__(self, dynprompt, node_ids, is_changed_cache):
|
def __init__(self, dynprompt, node_ids, is_changed_cache):
|
||||||
self.keys = {}
|
self.keys = {}
|
||||||
@ -101,12 +112,12 @@ class CacheKeySetInputSignature(CacheKeySet):
|
|||||||
async def get_node_signature(self, dynprompt, node_id):
|
async def get_node_signature(self, dynprompt, node_id):
|
||||||
signature = []
|
signature = []
|
||||||
ancestors, order_mapping = self.get_ordered_ancestry(dynprompt, node_id)
|
ancestors, order_mapping = self.get_ordered_ancestry(dynprompt, node_id)
|
||||||
signature.append(await self.get_immediate_node_signature(dynprompt, node_id, order_mapping))
|
signature.append(await self.get_immediate_node_signature(dynprompt, node_id, order_mapping, as_ancestor=False))
|
||||||
for ancestor_id in ancestors:
|
for ancestor_id in ancestors:
|
||||||
signature.append(await self.get_immediate_node_signature(dynprompt, ancestor_id, order_mapping))
|
signature.append(await self.get_immediate_node_signature(dynprompt, ancestor_id, order_mapping, as_ancestor=True))
|
||||||
return to_hashable(signature)
|
return to_hashable(signature)
|
||||||
|
|
||||||
async def get_immediate_node_signature(self, dynprompt, node_id, ancestor_order_mapping):
|
async def get_immediate_node_signature(self, dynprompt, node_id, ancestor_order_mapping, as_ancestor=False):
|
||||||
if not dynprompt.has_node(node_id):
|
if not dynprompt.has_node(node_id):
|
||||||
# This node doesn't exist -- we can't cache it.
|
# This node doesn't exist -- we can't cache it.
|
||||||
return [float("NaN")]
|
return [float("NaN")]
|
||||||
@ -117,12 +128,13 @@ class CacheKeySetInputSignature(CacheKeySet):
|
|||||||
if self.include_node_id_in_input() or (hasattr(class_def, "NOT_IDEMPOTENT") and class_def.NOT_IDEMPOTENT) or include_unique_id_in_input(class_type):
|
if self.include_node_id_in_input() or (hasattr(class_def, "NOT_IDEMPOTENT") and class_def.NOT_IDEMPOTENT) or include_unique_id_in_input(class_type):
|
||||||
signature.append(node_id)
|
signature.append(node_id)
|
||||||
inputs = node["inputs"]
|
inputs = node["inputs"]
|
||||||
|
skip_widgets = as_ancestor and is_cache_no_cascade(class_type)
|
||||||
for key in sorted(inputs.keys()):
|
for key in sorted(inputs.keys()):
|
||||||
if is_link(inputs[key]):
|
if is_link(inputs[key]):
|
||||||
(ancestor_id, ancestor_socket) = inputs[key]
|
(ancestor_id, ancestor_socket) = inputs[key]
|
||||||
ancestor_index = ancestor_order_mapping[ancestor_id]
|
ancestor_index = ancestor_order_mapping[ancestor_id]
|
||||||
signature.append((key,("ANCESTOR", ancestor_index, ancestor_socket)))
|
signature.append((key,("ANCESTOR", ancestor_index, ancestor_socket)))
|
||||||
else:
|
elif not skip_widgets:
|
||||||
signature.append((key, inputs[key]))
|
signature.append((key, inputs[key]))
|
||||||
return signature
|
return signature
|
||||||
|
|
||||||
|
|||||||
@ -168,6 +168,7 @@ class SaveAudio(IO.ComfyNode):
|
|||||||
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
||||||
is_deprecated=True,
|
is_deprecated=True,
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[IO.Audio.Output("audio")]
|
outputs=[IO.Audio.Output("audio")]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -198,6 +199,7 @@ class SaveAudioMP3(IO.ComfyNode):
|
|||||||
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
||||||
is_deprecated=True,
|
is_deprecated=True,
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[IO.Audio.Output("audio")]
|
outputs=[IO.Audio.Output("audio")]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -229,6 +231,7 @@ class SaveAudioOpus(IO.ComfyNode):
|
|||||||
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
||||||
is_deprecated=True,
|
is_deprecated=True,
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[IO.Audio.Output("audio")]
|
outputs=[IO.Audio.Output("audio")]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -258,20 +261,25 @@ class SaveAudioAdvanced(IO.ComfyNode):
|
|||||||
IO.String.Input(
|
IO.String.Input(
|
||||||
"filename_prefix",
|
"filename_prefix",
|
||||||
default="audio/ComfyUI",
|
default="audio/ComfyUI",
|
||||||
tooltip=(
|
tooltip=("The prefix for the file to save. May include formatting tokens such as %date:yyyy-MM-dd%."),
|
||||||
"The prefix for the file to save. May include formatting tokens "
|
|
||||||
"such as %date:yyyy-MM-dd%."
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
IO.DynamicCombo.Input(
|
IO.DynamicCombo.Input(
|
||||||
"format",
|
"format",
|
||||||
options=[
|
options=[
|
||||||
IO.DynamicCombo.Option("flac", []),
|
IO.DynamicCombo.Option("flac", []),
|
||||||
IO.DynamicCombo.Option("mp3", [
|
IO.DynamicCombo.Option("mp3", [
|
||||||
IO.Combo.Input("quality", options=["V0", "128k", "320k"], default="V0"),
|
IO.Combo.Input(
|
||||||
|
"quality",
|
||||||
|
options=["V0", "128k", "320k"],
|
||||||
|
default="V0",
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
IO.DynamicCombo.Option("opus", [
|
IO.DynamicCombo.Option("opus", [
|
||||||
IO.Combo.Input("quality", options=["64k", "96k", "128k", "192k", "320k"], default="128k"),
|
IO.Combo.Input(
|
||||||
|
"quality",
|
||||||
|
options=["64k", "96k", "128k", "192k", "320k"],
|
||||||
|
default="128k",
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
tooltip="The file format in which to save the audio.",
|
tooltip="The file format in which to save the audio.",
|
||||||
@ -279,6 +287,8 @@ class SaveAudioAdvanced(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
|
outputs=[IO.Audio.Output("audio")],
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -289,7 +299,7 @@ class SaveAudioAdvanced(IO.ComfyNode):
|
|||||||
ui=UI.AudioSaveHelper.get_save_audio_ui(audio, filename_prefix=filename_prefix, cls=cls, format=file_format, quality=quality)
|
ui=UI.AudioSaveHelper.get_save_audio_ui(audio, filename_prefix=filename_prefix, cls=cls, format=file_format, quality=quality)
|
||||||
else:
|
else:
|
||||||
ui=UI.AudioSaveHelper.get_save_audio_ui(audio, filename_prefix=filename_prefix, cls=cls, format=file_format)
|
ui=UI.AudioSaveHelper.get_save_audio_ui(audio, filename_prefix=filename_prefix, cls=cls, format=file_format)
|
||||||
return IO.NodeOutput(ui=ui)
|
return IO.NodeOutput(audio, ui=ui)
|
||||||
|
|
||||||
|
|
||||||
class PreviewAudio(IO.ComfyNode):
|
class PreviewAudio(IO.ComfyNode):
|
||||||
|
|||||||
@ -214,6 +214,7 @@ class SaveAnimatedWEBP(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[IO.Image.Output(display_name="images")]
|
outputs=[IO.Image.Output(display_name="images")]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -249,6 +250,7 @@ class SaveAnimatedPNG(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[IO.Image.Output(display_name="images")]
|
outputs=[IO.Image.Output(display_name="images")]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -513,6 +515,7 @@ class SaveSVGNode(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[IO.SVG.Output("svg")],
|
outputs=[IO.SVG.Output("svg")],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1156,40 +1159,42 @@ class SaveImageAdvanced(IO.ComfyNode):
|
|||||||
IO.String.Input(
|
IO.String.Input(
|
||||||
"filename_prefix",
|
"filename_prefix",
|
||||||
default="ComfyUI",
|
default="ComfyUI",
|
||||||
tooltip=(
|
tooltip=("The prefix for the file to save. May include formatting tokens such as %date:yyyy-MM-dd% or %Empty Latent Image.width%."),
|
||||||
"The prefix for the file to save. May include formatting tokens "
|
|
||||||
"such as %date:yyyy-MM-dd% or %Empty Latent Image.width%."
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
IO.DynamicCombo.Input(
|
IO.DynamicCombo.Input(
|
||||||
"format",
|
"format",
|
||||||
options=[
|
options=[
|
||||||
IO.DynamicCombo.Option("png", [
|
IO.DynamicCombo.Option("png", [
|
||||||
IO.Combo.Input("bit_depth", options=["8-bit", "16-bit"],
|
IO.Combo.Input(
|
||||||
default="8-bit", advanced=True),
|
"bit_depth",
|
||||||
IO.Combo.Input("input_color_space", options=["sRGB"],
|
options=["8-bit", "16-bit"],
|
||||||
default="sRGB", advanced=True),
|
default="8-bit",
|
||||||
|
advanced=True,
|
||||||
|
),
|
||||||
|
IO.Combo.Input(
|
||||||
|
"input_color_space",
|
||||||
|
options=["sRGB"],
|
||||||
|
default="sRGB",
|
||||||
|
advanced=True,
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
IO.DynamicCombo.Option("exr", [
|
IO.DynamicCombo.Option("exr", [
|
||||||
IO.Combo.Input("bit_depth", options=["32-bit float"],
|
IO.Combo.Input(
|
||||||
default="32-bit float", advanced=True),
|
"bit_depth",
|
||||||
|
options=["32-bit float"],
|
||||||
|
default="32-bit float",
|
||||||
|
advanced=True,
|
||||||
|
),
|
||||||
IO.Combo.Input(
|
IO.Combo.Input(
|
||||||
"input_color_space",
|
"input_color_space",
|
||||||
options=["sRGB", "HDR", "linear"],
|
options=["sRGB", "HDR", "linear"],
|
||||||
default="sRGB",
|
default="sRGB",
|
||||||
advanced=True,
|
advanced=True,
|
||||||
tooltip=(
|
tooltip=(
|
||||||
"Colorspace of the input tensor. The EXR is "
|
"Colorspace of the input tensor. The EXR is always written as scene-linear in the matching gamut.\n"
|
||||||
"always written as scene-linear in the matching "
|
"sRGB — input is sRGB-encoded Rec.709; the inverse sRGB EOTF is applied.\n"
|
||||||
"gamut.\n"
|
"HDR — input is HLG-encoded Rec.2020 (BT.2100); the inverse HLG OETF is applied to get scene-linear light.\n"
|
||||||
" 'sRGB' — input is sRGB-encoded Rec.709; "
|
"linear — input is already scene-linear (Rec.709 primaries); written through unchanged. Use this for renderer/compositor output."
|
||||||
"the inverse sRGB EOTF is applied.\n"
|
|
||||||
" 'HDR' — input is HLG-encoded Rec.2020 "
|
|
||||||
"(BT.2100); the inverse HLG OETF is applied "
|
|
||||||
"to get scene-linear light.\n"
|
|
||||||
" 'linear' — input is already scene-linear "
|
|
||||||
"(Rec.709 primaries); written through unchanged. "
|
|
||||||
"Use this for renderer/compositor output."
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
@ -1199,6 +1204,7 @@ class SaveImageAdvanced(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
hidden=[IO.Hidden.prompt, IO.Hidden.extra_pnginfo],
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[IO.Image.Output(display_name="images")]
|
outputs=[IO.Image.Output(display_name="images")]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -23,10 +23,18 @@ class SaveWEBM(io.ComfyNode):
|
|||||||
io.String.Input("filename_prefix", default="ComfyUI"),
|
io.String.Input("filename_prefix", default="ComfyUI"),
|
||||||
io.Combo.Input("codec", options=["vp9", "av1"]),
|
io.Combo.Input("codec", options=["vp9", "av1"]),
|
||||||
io.Float.Input("fps", default=24.0, min=0.01, max=1000.0, step=0.01),
|
io.Float.Input("fps", default=24.0, min=0.01, max=1000.0, step=0.01),
|
||||||
io.Float.Input("crf", default=32.0, min=0, max=63.0, step=1, tooltip="Higher crf means lower quality with a smaller file size, lower crf means higher quality higher filesize."),
|
io.Float.Input(
|
||||||
|
"crf",
|
||||||
|
default=32.0,
|
||||||
|
min=0,
|
||||||
|
max=63.0,
|
||||||
|
step=1,
|
||||||
|
tooltip="Higher crf means lower quality with a smaller file size, lower crf means higher quality higher filesize.",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
hidden=[io.Hidden.prompt, io.Hidden.extra_pnginfo],
|
hidden=[io.Hidden.prompt, io.Hidden.extra_pnginfo],
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[io.Image.Output(display_name="images")]
|
outputs=[io.Image.Output(display_name="images")]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -90,6 +98,7 @@ class SaveVideo(io.ComfyNode):
|
|||||||
],
|
],
|
||||||
hidden=[io.Hidden.prompt, io.Hidden.extra_pnginfo],
|
hidden=[io.Hidden.prompt, io.Hidden.extra_pnginfo],
|
||||||
is_output_node=True,
|
is_output_node=True,
|
||||||
|
cache_no_cascade=True,
|
||||||
outputs=[io.Video.Output("video")],
|
outputs=[io.Video.Output("video")],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
16
nodes.py
16
nodes.py
@ -483,15 +483,17 @@ class SaveLatent:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {"required": { "samples": ("LATENT", ),
|
return { "required": {
|
||||||
"filename_prefix": ("STRING", {"default": "latents/ComfyUI"})},
|
"samples": ("LATENT",),
|
||||||
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
"filename_prefix": ("STRING", {"default": "latents/ComfyUI"})},
|
||||||
}
|
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
||||||
|
}
|
||||||
RETURN_TYPES = ("LATENT",)
|
RETURN_TYPES = ("LATENT",)
|
||||||
RETURN_NAMES = ("samples",)
|
RETURN_NAMES = ("samples",)
|
||||||
FUNCTION = "save"
|
FUNCTION = "save"
|
||||||
|
|
||||||
OUTPUT_NODE = True
|
OUTPUT_NODE = True
|
||||||
|
CACHE_NO_CASCADE = True
|
||||||
|
|
||||||
CATEGORY = "experimental"
|
CATEGORY = "experimental"
|
||||||
|
|
||||||
@ -1632,7 +1634,10 @@ class SaveImage:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"images": ("IMAGE", {"tooltip": "The images to save."}),
|
"images": ("IMAGE", {"tooltip": "The images to save."}),
|
||||||
"filename_prefix": ("STRING", {"default": "ComfyUI", "tooltip": "The prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% or %Empty Latent Image.width% to include values from nodes."})
|
"filename_prefix": ("STRING", {
|
||||||
|
"default": "ComfyUI",
|
||||||
|
"tooltip": "The prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% or %Empty Latent Image.width% to include values from nodes."
|
||||||
|
})
|
||||||
},
|
},
|
||||||
"hidden": {
|
"hidden": {
|
||||||
"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"
|
"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"
|
||||||
@ -1644,6 +1649,7 @@ class SaveImage:
|
|||||||
FUNCTION = "save_images"
|
FUNCTION = "save_images"
|
||||||
|
|
||||||
OUTPUT_NODE = True
|
OUTPUT_NODE = True
|
||||||
|
CACHE_NO_CASCADE = True
|
||||||
|
|
||||||
CATEGORY = "image"
|
CATEGORY = "image"
|
||||||
ESSENTIALS_CATEGORY = "Basics"
|
ESSENTIALS_CATEGORY = "Basics"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user