Multiple inputs
This PR allows inputs to have multiple connections.
It works by adding new inputs when you make the connection, this way there is always one free input to connect, in the frontend the names of the inputs are changed by appending [0], [1], ... to the name, later the backend merge those inputs in an array.
Example:
Code of the custom node used in the example:
class SelectItem:
CATEGORY = "_for_testing"
RETURN_TYPES = ("*",)
FUNCTION = "run"
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"index": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
"only_active": (["true", "false"], ),
},
"optional": {
"values": ("*", {"multiple": True}),
},
}
def run(self, index, only_active, values=[]):
selected = None
if only_active == "true":
values = [value for value in values if value is not None]
index = index % len(values)
selected = values[index]
return (selected,)
NODE_CLASS_MAPPINGS = {
"SelectItem": SelectItem,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"SelectItem": "Select Item",
}
It accepts multiple values and select one based on an index, in this case the index was transformed from widget to input and is using a random value, so each generation gets a random size.
P.S.: This example code uses the generic type from the #1566 but you get the idea.
Very useful, please merge
Very useful, please merge
again, this is already a solved thing inside the core. You just use KWARGS from python.
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"index": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
"only_active": (["true", "false"], ),
}
}
def run(self, index, only_active, **kw):
selected = None
if only_active == "true":
values = [value for value in values if value is not None]
index = index % len(values)
key = kw.keys()[index]
selected = kw[key]
return (selected,)
Both things you asked to be pushed are: 10+ months old and require core changes but are not required if you actually know how to use python.
Is there clear documentation on how to have multiple inputs inside core? I haven't found that anywhere, other than a link to Dynamic Inputs here: https://github.com/Suzie1/ComfyUI_Guide_To_Making_Custom_Nodes/wiki/js-extensions#dynamic-widgets
Is that the recommended workflow for handling multiple inputs in a single input?
For the people asking to merge it, please be patient, it is an old code, I just came back to work with comfyui, I have to catch up with the news, I'll check my old PRs and see if they are needed with the current state of comfyui, a lot have changed since I wrote this PR, but if this is still a missing feature I'll see for it to work with the current version of comfyui.
Is there clear documentation on how to have multiple inputs inside core? I haven't found that anywhere, other than a link to Dynamic Inputs here: https://github.com/Suzie1/ComfyUI_Guide_To_Making_Custom_Nodes/wiki/js-extensions#dynamic-widgets
Is that the recommended workflow for handling multiple inputs in a single input?
I didnt want to do a PR for the docs, but hopefully here is a clean, clear example:
https://github.com/cozy-comfyui/cozy_ex_dynamic
I cut it down to just a single type and indexing at 1.
I feel a few more of the mechanisms, especially on the JS side, could be done as one off examples.
HTH.
Thanks for the link to the example!
i did give this a try, and unfortunately it didn't work when I had multiple inputs for the node that weren't dynamic - it started renaming things funky. Now that could be because I had other stuff in my js file that was messing with it.. but have you tried this with more inputs, or with dynamic inputs that come after previous inputs?
@shhlife for now I updated my fork, the branch beta has all my changes https://github.com/jn-jairo/ComfyUI/tree/beta I'm working on an extension (custom nodes) to patch these changes into ComfyUI.
The code on the branch beta works well with the vanilla ComfyUI, but I cannot guarantee it will work with other extensions.
I have some custom nodes at https://github.com/jn-jairo/jn_node_suite_comfyui that use this feature, this repository is temporary, I'm working on another repository for the new version that is compatible with the new comfy register, but I use those nodes and they work fine, even in my most complex workflow.
Thanks for the link to the example!
i did give this a try, and unfortunately it didn't work when I had multiple inputs for the node that weren't dynamic - it started renaming things funky. Now that could be because I had other stuff in my js file that was messing with it.. but have you tried this with more inputs, or with dynamic inputs that come after previous inputs?
Correct. The example itself is for only the dynamic mechanism, not adding statics to it. Basically a route node. It is only setup to be a single prefix/type for all the inputs.
I can potentially make another example, but the one that exists is only to that exact problem of making and using the dynamic input itself -- the user is free to employ that mechanism how they need (with other inputs, e.g.)
For the more complex examples with additional inputs, etc... I recommend looking over the solutions in mtb's repo, kijai's repo, my repo, et. al.
FYI:
def run(self, index, only_active, values=[]):
selected = None
In Python, using mutable default arguments like lists or dictionaries can lead to unexpected behavior. You should initialize those parameters (list, dict) to None and recast in the body:
def run(self, index, only_active, values=None):
if values is None:
values = []
Fredrik Lundh can explain it way better than I: https://web.archive.org/web/20200221224620id_/http://effbot.org/zone/default-values.htm
FYI:
def run(self, index, only_active, values=[]): selected = NoneIn Python, using mutable default arguments like lists or dictionaries can lead to unexpected behavior. You should initialize those parameters (list, dict) to None and recast in the body:
def run(self, index, only_active, values=None): if values is None: values = []Fredrik Lundh can explain it way better than I: https://web.archive.org/web/20200221224620id_/http://effbot.org/zone/default-values.htm
Python is a stupid language 🙄
frontend is replaced by https://github.com/Comfy-Org/ComfyUI_frontend now
Let's be honest, no one cared about this PR in this repo, and no one will care about it if I redo the PR in the other repo, so I won't waste my time.
see reply at https://github.com/comfyanonymous/ComfyUI/pull/2015#issuecomment-2376050796