improve: GeneralSwitch - support sel_mode

This commit is contained in:
Dr.Lt.Data
2023-09-09 13:02:34 +09:00
parent e0aead5671
commit 2d278d7cf9
5 changed files with 48 additions and 17 deletions
+8 -4
View File
@@ -120,10 +120,14 @@ This takes latent as input and outputs latent as the result.
* Furthermore, LatentSender is implemented with PreviewLatent, which stores the latent in payload form within the image thumbnail.
* Due to the current structure of ComfyUI, it is unable to distinguish between SDXL latent and SD1.5/SD2.1 latent. Therefore, it generates thumbnails by decoding them using the SD1.5 method.
* Switch (image,mask), Switch (latent), Switch (SEGS) - Among multiple inputs, it selects the input designated by the selector and outputs it. The first input must be provided, while the others are optional. However, if the input specified by the selector is not connected, an error may occur.
* Switch (Any) - This is a Switch node that takes an arbitrary number of inputs and produces a single output. Its type is determined when connected to any node, and connecting inputs increases the available slots for connections.
* Inversed Switch (Any) - In contrast to `Switch (Any)`, it takes a single input and outputs one of many. Due to ComfyUI's functional limitations, the value of `select` must be determined at the time of queuing a prompt, and while it can serve as a `Primitive Node`, it cannot function properly when connected through other nodes.
* When the `Switch (Any)` and `Inversed Switch (Any)` selects are transformed into primitives, it's important to be cautious because the select range is not appropriately constrained, potentially leading to unintended behavior.
* Switches
* Switch (image,mask), Switch (latent), Switch (SEGS) - Among multiple inputs, it selects the input designated by the selector and outputs it. The first input must be provided, while the others are optional. However, if the input specified by the selector is not connected, an error may occur.
* Switch (Any) - This is a Switch node that takes an arbitrary number of inputs and produces a single output. Its type is determined when connected to any node, and connecting inputs increases the available slots for connections.
* Inversed Switch (Any) - In contrast to `Switch (Any)`, it takes a single input and outputs one of many. Due to ComfyUI's functional limitations, the value of `select` must be determined at the time of queuing a prompt, and while it can serve as a `Primitive Node`, it cannot function properly when connected through other nodes.
* Guide
* When the `Switch (Any)` and `Inversed Switch (Any)` selects are transformed into primitives, it's important to be cautious because the select range is not appropriately constrained, potentially leading to unintended behavior.
* `Switch (image,mask)`, `Switch (latent)`, `Switch (SEGS)`, `Switch (Any)` supports `sel_mode` param. The `sel_mode` sets the moment at which the `select` parameter is determined. `select_on_prompt` determines the `select` at the time of queuing the prompt, while `select_on_execution` determines it during the execution of the workflow. While `select_on_execution` offers more flexibility, it can potentially trigger workflow execution errors due to running nodes that may be impossible to execute within the limitations of ComfyUI. `select_on_prompt` bypasses this constraint by treating any inputs not selected as if they were disconnected. However, please note that when using `select_on_prompt`, the `select` can only be used with widgets or `Primitive Nodes` determined at the queue prompt.
* ImpactWildcardProcessor - The text is generated by processing the wildcard in the Text. If the mode is set to "populate", a dynamic prompt is generated with each execution and the input is filled in the second textbox. If the mode is set to "fixed", the content of the second textbox remains unchanged.
* When an image is generated with the "fixed" mode, the prompt used for that particular generation is stored in the metadata.
+21 -10
View File
@@ -319,8 +319,9 @@ app.registerExtension({
this.outputs[0].name = link_info.type;
for(let i in this.inputs) {
if(this.inputs[i].name != 'select')
this.inputs[i].type = link_info.type;
let input_i = this.inputs[i];
if(input_i.name != 'select' && input_i.name != 'sel_mode')
input_i.type = link_info.type;
}
}
}
@@ -330,6 +331,9 @@ app.registerExtension({
}
else {
// connect input
if(this.inputs[index].name == 'select' || this.inputs[index].name == 'sel_mode')
return;
if(this.inputs[0].type == '*'){
const node = app.graph.getNodeById(link_info.origin_id);
let origin_type = node.outputs[link_info.origin_slot].type;
@@ -340,8 +344,9 @@ app.registerExtension({
}
for(let i in this.inputs) {
if(this.inputs[i].name != 'select')
this.inputs[i].type = origin_type;
let input_i = this.inputs[i];
if(input_i.name != 'select' && input_i.name != 'sel_mode')
input_i.type = origin_type;
}
this.outputs[0].type = origin_type;
@@ -351,8 +356,13 @@ app.registerExtension({
}
let select_slot = this.inputs.find(x => x.name == "select");
let mode_slot = this.inputs.find(x => x.name == "sel_mode");
if (!connected && (select_slot && this.inputs.length > 2) || (!select_slot && this.inputs.length > 1)) {
let converted_count = 0;
converted_count += select_slot?1:0;
converted_count += mode_slot?1:0;
if (!connected && (this.inputs.length > 1+converted_count)) {
const stackTrace = new Error().stack;
if(
@@ -366,17 +376,18 @@ app.registerExtension({
let slot_i = 1;
for (let i = 0; i < this.inputs.length; i++) {
if(this.inputs[i].name != 'select') {
this.inputs[i].label = `${input_name}${slot_i}`
this.inputs[i].name = `${input_name}${slot_i}`
let input_i = this.inputs[i];
if(input_i.name != 'select'&& input_i.name != 'sel_mode') {
input_i.label = `${input_name}${slot_i}`
input_i.name = `${input_name}${slot_i}`
slot_i++;
}
}
let last_slot = this.inputs[this.inputs.length - 1];
if (
(last_slot.name == 'select' && this.inputs[this.inputs.length - 2].link != undefined)
|| (last_slot.name != 'select' && last_slot.link != undefined)) {
(last_slot.name == 'select' && last_slot.name != 'sel_mode' && this.inputs[this.inputs.length - 2].link != undefined)
|| (last_slot.name != 'select' && last_slot.name != 'sel_mode' && last_slot.link != undefined)) {
this.addInput(`${input_name}${slot_i}`, this.outputs[0].type);
}
+1 -1
View File
@@ -2,7 +2,7 @@ import configparser
import os
version = "V4.1"
version = "V4.2"
dependency_version = 11
+14 -1
View File
@@ -196,18 +196,31 @@ async def populate_wildcards(request):
def onprompt(json_data):
inversed_switch_info = {}
onprompt_switch_info = {}
for k, v in json_data['prompt'].items():
if v['class_type'] == 'ImpactInversedSwitch':
cls = v['class_type']
if cls == 'ImpactInversedSwitch':
inversed_switch_info[k] = v['inputs']['select']
elif cls in ['ImpactSwitch', 'LatentSwitch', 'SEGSSwitch', 'ImpactMakeImageList']:
if v['inputs']['sel_mode']:
onprompt_switch_info[k] = v['inputs']['select']
for k, v in json_data['prompt'].items():
disable_targets = set()
for kk, vv in v['inputs'].items():
if isinstance(vv, list) and len(vv) == 2:
if vv[0] in inversed_switch_info:
if vv[1]+1 != inversed_switch_info[vv[0]]:
disable_targets.add(kk)
if k in onprompt_switch_info:
selected_slot_name = f"input{onprompt_switch_info[k]}"
for kk, vv in v['inputs'].items():
if kk != selected_slot_name and kk.startswith('input'):
disable_targets.add(kk)
for kk in disable_targets:
del v['inputs'][kk]
+4 -1
View File
@@ -5,8 +5,11 @@ class GeneralSwitch:
def INPUT_TYPES(s):
return {"required": {
"select": ("INT", {"default": 1, "min": 1, "max": 999999, "step": 1}),
"input1": (any_typ,),
"sel_mode": ("BOOLEAN", {"default": True, "label_on": "select_on_prompt", "label_off": "select_on_execution", "forceInput": False}),
},
"optional": {
"input1": (any_typ,),
}
}
RETURN_TYPES = (any_typ, )