mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-04-10 02:22:33 +08:00
Add has_intermediate_output flag for nodes with interactive UI
Some checks are pending
Python Linting / Run Ruff (push) Waiting to run
Python Linting / Run Pylint (push) Waiting to run
Build package / Build Test (3.10) (push) Waiting to run
Build package / Build Test (3.11) (push) Waiting to run
Build package / Build Test (3.12) (push) Waiting to run
Build package / Build Test (3.13) (push) Waiting to run
Build package / Build Test (3.14) (push) Waiting to run
Some checks are pending
Python Linting / Run Ruff (push) Waiting to run
Python Linting / Run Pylint (push) Waiting to run
Build package / Build Test (3.10) (push) Waiting to run
Build package / Build Test (3.11) (push) Waiting to run
Build package / Build Test (3.12) (push) Waiting to run
Build package / Build Test (3.13) (push) Waiting to run
Build package / Build Test (3.14) (push) Waiting to run
This commit is contained in:
parent
2a1f402601
commit
52fd46ab04
@ -1373,6 +1373,7 @@ class NodeInfoV1:
|
|||||||
price_badge: dict | None = None
|
price_badge: dict | None = None
|
||||||
search_aliases: list[str]=None
|
search_aliases: list[str]=None
|
||||||
essentials_category: str=None
|
essentials_category: str=None
|
||||||
|
has_intermediate_output: bool=None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -1496,6 +1497,16 @@ class Schema:
|
|||||||
"""When True, all inputs from the prompt will be passed to the node as kwargs, even if not defined in the schema."""
|
"""When True, all inputs from the prompt will be passed to the node as kwargs, even if not defined in the schema."""
|
||||||
essentials_category: str | None = None
|
essentials_category: str | None = None
|
||||||
"""Optional category for the Essentials tab. Path-based like category field (e.g., 'Basic', 'Image Tools/Editing')."""
|
"""Optional category for the Essentials tab. Path-based like category field (e.g., 'Basic', 'Image Tools/Editing')."""
|
||||||
|
has_intermediate_output: bool=False
|
||||||
|
"""Flags this node as having intermediate output that should persist across page refreshes.
|
||||||
|
|
||||||
|
Nodes with this flag behave like output nodes (their UI results are cached and resent
|
||||||
|
to the frontend) but do NOT automatically get added to the execution list. This means
|
||||||
|
they will only execute if they are on the dependency path of a real output node.
|
||||||
|
|
||||||
|
Use this for nodes with interactive/operable UI regions that produce intermediate outputs
|
||||||
|
(e.g., Image Crop, Painter) rather than final outputs (e.g., Save Image).
|
||||||
|
"""
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
'''Validate the schema:
|
'''Validate the schema:
|
||||||
@ -1595,6 +1606,7 @@ class Schema:
|
|||||||
category=self.category,
|
category=self.category,
|
||||||
description=self.description,
|
description=self.description,
|
||||||
output_node=self.is_output_node,
|
output_node=self.is_output_node,
|
||||||
|
has_intermediate_output=self.has_intermediate_output,
|
||||||
deprecated=self.is_deprecated,
|
deprecated=self.is_deprecated,
|
||||||
experimental=self.is_experimental,
|
experimental=self.is_experimental,
|
||||||
dev_only=self.is_dev_only,
|
dev_only=self.is_dev_only,
|
||||||
@ -1886,6 +1898,14 @@ class _ComfyNodeBaseInternal(_ComfyNodeInternal):
|
|||||||
cls.GET_SCHEMA()
|
cls.GET_SCHEMA()
|
||||||
return cls._OUTPUT_NODE
|
return cls._OUTPUT_NODE
|
||||||
|
|
||||||
|
_HAS_INTERMEDIATE_OUTPUT = None
|
||||||
|
@final
|
||||||
|
@classproperty
|
||||||
|
def HAS_INTERMEDIATE_OUTPUT(cls): # noqa
|
||||||
|
if cls._HAS_INTERMEDIATE_OUTPUT is None:
|
||||||
|
cls.GET_SCHEMA()
|
||||||
|
return cls._HAS_INTERMEDIATE_OUTPUT
|
||||||
|
|
||||||
_INPUT_IS_LIST = None
|
_INPUT_IS_LIST = None
|
||||||
@final
|
@final
|
||||||
@classproperty
|
@classproperty
|
||||||
@ -1978,6 +1998,8 @@ class _ComfyNodeBaseInternal(_ComfyNodeInternal):
|
|||||||
cls._API_NODE = schema.is_api_node
|
cls._API_NODE = schema.is_api_node
|
||||||
if cls._OUTPUT_NODE is None:
|
if cls._OUTPUT_NODE is None:
|
||||||
cls._OUTPUT_NODE = schema.is_output_node
|
cls._OUTPUT_NODE = schema.is_output_node
|
||||||
|
if cls._HAS_INTERMEDIATE_OUTPUT is None:
|
||||||
|
cls._HAS_INTERMEDIATE_OUTPUT = schema.has_intermediate_output
|
||||||
if cls._INPUT_IS_LIST is None:
|
if cls._INPUT_IS_LIST is None:
|
||||||
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:
|
||||||
|
|||||||
@ -762,6 +762,7 @@ class GLSLShader(io.ComfyNode):
|
|||||||
"Apply GLSL ES fragment shaders to images. "
|
"Apply GLSL ES fragment shaders to images. "
|
||||||
"u_resolution (vec2) is always available."
|
"u_resolution (vec2) is always available."
|
||||||
),
|
),
|
||||||
|
has_intermediate_output=True,
|
||||||
inputs=[
|
inputs=[
|
||||||
io.String.Input(
|
io.String.Input(
|
||||||
"fragment_shader",
|
"fragment_shader",
|
||||||
|
|||||||
@ -59,6 +59,7 @@ class ImageCropV2(IO.ComfyNode):
|
|||||||
display_name="Image Crop",
|
display_name="Image Crop",
|
||||||
category="image/transform",
|
category="image/transform",
|
||||||
essentials_category="Image Tools",
|
essentials_category="Image Tools",
|
||||||
|
has_intermediate_output=True,
|
||||||
inputs=[
|
inputs=[
|
||||||
IO.Image.Input("image"),
|
IO.Image.Input("image"),
|
||||||
IO.BoundingBox.Input("crop_region", component="ImageCrop"),
|
IO.BoundingBox.Input("crop_region", component="ImageCrop"),
|
||||||
|
|||||||
@ -30,6 +30,7 @@ class PainterNode(io.ComfyNode):
|
|||||||
node_id="Painter",
|
node_id="Painter",
|
||||||
display_name="Painter",
|
display_name="Painter",
|
||||||
category="image",
|
category="image",
|
||||||
|
has_intermediate_output=True,
|
||||||
inputs=[
|
inputs=[
|
||||||
io.Image.Input(
|
io.Image.Input(
|
||||||
"image",
|
"image",
|
||||||
|
|||||||
@ -1071,7 +1071,7 @@ async def validate_prompt(prompt_id, prompt, partial_execution_list: Union[list[
|
|||||||
}
|
}
|
||||||
return (False, error, [], {})
|
return (False, error, [], {})
|
||||||
|
|
||||||
if hasattr(class_, 'OUTPUT_NODE') and class_.OUTPUT_NODE is True:
|
if (hasattr(class_, 'OUTPUT_NODE') and class_.OUTPUT_NODE is True) or getattr(class_, 'HAS_INTERMEDIATE_OUTPUT', False):
|
||||||
if partial_execution_list is None or x in partial_execution_list:
|
if partial_execution_list is None or x in partial_execution_list:
|
||||||
outputs.add(x)
|
outputs.add(x)
|
||||||
|
|
||||||
|
|||||||
@ -709,6 +709,11 @@ class PromptServer():
|
|||||||
else:
|
else:
|
||||||
info['output_node'] = False
|
info['output_node'] = False
|
||||||
|
|
||||||
|
if hasattr(obj_class, 'HAS_INTERMEDIATE_OUTPUT') and obj_class.HAS_INTERMEDIATE_OUTPUT == True:
|
||||||
|
info['has_intermediate_output'] = True
|
||||||
|
else:
|
||||||
|
info['has_intermediate_output'] = False
|
||||||
|
|
||||||
if hasattr(obj_class, 'CATEGORY'):
|
if hasattr(obj_class, 'CATEGORY'):
|
||||||
info['category'] = obj_class.CATEGORY
|
info['category'] = obj_class.CATEGORY
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user