From 920e942ba8a255babda3483edb033b2de2e4b27f Mon Sep 17 00:00:00 2001 From: yolain Date: Thu, 28 Dec 2023 13:28:02 +0800 Subject: [PATCH] fix:easy pipeIn bug --- ComfyUI-Easy-Use.json | 13 +++++++++- README.en.md | 6 +++++ README.md | 6 +++++ py/easyNodes.py | 40 +++++++++++++++++++----------- py/server.py | 10 ++++++-- web/js/easy/easyDynamicWidgets.js | 2 ++ web/js/easy/easyQuick.js | 41 +++++++++++++++++++++++++++++++ 7 files changed, 100 insertions(+), 18 deletions(-) create mode 100644 web/js/easy/easyQuick.js diff --git a/ComfyUI-Easy-Use.json b/ComfyUI-Easy-Use.json index 427122d..509b86d 100644 --- a/ComfyUI-Easy-Use.json +++ b/ComfyUI-Easy-Use.json @@ -273,6 +273,16 @@ "model": "模型" } }, + "easy seed": { + "title": "随机种", + "widgets": { + "seed_num": "种子值", + "control_before_generate": "运行前操作" + }, + "outputs": { + "seed_num": "种子值" + } + }, "easy globalSeed": { "title": "全局随机种", "widgets": { @@ -581,7 +591,8 @@ "positive": "正面提示词", "negative": "负面提示词", "bbox_segm_pipe": "BBox&Segm节点束", - "sam_pipe": "SAM模型节点束" + "sam_pipe": "SAM模型节点束", + "optional_image": "图像(可选)" }, "widgets": { "guide_size": "引导大小", diff --git a/README.en.md b/README.en.md index 661d0af..041213d 100644 --- a/README.en.md +++ b/README.en.md @@ -29,6 +29,12 @@ After installing the node package, the UI interface will be automatically switch ## Changelog +**2023-12-27** + +- Fixed seed that cannot be fixed when you convert `seed_num` to `easy seed` +- Fixed `easy pipeIn` inputs bug +- `easy preDetailerFix` have added a new parameter `optional_image` +- **v1.0.1(Updated at 12/26/2023)** - Fixed `easy zero123Loader` and `easy svdLoader` model into cache. diff --git a/README.md b/README.md index 1d1ea4d..92c9dd0 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,12 @@ ## 更新日志 +**2023-12-27** + +- 修复 convert 到 `easy seed` 随机种无法固定的问题 +- 修复 `easy pipeIn` 值传入的报错问题 +- `easy preDetailerFix` 新增了 `optional_image` 传入图像可选,如未传默认取值为pipe里的图像 + **v1.0.1(2023-12-26)** - 修复 `easy zero123Loader` 和 `easy svdLoader` 读取模型时将模型加入到缓存中 diff --git a/py/easyNodes.py b/py/easyNodes.py index 338cad4..376d9b8 100644 --- a/py/easyNodes.py +++ b/py/easyNodes.py @@ -3017,6 +3017,7 @@ class preDetailerFix: "optional": { "bbox_segm_pipe": ("PIPE_LINE",), "sam_pipe": ("PIPE_LINE",), + "optional_image": ("IMAGE",), }, } @@ -3027,14 +3028,8 @@ class preDetailerFix: CATEGORY = "EasyUse/Fix" - def doit(self, pipe, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, feather, noise_mask, force_inpaint, drop_size, wildcard, cycle, bbox_segm_pipe=None, sam_pipe=None,): + def doit(self, pipe, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, feather, noise_mask, force_inpaint, drop_size, wildcard, cycle, bbox_segm_pipe=None, sam_pipe=None, optional_image=None): - samples = pipe["samples"] if "samples" in pipe else None - if samples is None: - raise Exception(f"[ERROR] pipe['samples'] is missing") - image = pipe["images"] if "images" in pipe else None - if image is None: - raise Exception(f"[ERROR] pipe['image'] is missing") model = pipe["model"] if "model" in pipe else None if model is None: raise Exception(f"[ERROR] pipe['model'] is missing") @@ -3044,6 +3039,18 @@ class preDetailerFix: vae = pipe["vae"] if "vae" in pipe else None if vae is None: raise Exception(f"[ERROR] pipe['vae'] is missing") + if optional_image is not None: + batch_size = pipe["loader_settings"]["batch_size"] if "batch_size" in pipe["loader_settings"] else 1 + samples = {"samples": vae.encode(optional_image)} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] + image = optional_image + else: + samples = pipe["samples"] if "samples" in pipe else None + if samples is None: + raise Exception(f"[ERROR] pipe['samples'] is missing") + image = pipe["images"] if "images" in pipe else None + if image is None: + raise Exception(f"[ERROR] pipe['image'] is missing") positive = pipe["positive"] if "positive" in pipe else None if positive is None: raise Exception(f"[ERROR] pipe['positive'] is missing") @@ -3325,27 +3332,30 @@ class pipeIn: def flush(self, pipe, model=None, pos=None, neg=None, latent=None, vae=None, clip=None, image=None, xyplot=None, my_unique_id=None): - model = model or pipe.get("model") + model = model if model is not None else pipe.get("model") if model is None: log_node_warn(f'pipeIn[{my_unique_id}]', "Model missing from pipeLine") - pos = pos or pipe.get("positive") + pos = pos if pos is not None else pipe.get("positive") if pos is None: log_node_warn(f'pipeIn[{my_unique_id}]', "Positive conditioning missing from pipeLine") - neg = neg or pipe.get("negative") + neg = neg if neg is not None else pipe.get("negative") if neg is None: log_node_warn(f'pipeIn[{my_unique_id}]', "Negative conditioning missing from pipeLine") - samples = latent or pipe.get("samples") + samples = latent if latent is not None else pipe.get("samples") if samples is None: log_node_warn(f'pipeIn[{my_unique_id}]', "Latent missing from pipeLine") - vae = vae or pipe.get("vae") + vae = vae if vae is not None else pipe.get("vae") if vae is None: log_node_warn(f'pipeIn[{my_unique_id}]', "VAE missing from pipeLine") - clip = clip or pipe.get("clip") + clip = clip if clip is not None else pipe.get("clip") if clip is None: log_node_warn(f'pipeIn[{my_unique_id}]', "Clip missing from pipeLine") - image = image or pipe.get("images") if image is None: - log_node_warn(f'pipeIn[{my_unique_id}]', "Image missing from pipeLine") + image = pipe.get("images") + else: + batch_size = pipe["loader_settings"]["batch_size"] if "batch_size" in pipe["loader_settings"] else 1 + samples = {"samples": vae.encode(image)} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] seed = pipe.get("seed") if seed is None: log_node_warn(f'pipeIn[{my_unique_id}]', "Seed missing from pipeLine") diff --git a/py/server.py b/py/server.py index 50be3c6..2dceecd 100644 --- a/py/server.py +++ b/py/server.py @@ -124,16 +124,22 @@ def prompt_seed_update(json_data): if mode is not None and not mode: control_seed(node[1], action, seed_is_global) else: - for k, v in json_data['prompt'].items(): + prompts = json_data['prompt'].items() + for k, v in prompts: if 'class_type' not in v: continue cls = v['class_type'] if cls == "easy wildcards" or cls == "easy preSampling" or cls == "easy preSamplingAdvanced" or cls == "easy preSamplingSdTurbo" or cls == "easy preSamplingDynamicCFG" or cls == "easy fullkSampler" or cls == 'easy seed': extra_data = next((x for x in workflow["nodes"] if str(x["id"]) == k), None) if extra_data is not None: + inputs = extra_data.get('inputs') widgets_value = extra_data.get('widgets_values') widgets_length = len(widgets_value) - action = widgets_value[widgets_length - 1] + seed_num_input = next((x for x in inputs if x['name'] == 'seed_num' and x['type'] == 'INT'), None) + if seed_num_input: + action = 'fixed' + else: + action = widgets_value[widgets_length - 1] node = k, v value = control_seed(node[1], action, False) diff --git a/web/js/easy/easyDynamicWidgets.js b/web/js/easy/easyDynamicWidgets.js index 9fab60b..0a51b07 100644 --- a/web/js/easy/easyDynamicWidgets.js +++ b/web/js/easy/easyDynamicWidgets.js @@ -329,10 +329,12 @@ app.registerExtension({ nodeType.prototype.onNodeCreated = async function () { onNodeCreated ? onNodeCreated.apply(this, []) : undefined; const values = ["randomize","fixed","increment","decrement"] + const seed_widget = this.widgets.find(w=> w.name == 'seed_num') const seed_control = this.addWidget("combo", "control_before_generate", values[0], () => {},{ values, serialize:false }) + seed_widget.linkedWidgets = [seed_control] } } }, diff --git a/web/js/easy/easyQuick.js b/web/js/easy/easyQuick.js new file mode 100644 index 0000000..70e9633 --- /dev/null +++ b/web/js/easy/easyQuick.js @@ -0,0 +1,41 @@ +// 1.0.2版本的内容 增加node_template的快捷键 +// ps: (测试中) 还差个设置管理开启,以免其他包或后续官方添加快捷键造成冲突,后续开放 +// import { app } from "../../../../scripts/app.js"; +// import { GroupNodeConfig } from "../../../../extensions/core/groupNode.js"; +// +// function loadTemplate(){ +// return localStorage['Comfy.NodeTemplates'] ? JSON.parse(localStorage['Comfy.NodeTemplates']) : null +// } +// const clipboardAction = async (cb) => { +// const old = localStorage.getItem("litegrapheditor_clipboard"); +// await cb(); +// localStorage.setItem("litegrapheditor_clipboard", old); +// }; +// async function addTemplateToCanvas(t){ +// const data = JSON.parse(t.data); +// await GroupNodeConfig.registerFromWorkflow(data.groupNodes, {}); +// localStorage.setItem("litegrapheditor_clipboard", t.data); +// app.canvas.pasteFromClipboard(); +// } +// +// app.registerExtension({ +// name: 'comfy.easyUse.quick', +// init() { +// const keybindListener = async function (event) { +// const modifierPressed = event.altKey; +// if(['1','2','3','4','5','6','7','8','9'].includes(event.key) && modifierPressed){ +// const template = loadTemplate() +// const idx = parseInt(event.key) - 1 +// if(template && template[idx]){ +// const t = template[idx] +// clipboardAction(_=>{addTemplateToCanvas(t)}) +// } +// } +// if (event.ctrlKey || event.altKey || event.metaKey) { +// return; +// } +// } +// window.addEventListener("keydown", keybindListener, true); +// } +// }); +