feat GlobalSampler

This commit is contained in:
Dr.Lt.Data
2023-12-26 14:40:46 +09:00
parent fe57ea6f8a
commit fb7ebc7bdf
6 changed files with 135 additions and 51 deletions
+3
View File
@@ -54,6 +54,9 @@ This repository offers various extension nodes for ComfyUI. Nodes here have diff
* `Prompt Extractor (Inspire)`: This node reads prompt information from the image's metadata. Since it retrieves all the text, you need to directly specify the prompts to be used for `positive` and `negative` as indicated in the info.
* `Global Seed (Inspire)`: This is a node that controls the global seed without a separate connection line. It only controls when the widget's name is 'seed' or 'noise_seed'. Additionally, if 'control_before_generate' is checked, it controls the seed before executing the prompt.
* Seeds that have been converted into inputs are excluded from the target. If you want to control the seed separately, convert it into an input and control it separately.
* `Global Sampler (Inspire)`: This node is similar to GlobalSeed and can simultaneously set the sampler_name and scheduler for all nodes in the workflow.
* It applies only to nodes that have both sampler_name and scheduler, and it won't be effective if `GlobalSampler` is muted.
* If some of the `sampler_name` and `scheduler` have been converted to input and connected to Primitive node, it will not apply only to the converted widget. The widget that has not been converted to input will still be affected.
* `Bind [ImageList, PromptList] (Inspire)`: Bind Image list and zipped prompt list to export `image`, `positive`, `negative`, and `prompt_label` in a list format. If there are more prompts than images, the excess prompts are ignored, and if there are not enough, the remainder is filled with default input based on the images.
* `Wildcard Encode (Inspire)`: The combination node of [ImpactWildcardEncode](https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/ImpactWildcard.md) and BlenderNeko's [CLIP Text Encode (Advanced)](https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb).
* To use this node, you need both the [Impact Pack](https://github.com/ltdrdata/ComfyUI-Impact-Pack) and the [Advanced CLIP Text Encode]((https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb)) extensions.
+1 -1
View File
@@ -7,7 +7,7 @@
import importlib
print(f"### Loading: ComfyUI-Inspire-Pack (V0.53)")
print(f"### Loading: ComfyUI-Inspire-Pack (V0.54)")
node_list = [
"lora_block_weight",
+62 -12
View File
@@ -99,11 +99,10 @@ def control_seed(v):
def prompt_seed_update(json_data):
try:
seed_widget_map = json_data['extra_data']['extra_pnginfo']['workflow']['seed_widgets']
except:
widget_idx_map = json_data['extra_data']['extra_pnginfo']['workflow']['widget_idx_map']
except Exception:
return None
seed_widget_map = json_data['extra_data']['extra_pnginfo']['workflow']['seed_widgets']
value = None
mode = None
node = None
@@ -132,7 +131,7 @@ def prompt_seed_update(json_data):
if isinstance(v2, str) and '$GlobalSeed.value$' in v2:
v['inputs'][k2] = v2.replace('$GlobalSeed.value$', str(value))
if k not in seed_widget_map:
if k not in widget_idx_map or ('seed' not in widget_idx_map[k] and 'noise_seed' not in widget_idx_map[k]):
continue
if 'seed' in v['inputs']:
@@ -156,7 +155,7 @@ def prompt_seed_update(json_data):
def workflow_seed_update(json_data):
nodes = json_data['extra_data']['extra_pnginfo']['workflow']['nodes']
seed_widget_map = json_data['extra_data']['extra_pnginfo']['workflow']['seed_widgets']
widget_idx_map = json_data['extra_data']['extra_pnginfo']['workflow']['widget_idx_map']
prompt = json_data['prompt']
updated_seed_map = {}
@@ -167,18 +166,67 @@ def workflow_seed_update(json_data):
if node['type'] == 'GlobalSeed //Inspire':
value = prompt[node_id]['inputs']['value']
node['widgets_values'][0] = value
elif node_id in seed_widget_map:
widget_idx = seed_widget_map[node_id]
elif node_id in widget_idx_map:
widget_idx = None
seed = None
if 'noise_seed' in prompt[node_id]['inputs']:
seed = prompt[node_id]['inputs']['noise_seed']
else:
widget_idx = widget_idx_map[node_id].get('noise_seed')
elif 'seed' in prompt[node_id]['inputs']:
seed = prompt[node_id]['inputs']['seed']
widget_idx = widget_idx_map[node_id].get('seed')
node['widgets_values'][widget_idx] = seed
updated_seed_map[node_id] = seed
if widget_idx is not None:
node['widgets_values'][widget_idx] = seed
updated_seed_map[node_id] = seed
server.PromptServer.instance.send_sync("inspire-global-seed", {"id": node_id, "value": value, "seed_map": updated_seed_map})
server.PromptServer.instance.send_sync("inspire-global-seed", {"value": value, "seed_map": updated_seed_map})
def prompt_sampler_update(json_data):
try:
widget_idx_map = json_data['extra_data']['extra_pnginfo']['workflow']['widget_idx_map']
except Exception:
return None
nodes = json_data['extra_data']['extra_pnginfo']['workflow']['nodes']
prompt = json_data['prompt']
sampler_name = None
scheduler = None
updated_nodes = set()
for v in prompt.values():
cls = v.get('class_type')
if cls == 'GlobalSampler //Inspire':
sampler_name = v['inputs']['sampler_name']
scheduler = v['inputs']['scheduler']
if sampler_name is not None:
for k, v in json_data['prompt'].items():
if v.get('class_type') == 'GlobalSampler //Inspire':
continue
if ('sampler_name' in v['inputs'] and 'scheduler' in v['inputs'] and
isinstance(v['inputs']['sampler_name'], str) and 'scheduler' in v['inputs']):
v['inputs']['sampler_name'] = sampler_name
v['inputs']['scheduler'] = scheduler
server.PromptServer.instance.send_sync("inspire-node-feedback", {"node_id": k, "widget_name": 'sampler_name', "type": "text", "data": sampler_name})
server.PromptServer.instance.send_sync("inspire-node-feedback", {"node_id": k, "widget_name": 'scheduler', "type": "text", "data": scheduler})
updated_nodes.add(k)
for node in nodes:
node_id = str(node['id'])
if node_id in prompt and node_id in widget_idx_map:
sampler_widget_idx = widget_idx_map[node_id].get('sampler_name')
scheduler_widget_idx = widget_idx_map[node_id].get('scheduler')
if sampler_widget_idx is not None:
node['widgets_values'][sampler_widget_idx] = sampler_name
if scheduler_widget_idx is not None:
node['widgets_values'][scheduler_widget_idx] = scheduler
def workflow_loadimage_update(json_data):
@@ -240,6 +288,8 @@ def onprompt(json_data):
if is_changed:
workflow_seed_update(json_data)
prompt_sampler_update(json_data)
workflow_loadimage_update(json_data)
populate_wildcards(json_data)
+23
View File
@@ -335,6 +335,27 @@ class GlobalSeed:
return {}
class GlobalSampler:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, ),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, ),
}
}
RETURN_TYPES = ()
FUNCTION = "doit"
CATEGORY = "InspirePack/Prompt"
OUTPUT_NODE = True
def doit(self, **kwargs):
return {}
class BindImageListPromptList:
@classmethod
def INPUT_TYPES(s):
@@ -599,6 +620,7 @@ NODE_CLASS_MAPPINGS = {
"ZipPrompt //Inspire": ZipPrompt,
"PromptExtractor //Inspire": PromptExtractor,
"GlobalSeed //Inspire": GlobalSeed,
"GlobalSampler //Inspire": GlobalSampler,
"BindImageListPromptList //Inspire": BindImageListPromptList,
"WildcardEncode //Inspire": WildcardEncodeInspire,
"PromptBuilder //Inspire": PromptBuilder,
@@ -614,6 +636,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"ZipPrompt //Inspire": "Zip Prompt (Inspire)",
"PromptExtractor //Inspire": "Prompt Extractor (Inspire)",
"GlobalSeed //Inspire": "Global Seed (Inspire)",
"GlobalSampler //Inspire": "Global Sampler (Inspire)",
"BindImageListPromptList //Inspire": "Bind [ImageList, PromptList] (Inspire)",
"WildcardEncode //Inspire": "Wildcard Encode (Inspire)",
"PromptBuilder //Inspire": "Prompt Builder (Inspire)",
+29 -1
View File
@@ -165,4 +165,32 @@ app.registerExtension({
});
}
}
});
});
const original_queuePrompt = api.queuePrompt;
async function queuePrompt_with_widget_idxs(number, { output, workflow }) {
workflow.widget_idx_map = {};
for(let i in app.graph._nodes_by_id) {
let widgets = app.graph._nodes_by_id[i].widgets;
if(widgets) {
for(let j in widgets) {
if(['seed', 'noise_seed', 'sampler_name', 'scheduler'].includes(widgets[j].name)
&& widgets[j].type != 'converted-widget') {
if(workflow.widget_idx_map[i] == undefined) {
workflow.widget_idx_map[i] = {};
}
workflow.widget_idx_map[i][widgets[j].name] = parseInt(j);
}
}
}
}
return await original_queuePrompt.call(api, number, { output, workflow });
}
api.queuePrompt = queuePrompt_with_widget_idxs;
+17 -37
View File
@@ -4,44 +4,24 @@ function globalSeedHandler(event) {
let nodes = app.graph._nodes_by_id;
for(let i in nodes) {
let node = nodes[i];
let node = nodes[i];
if(node.type == 'GlobalSeed //Inspire') {
if(node.widgets) {
const w = node.widgets.find((w) => w.name == 'value');
const last_w = node.widgets.find((w) => w.name == 'last_seed');
last_w.value = w.value;
w.value = event.detail.value;
}
}
else
if(node.widgets) {
const w = node.widgets.find((w) => (w.name == 'seed' || w.name == 'noise_seed') && w.type == 'number');
if(w && event.detail.seed_map[node.id] != undefined) {
w.value = event.detail.seed_map[node.id];
}
}
if(node.type == 'GlobalSeed //Inspire') {
if(node.widgets) {
const w = node.widgets.find((w) => w.name == 'value');
const last_w = node.widgets.find((w) => w.name == 'last_seed');
last_w.value = w.value;
w.value = event.detail.value;
}
}
else
if(node.widgets) {
const w = node.widgets.find((w) => (w.name == 'seed' || w.name == 'noise_seed') && w.type == 'number');
if(w && event.detail.seed_map[node.id] != undefined) {
w.value = event.detail.seed_map[node.id];
}
}
}
}
api.addEventListener("inspire-global-seed", globalSeedHandler);
const original_queuePrompt = api.queuePrompt;
async function queuePrompt_with_seed(number, { output, workflow }) {
workflow.seed_widgets = {};
for(let i in app.graph._nodes_by_id) {
let widgets = app.graph._nodes_by_id[i].widgets;
if(widgets) {
for(let j in widgets) {
if((widgets[j].name == 'seed' || widgets[j].name == 'noise_seed') && widgets[j].type != 'converted-widget')
workflow.seed_widgets[i] = parseInt(j);
}
}
}
return await original_queuePrompt.call(api, number, { output, workflow });
}
api.queuePrompt = queuePrompt_with_seed;
api.addEventListener("inspire-global-seed", globalSeedHandler);