#21, docs, 1.1.3
This commit is contained in:
@@ -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 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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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]
|
||||
|
||||
@@ -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])
|
||||
Reference in New Issue
Block a user