From 8519e28da248c57cbeedca4f24fbbfdb7371bd75 Mon Sep 17 00:00:00 2001 From: Joel Trauger Date: Tue, 26 Dec 2023 23:06:25 -0600 Subject: [PATCH] Removed Prompt Editor and rolled into Prompt Builder --- __init__.py | 4 +- harronode.py | 127 +--------------------------- js/harronode.js | 215 +++++++++++++++++++++++++++++++++++------------- 3 files changed, 160 insertions(+), 186 deletions(-) diff --git a/__init__.py b/__init__.py index b27c522..2227a2d 100644 --- a/__init__.py +++ b/__init__.py @@ -6,17 +6,15 @@ """ -from .harronode import Harronode,PromptEditor +from .harronode import Harronode from .harroserver import HarroServer NODE_CLASS_MAPPINGS = { "Harronode": Harronode, - "PromptEditor": PromptEditor } NODE_DISPLAY_NAME_MAPPINGS = { "Harronode": "Harronode - Prompt Builder", - "PromptEditor": "Harronode - Prompt Editor" } WEB_DIRECTORY = "js" diff --git a/harronode.py b/harronode.py index ea9a993..72d5236 100644 --- a/harronode.py +++ b/harronode.py @@ -20,6 +20,7 @@ class Harronode: "required": { "prompt": ("STRING", {"default": "", "multiline": True}), "text_on_image": ("STRING", {"default": "", "multiline": True}), + "mode": ("BOOLEAN", {"default": True, "label_on": "Editable", "label_off": "Fixed"}), "text_weight": ("FLOAT", {"default": 1.0, "min":0.5, "max":1.5, "step": 0.01}), "color_count": ("INT", {"default": 1, "min": 0, "max": 3, "step": 1}), "style_count": ("INT", {"default": 1, "min": 1, "max": 2, "step": 1}), @@ -49,129 +50,3 @@ class Harronode: def doTheThing(self, *args, **kwargs): output = kwargs['prompt'] return(output,) # comma outputs a tuple with a single record instead of a bunch of records all containing the prompt - -class PromptEditor: - - @classmethod - def INPUT_TYPES(cls): - - inputs = { - "optional": { - "prompt": ("STRING", {"forceInput": True}) # forceInput makes it an input node - }, - "required": { - "mode": (["Edit", "Bypass"],{}), - "promptEditor": ("STRING", {"default": "", "multiline": True}) - }, - "hidden": { - "unique_id": "UNIQUE_ID", - "extra_pnginfo": "EXTRA_PNGINFO" - }, - } - return inputs - - RETURN_TYPES = ("STRING",) - FUNCTION = "EditPrompt" - CATEGORY = "Harronode/PromptBuilder" - - def EditPrompt(self, *args, **kwargs): - print("EditPrompt") - output = '' - prompt = '' - unique_id = kwargs["unique_id"] - extra_pnginfo = kwargs["extra_pnginfo"] - mode = kwargs["mode"] - promptEditor = kwargs["promptEditor"] - if "prompt" in kwargs: - prompt = kwargs["prompt"] - if unique_id and extra_pnginfo and "workflow" in extra_pnginfo: - workflow = extra_pnginfo["workflow"] - target_id = unique_id - node = None - # try to find the node in the workflow so we can get all the values of it - for node in workflow["nodes"]: - if str(node["id"]) == target_id: - break - # if the node is found, set the value of the textbox (3rd input, 0-indexed) to the prompt - if node: - print(node) - if mode == "Edit": - server.PromptServer.instance.send_sync("harronode-populate-promptEditor", {"node_id": unique_id, "value": prompt,}) - output = promptEditor, - else: - # just set the output to the string we input - output = prompt, - return (output,) - -def onprompt_populate_prompt(json_data): - try: - prompt = json_data['prompt'] - updated_widget_values = {} - for k, v in prompt.items(): - if 'class_type' in v and (v['class_type'] == 'Harronode'): - inputs = v['inputs'] - if isinstance(inputs['prompt'], str): - inputs['prompt'] = prompt_builder.build_prompt(inputs) - server.PromptServer.instance.send_sync("harronode-node-feedback", {"node_id": k, "widget_name": "prompt", "type": "STRING", "value": inputs['prompt']}) - updated_widget_values[k] = inputs['prompt'] - except Exception as e: - print(f"[WARN] ComfyUI-Harronode: Error on prompt\n{e}") - -def harroonprompt(json_data): - try: - onprompt_populate_prompt(json_data) - except Exception as e: - print(f"[WARN] ComfyUI-Harronode: Error on prompt - autopopulation of prompt will not work.\n{e}") - - return json_data - -class prompt_builder: - def build_prompt(inputs): - # Initialize the prompt builder string - text = "" - text = text + "('" - text = text + inputs["text_on_image"] - text_weight = inputs["text_weight"] - text = text + f"':{text_weight:.2f}) text logo, " - color_count = inputs["color_count"] - # gather colors - if color_count > 0: - color1 = inputs["color_1"] - color2 = inputs["color_2"] - color3 = inputs["color_3"] - for i in range(1, color_count + 1): - variable_name = f"color{i}" - color_value = locals()[variable_name] - text = text + color_value + ", " - style_count = inputs["style_count"] - # gather styles - if style_count > 0: - style1 = inputs["style_1"] - style2 = inputs["style_2"] - for i in range(1, style_count + 1): - variable_name = f"style{i}" - style_value = locals()[variable_name] - text = text + style_value + ", " - accent_count = inputs["accent_count"] - # gather accents - if accent_count > 0: - accent1 = inputs["accent_1"] - accent2 = inputs["accent_2"] - accent3 = inputs["accent_3"] - for i in range(1, accent_count + 1): - variable_name = f"accent{i}" - accent_value = locals()[variable_name] - text = text + accent_value + ", " - content_count = inputs["content_count"] - # gather contents - if content_count > 0: - content1 = inputs["content_1"] - content2 = inputs["content_2"] - content3 = inputs["content_3"] - for i in range(1, content_count + 1): - variable_name = f"content{i}" - content_value = locals()[variable_name] - text = text + content_value + ", " - return text - -server.PromptServer.instance.add_on_prompt_handler(harroonprompt) diff --git a/js/harronode.js b/js/harronode.js index a94b44d..4c15b52 100644 --- a/js/harronode.js +++ b/js/harronode.js @@ -1,23 +1,88 @@ import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js"; +import "../../scripts/widgets.js"; +import { ComfyWidgets } from "../../scripts/widgets.js"; let origProps = {}; let initialized = false; let previousPrompt = ""; +let tokenDict = { + "text": { + "location": 0, + "currentValue":"" + }, + "color_1":{ + "location": 0, + "currentValue":"" + }, + "color_2":{ + "location": 0, + "currentValue":"" + }, + "color_3":{ + "location": 0, + "currentValue":"" + }, + "style_1":{ + "location": 0, + "currentValue":"" + }, + "style_2":{ + "location": 0, + "currentValue":"" + }, + "accent_1":{ + "location": 0, + "currentValue":"" + }, + "accent_2":{ + "location": 0, + "currentValue":"" + }, + "accent_3":{ + "location": 0, + "currentValue":"" + }, + "content_1":{ + "location": 0, + "currentValue":"" + }, + "content_2":{ + "location": 0, + "currentValue":"" + }, + "content_3":{ + "location": 0, + "currentValue":"" + }, + "tokens": [] +} const harroWidgetHandlers = { "Harronode": { 'color_count': handleColorCount, 'style_count': handleStyleCount, 'accent_count': handleAccentCount, - 'content_count': handleContentCount - }, - "PromptEditor": { - 'mode': handleMode + 'content_count': handleContentCount, + 'color_1': handlePromptChange, + 'color_2': handlePromptChange, + 'color_3': handlePromptChange, + 'style_1': handlePromptChange, + 'style_2': handlePromptChange, + 'accent_1': handlePromptChange, + 'accent_2': handlePromptChange, + 'accent_3': handlePromptChange, + 'content_1': handlePromptChange, + 'content_2': handlePromptChange, + 'content_3': handlePromptChange, + 'text_weight': handlePromptChange, }, }; // ------------------ HANDLERS +function handlePromptChange(node, widget) { + rebuildPrompt(node); +} function handleColorCount(node, widget) { updateColorWidgets(node, widget.value); @@ -35,19 +100,6 @@ function handleContentCount(node, widget) { updateContentWidgets(node, widget.value); } -function handleMode (node, widget) { - //const goButton = findWidgetByName(node, "Prompt looks good (GO)"); - const promptEditor = findWidgetByName(node, "promptEditor"); - if (widget.value == "Bypass"){ - //goButton.disabled = 1==1; - promptEditor.inputEl.disabled = 1==1; - } - else { - //goButton.disabled = 1==0; - promptEditor.inputEl.disabled = 1==0; - } -} - //----------------------END HANDLERS //-------function credit to efficiency nodes for comfyUI---------// @@ -88,7 +140,6 @@ function harrToggleWidget(node, widget, show = false, suffix = "") { // -- BASE CODE NEEDED BY PROMPT BUILDER function updateColorWidgets(node, color_count){ - console.log("colors", color_count) for (let i = 1; i <= 3; i++) { //find widget const color_picker = findWidgetByName(node, `color_${i}`) @@ -101,6 +152,7 @@ function updateColorWidgets(node, color_count){ harrToggleWidget(node, color_picker, false) } } + rebuildPrompt(node); } function updateStyleWidgets(node, color_count){ @@ -116,6 +168,7 @@ function updateStyleWidgets(node, color_count){ harrToggleWidget(node, style_picker, false) } } + rebuildPrompt(node); } function updateAccentWidgets(node, color_count){ for (let i = 1; i <= 3; i++) { @@ -130,6 +183,7 @@ function updateAccentWidgets(node, color_count){ harrToggleWidget(node, accent_picker, false) } } + rebuildPrompt(node); } function updateContentWidgets(node, color_count){ for (let i = 1; i <= 3; i++) { @@ -144,6 +198,56 @@ function updateContentWidgets(node, color_count){ harrToggleWidget(node, content_picker, false) } } + rebuildPrompt(node); +} + +function buildPrompt(node, widgets = null, event = null){ + var prompt = ""; + var _widgets; + if(widgets != null) + { + _widgets = widgets; + + } + //get widget values from node + else { + if(node.comfyClass == "Harronode"){ + _widgets = node.widgets; + } + } + prompt += '("' + findWidgetByName(node, "text_on_image").value+ '":' + parseFloat(findWidgetByName(node, "text_weight").value).toFixed(2) + ") text logo, "; + //foreach color + var colors = findWidgetByName(node, "color_count").value; + for(var i = 1; i <= colors; i++){ + var color = findWidgetByName(node, `color_${i}`).value; + prompt += color + ", "; + } + //foreach style + var styles = findWidgetByName(node, "style_count").value; + for(var i = 1; i <= styles; i++){ + var style = findWidgetByName(node, `style_${i}`).value; + prompt += style + ", "; + } + //foreach accent + var accents = findWidgetByName(node, "accent_count").value; + for(var i = 1; i <= accents; i++){ + var accent = findWidgetByName(node, `accent_${i}`).value; + prompt += accent + ", "; + } + //foreach content + var contents = findWidgetByName(node, "content_count").value; + for(var i = 1; i <= contents; i++){ + var content = findWidgetByName(node, `content_${i}`).value; + prompt += content + ", "; + } + return prompt; +} + +function rebuildPrompt(node){ + // build prompt + var promptOutput = ""; + promptOutput = buildPrompt(node); + node.widgets[0].inputEl.value = promptOutput; } // -- END BASE CODE NEEDED BY PROMPT BUILDER @@ -155,39 +259,21 @@ function startupLogic (node, widget) //change name if (handler) { handler(node, widget); } - prompt = findWidgetByName(node, 'prompt'); - -} - -function progressButtonPressed (){ - } app.registerExtension({ name: "harronode.harronode", - setup(){ - function harronode_populate_promptEditor(event) - { - const node = app.graph._nodes_by_id[event.detail.node_id]; - if (node) { - if(node.comfyClass == "PromptEditor") { - let prompt = event.detail.value; - if (prompt != previousPrompt){ - previousPrompt = prompt; - node.widgets[1].inputEl.value = event.detail.value; - } - } - } else { - console.log(`Harronode Prompt Editor - failed to find ${event.detail.node_id}`) - } - } - + setup() + { function harronode_node_feedback(event){ const node = app.graph._nodes_by_id[event.detail.node_id]; + let promptOutput = ""; + let editedPrompt = node.widgets[0].inputEl.value; if (node) { if(node.comfyClass == "Harronode"){ - let prompt = event.detail.value; - node.widgets[0].inputEl.value = prompt; + let widgets = event.detail.value; + console.log(widgets); + rebuildPrompt(node); } } else { @@ -195,10 +281,10 @@ app.registerExtension({ } } - api.addEventListener("harronode-populate-promptEditor", harronode_populate_promptEditor); api.addEventListener("harronode-node-feedback", harronode_node_feedback); }, - async nodeCreated(node) { + async nodeCreated(node) + { for (const w of node.widgets || []) { let widgetValue = w.value; @@ -225,22 +311,37 @@ app.registerExtension({ startupLogic(node, w); } }); + if(node.comfyClass == "Harronode"){ + const editablePrompt = node.widgets.find((w) => w.name == 'prompt'); + const mode_widget = node.widgets.find((w) => w.name == 'mode'); + Object.defineProperty(mode_widget, "value", { + set: (value) => { + node._mode_value = value == true || value == "Editable"; + editablePrompt.inputEl.disabled = value == false || value == "Editable"; + }, + get: () => { + if(node._mode_value != undefined) + return node._mode_value; + else + return true; + } + }); + } } //do this if we're messing with the prompt builder if(node.comfyClass == "Harronode"){ - node.widgets[0].inputEl.placeholder = "Populated Prompt (Will be generated automatically)"; + node.widgets[0].inputEl.placeholder = "Generated Prompt - Changing a parameter may overwrite what is in this box."; node.widgets[1].inputEl.placeholder = "Input Text to Display on Image"; - const prompt = node.widgets.find((w) => w.name == 'prompt'); - prompt.inputEl.disabled = 1 == 1; - } - //do this if we're messing with the prompt editor - if(node.comfyClass == "PromptEditor") { - const mode = node.widgets.find((w) => w.name === "mode"); - node.widgets[1].inputEl.placeholder = "Populated Prompt (Will be generated automatically)"; - console.log("setting size"); - const newHeight = node.computeSize()[1]; - node.setSize([node.size[0], newHeight]); + //janky af but I don't care at this point + if(!initialized) { + console.log(node.widgets); + const thebutton = node.addWidget("button", "CLICK to Rebuild Prompt (Erases edits)", "", () => { + rebuildPrompt(node); + }); + initialized = true; + console.log(node.widgets); + } } setTimeout(() => { initialized = true; }, 500); } -}); +}); \ No newline at end of file