#21, docs, 1.1.3

This commit is contained in:
Chris
2025-02-05 11:55:12 +11:00
parent 4f35aab788
commit 32f2ac401a
7 changed files with 55 additions and 10 deletions
+11 -5
View File
@@ -3,10 +3,12 @@
A set of four nodes designed to pause execution of the workflow to allow you to make selections and/or edits before continuing.
There's an example workflow that illustrates all of them at the end.
- 'Image Filter' - pause the flow and pick which images from a set you want to proceed with
- 'Mask Image Filter' - launch the mask editor for the image, and return the image and mask
- 'Text Image Filter' - show the image with some editable text which is returned
- 'Text Image Filter witrh Extras' - as 'Text Image Filter' but with three extra single line texts fields that are also returned
- ['Image Filter'](#image-filter) - pause the flow and pick which images from a set you want to proceed with
- ['Mask Image Filter'](#mask-image-filter) - launch the mask editor for the image, and return the image and mask
- ['Text Image Filter'](#text-image-filter) - show the image with some editable text which is returned
- ['Text Image Filter with Extras'](#text-image-filter-with-extras) - as 'Text Image Filter' but with three extra single line texts fields that are also returned
There's also a helper node, 'Split String by Commas' that can be used if you want more extra values.
## Examples of what you might do with them
@@ -83,11 +85,15 @@ generated. Here's a trivial workflow:
![text workflow](images/text%20workflow.png)
## Text Image Filter with Extras
Just like the Text Image Filter, but with three extra text fields, intended for short form - like specifying the denoising you want on the next step.
They are all strings, so you'll probably need to run the output through some sort of conversion node.
They are all strings, so you'll probably need to run the output through some sort of conversion node.
If you need more than three, consider using the 'Split Text by Commas' helper node.
If you use the optional 'tip' input, the contents will be displayed under the extras input fields, so you can remind yourself what they are for!
---
+4 -2
View File
@@ -6,15 +6,17 @@
"""
from .image_filter import ImageFilter, TextImageFilter, MaskImageFilter, TextImageFilterWithExtras
from .split_by_commas import SplitByCommas
VERSION = "1.1.2"
VERSION = "1.1.3"
WEB_DIRECTORY = "./js"
NODE_CLASS_MAPPINGS= {
"Image Filter": ImageFilter,
"Text Image Filter": TextImageFilter,
"Text Image Filter with Extras": TextImageFilterWithExtras,
"Mask Image Filter": MaskImageFilter
"Mask Image Filter": MaskImageFilter,
"Split String by Commas": SplitByCommas
}
__all__ = ["NODE_CLASS_MAPPINGS", "WEB_DIRECTORY"]
+3 -2
View File
@@ -158,6 +158,7 @@ class TextImageFilterWithExtras(PreviewImage):
},
"optional": {
"mask" : ("MASK", {"tooltip": "Optional - if provided, will be overlaid on image"}),
"tip" : ("STRING", {"default":"", "tooltip": "Optional - if provided, will be displayed in popup window"})
},
"hidden": HIDDEN,
}
@@ -166,9 +167,9 @@ class TextImageFilterWithExtras(PreviewImage):
def IS_CHANGED(cls, **kwargs):
return float("NaN")
def func(self, image, text, extra1, extra2, extra3, timeout, uid, mask=None, **kwargs):
def func(self, image, text, extra1, extra2, extra3, timeout, uid, mask=None, tip="", **kwargs):
urls:list[str] = self.save_images(images=image, **kwargs)['ui']['images']
payload = {"uid": uid, "urls":urls, "text":text, "extras":[extra1, extra2, extra3]}
payload = {"uid": uid, "urls":urls, "text":text, "extras":[extra1, extra2, extra3], "tip":tip}
if mask is not None: payload['mask_urls'] = self.save_images(images=mask_to_image(mask), **kwargs)['ui']['images']
response = send_with_resend(payload, timeout, uid)
+6
View File
@@ -41,6 +41,12 @@
font-size: larger;
}
.cg_popup .tip {
display: block;
padding-top: 10px;
line-height: 20px;
}
.cg_popup .buttons {
position: absolute;
width:14%;
+15
View File
@@ -36,6 +36,7 @@ class Popup extends HTMLSpanElement {
this.send_button = create('button', 'control', this.buttons, {innerText:"Send (S)"} )
this.cancel_button = create('button', 'control', this.buttons, {innerText:"Cancel (X)"} )
this.extras = create('span', 'extras', this.buttons)
this.tip = create('span', 'tip', this.buttons)
this.grid.addEventListener('click', this.on_click.bind(this))
this.send_button.addEventListener( 'click', this.send_current_state.bind(this) )
@@ -43,16 +44,19 @@ class Popup extends HTMLSpanElement {
document.addEventListener('keypress', this.on_keypress.bind(this) )
document.body.appendChild(this)
this.last_response_sent = 0
this.close()
}
_send_response(msg, no_extras) {
if (Date.now()-this.last_response_sent < 1000) return
const body = new FormData();
var response = msg
if (!no_extras) Array.from(this.extras.children).forEach((e)=>{ response = response + "|||" + e.value })
body.append('response', response);
api.fetchApi("/cg-image-filter-message", { method: "POST", body, });
Log.log(`"Sent ${JSON.stringify(response)}`)
if (!no_extras) this.last_response_sent = Date.now()
this.close()
}
@@ -70,13 +74,19 @@ class Popup extends HTMLSpanElement {
close() {
this.classList.add('hidden')
this.counter.classList.add('hidden')
this.tip.innerHTML = ""
this.active = false
if (document.getElementById('maskEditor')) document.getElementById('maskEditor').style.display = 'none'
this.n_images = 0
}
handle_message(message) {
if (!message.detail?.tick) Log.log(`Got ${JSON.stringify(message.detail)}`)
if (Date.now()-this.last_response_sent < 1000) {
Log.log(`Ignoring message because we just responded`)
return
}
if (this.handling_message && !detail.timeout) {
Log.log(`Already handling a message, so dropped message`)
return
@@ -98,6 +108,9 @@ class Popup extends HTMLSpanElement {
else if (detail.tick) this.handle_tick(detail)
else if (detail.maskedit) this.handle_maskedit(detail)
else if (detail.urls) this.handle_urls(detail)
if (detail.tip) this.handle_tip(detail)
} finally { this.handling_message = false }
}
@@ -108,6 +121,8 @@ class Popup extends HTMLSpanElement {
handle_timeout(detail) { this.close() }
handle_tip(detail) { this.tip.innerHTML = detail.tip.replace(/(?:\r\n|\r|\n)/g, '<br/>') }
window_not_showing(uid) {
const node = app.graph._nodes_by_id[uid]
return (
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "cg-image-filter"
description = "A set of custom nodes that pause a workflow while you select images, add masks, or edit text."
version = "1.1.2"
version = "1.1.3"
license = { file = "LICENSE" }
[project.urls]
+15
View File
@@ -0,0 +1,15 @@
class SplitByCommas:
RETURN_TYPES = ("STRING","STRING","STRING","STRING","STRING")
FUNCTION = "func"
CATEGORY = "image_filter"
OUTPUT_NODE = False
DESCRIPTION = "Split the input string into up to five pieces. Splits on commas and then strips whitespace from front and end."
@classmethod
def INPUT_TYPES(s):
return {"required": {"string" : ("STRING", {"default":""})}}
def func(self, string:str):
bits = [r.strip() for r in string.split(",",5)] + [""]*5
return tuple(bits[:5])