feat: GlobalSeed

This commit is contained in:
Dr.Lt.Data
2023-09-14 19:52:39 +09:00
parent 353595c942
commit 4a5d8a2c73
6 changed files with 150 additions and 4 deletions
+1 -1
View File
@@ -157,4 +157,4 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/
+2 -1
View File
@@ -31,7 +31,8 @@ This repository offers various extension nodes for ComfyUI. Nodes here have diff
* `Zip Prompt (Inspire)`: Create ZIPPED_PROMPT from positive, negative, and name_opt.
* If name_opt is omitted, it will be considered as an empty name.
* `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.' Additionally, if 'control_before_generate' is checked, it controls the seed before executing the prompt.
* NOTE: In the case of seed widgets converted into input slots, normal operation is not guaranteed.
## Credits
+2 -1
View File
@@ -7,13 +7,14 @@
import importlib
print(f"### Loading: ComfyUI-Inspire-Pack (V0.11.1)")
print(f"### Loading: ComfyUI-Inspire-Pack (V0.12)")
node_list = [
"lora_block_weight",
"segs_support",
"a1111_compat",
"prompt_support",
"inspire_server",
]
NODE_CLASS_MAPPINGS = {}
+74
View File
@@ -0,0 +1,74 @@
import random
import server
def control_seed(node_id, v):
action = v['inputs']['action']
value = v['inputs']['value']
if action == 'increment':
value += 1
elif action == 'decrement':
value -= 1
elif action == 'randomize':
value = random.randint(0, 1125899906842624)
v['inputs']['value'] = value
server.PromptServer.instance.send_sync("inspire-global-seed", {"id": node_id, "value": value})
return value
def prompt_seed_update(json_data):
value = None
mode = None
node = None
for k, v in json_data['prompt'].items():
cls = v['class_type']
if cls == 'GlobalSeed //Inspire':
mode = v['inputs']['mode']
node = k, v
# control before generated
if mode is not None and mode:
value = control_seed(node[0], node[1])
if value is not None:
for k, v in json_data['prompt'].items():
if 'seed' in v['inputs']:
if isinstance(v['inputs']['seed'], int):
v['inputs']['seed'] = value
# control after generated
if mode is not None and not mode:
control_seed(node[0], node[1])
return value
def workflow_seed_update(json_data, value):
nodes = json_data['extra_data']['extra_pnginfo']['workflow']['nodes']
seed_widget_map = json_data['extra_data']['extra_pnginfo']['workflow']['seed_widgets']
for node in nodes:
if node['type'] == 'GlobalSeed //Inspire':
node['widgets_values'][0] = value
elif str(node['id']) in seed_widget_map:
node_id = str(node['id'])
widget_idx = seed_widget_map[node_id]
node['widgets_values'][widget_idx] = value
def onprompt(json_data):
value = prompt_seed_update(json_data)
workflow_seed_update(json_data, value)
return json_data
server.PromptServer.instance.add_on_prompt_handler(onprompt)
NODE_CLASS_MAPPINGS = {}
NODE_DISPLAY_NAME_MAPPINGS = {}
+46
View File
@@ -0,0 +1,46 @@
import { api } from "../../scripts/api.js";
function globalSeedHandler(event) {
let nodes = app.graph._nodes_by_id;
for(let i in nodes) {
let node = nodes[i];
if(node.type == 'GlobalSeed //Inspire') {
if(node.widgets) {
const w = node.widgets.find((w) => w.name == 'value');
w.value = event.detail.value;
}
}
else
if(node.widgets) {
const w = node.widgets.find((w) => w.name == 'seed' && w.type == 'number');
if(w) {
w.value = event.detail.value;
}
}
}
}
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 workflow.nodes) {
let node_id = workflow.nodes[i].id;
let widgets = app.graph._nodes_by_id[node_id].widgets;
if(widgets) {
for(let j in widgets) {
if(widgets[j].name == 'seed')
workflow.seed_widgets[node_id] = parseInt(j);
}
}
}
return await original_queuePrompt.call(api, number, { output, workflow });
}
api.queuePrompt = queuePrompt_with_seed;
+25 -1
View File
@@ -174,15 +174,39 @@ class PromptExtractor:
return (positive, negative)
class GlobalSeed:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"value": ("INT", {"default": 0, "min": 0, "max": 1125899906842624}),
"mode": ("BOOLEAN", {"default": True, "label_on": "control_before_generate", "label_off": "control_after_generate"}),
"action": (["fixed", "increment", "decrement", "randomize"], )
}
}
RETURN_TYPES = ()
FUNCTION = "doit"
CATEGORY = "InspirePack"
OUTPUT_NODE = True
def doit(self, **kwargs):
return {}
NODE_CLASS_MAPPINGS = {
"LoadPromptsFromDir //Inspire": LoadPromptsFromDir,
"UnzipPrompt //Inspire": UnzipPrompt,
"ZipPrompt //Inspire": ZipPrompt,
"PromptExtractor //Inspire": PromptExtractor,
"GlobalSeed //Inspire": GlobalSeed,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"LoadPromptsFromDir //Inspire": "Load Prompts From Dir (Inspire)",
"UnzipPrompt //Inspire": "Unzip Prompt (Inspire)",
"ZipPrompt //Inspire": "Zip Prompt (Inspire)",
"PromptExtractor //Inspire": "Prompt Extractor (Inspire)"
"PromptExtractor //Inspire": "Prompt Extractor (Inspire)",
"GlobalSeed //Inspire": "Global Seed (Inspire)"
}