Properties of a custom node
INPUT_TYPES
, as the name suggests, defines the inputs for the node. The method returns a dict
which must contain the key required
, and may also include the keys optional
and/or hidden
. The only difference
between required
and optional
inputs is that optional
inputs can be left unconnected.
For more information on hidden
inputs, see Hidden Inputs.
Each key has, as its value, another dict
, in which key-value pairs specify the names and types of the inputs.
The types are defined by a tuple
, the first element of which defines the data type,
and the second element of which is a dict
of additional parameters.
Here we have just one required input, named image_in
, of type IMAGE
, with no additional parameters.
Note that unlike the next few attributes, this INPUT_TYPES
is a @classmethod
. This is so
that the options in dropdown widgets (like the name of the checkpoint to be loaded) can be
computed by Comfy at run time. We’ll go into this more later.
tuple
of str
defining the data types returned by the node.
If the node has no outputs this must still be provided RETURN_TYPES = ()
RETURN_TYPES = ("IMAGE",)
.
This is required for Python to make it a tuple
RETURN_TYPES
in lowercase.
examples/trivial
.
required
(and hidden
) inputs will be included;
optional
inputs will be included only if they are connected, so you should provide default values for them in the function
definition (or capture them with **kwargs
).
The function returns a tuple corresponding to the RETURN_TYPES
. This is required even if nothing is returned (return ()
).
Again, if you only have one output, remember that trailing comma return (image_out,)
!
OUTPUT_NODE = True
to specify that it is.
bool
IS_CHANGED
is passed the same arguments as the main function defined by FUNCTION
, and can return any
Python object. This object is compared with the one returned in the previous run (if any) and the node
will be considered to have changed if is_changed != is_changed_old
(this code is in execution.py
if you need to dig).
Since True == True
, a node that returns True
to say it has changed will be considered not to have! I’m sure this would
be changed in the Comfy code if it wasn’t for the fact that it might break existing nodes to do so.
To specify that your node should always be considered to have changed (which you should avoid if possible, since it
stops Comfy optimising what gets run), return float("NaN")
. This returns a NaN
value, which is not equal
to anything, even another NaN
.
A good example of actually checking for changes is the code from the built-in LoadImage node, which loads the image and returns a hash
VALIDATE_INPUTS
is defined, it will be called before the workflow begins execution.
VALIDATE_INPUTS
should return True
if the inputs are valid, or a message (as a str
) describing the error (which will prevent execution).
VALIDATE_INPUTS
will only receive inputs that are defined as constants within the workflow. Any inputs that are received from other nodes will not be available in VALIDATE_INPUTS
.VALIDATE_INPUTS
is called with only the inputs that its signature requests (those returned by inspect.getfullargspec(obj_class.VALIDATE_INPUTS).args
). Any inputs which are received in this way will not run through the default validation rules. For example, in the following snippet, the front-end will use the specified min
and max
values of the foo
input, but the back-end will not enforce it.
**kwargs
input, it will receive all available inputs and all of them will skip validation as if specified explicitly.
VALIDATE_INPUTS
method receives an argument named input_types
, it will be passed a dictionary in which the key is the name of each input which is connected to an output from another node and the value is the type of that output.
When this argument is present, all default validation of input types is skipped. Here’s an example making use of the fact that the front-end allows for the specification of multiple types: