copy/paste bug fixes for batch images

enhance selector preview on clipspace menu
add img_paste_mode option into clipspace menu
This commit is contained in:
Dr.Lt.Data 2023-04-29 14:39:03 +09:00
parent 8aac84a2e4
commit 286b731de3
3 changed files with 130 additions and 48 deletions

View File

@ -4,13 +4,14 @@ import { ComfyApp } from "/scripts/app.js";
export class ClipspaceDialog extends ComfyDialog { export class ClipspaceDialog extends ComfyDialog {
static items = []; static items = [];
static is_opened = false; // prevent redundant popup static instance = null;
static registerButton(name, callback) { static registerButton(name, contextPredicate, callback) {
const item = const item =
$el("button", { $el("button", {
type: "button", type: "button",
textContent: name, textContent: name,
contextPredicate: contextPredicate,
onclick: callback onclick: callback
}) })
@ -18,59 +19,109 @@ export class ClipspaceDialog extends ComfyDialog {
} }
static invalidatePreview() { static invalidatePreview() {
const img_preview = document.getElementById("clipspace_preview"); if(ComfyApp.clipspace && ComfyApp.clipspace.imgs && ComfyApp.clipspace.imgs.length > 0) {
img_preview.src = ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src; const img_preview = document.getElementById("clipspace_preview");
img_preview.style.height = "100px"; if(img_preview) {
img_preview.src = ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src;
img_preview.style.maxHeight = "100%";
img_preview.style.maxWidth = "100%";
}
}
} }
static invalidate() {
if(ClipspaceDialog.instance) {
const self = ClipspaceDialog.instance;
// allow reconstruct controls when copying from non-image to image content.
const children = $el("div.comfy-modal-content",[
self.createImgSettings(),
// self.createImgPreview(),
...self.createButtons()
]);
if(self.element) {
// update
self.element.removeChild(self.element.firstChild);
self.element.appendChild(children);
}
else {
// new
self.element = $el("div.comfy-modal", { parent: document.body }, [children,]);
}
ClipspaceDialog.invalidatePreview();
}
}
constructor() { constructor() {
super(); super();
this.element =
$el("div.comfy-modal", { parent: document.body },
[$el("div.comfy-modal-content",[
this.createImgSelector(),
this.createImgPreview(),
...this.createButtons()]),]
);
} }
createButtons() { createButtons(self) {
const buttons = []; const buttons = [];
for(let idx in ClipspaceDialog.items) { for(let idx in ClipspaceDialog.items) {
const item = ClipspaceDialog.items[idx]; const item = ClipspaceDialog.items[idx];
buttons.push(ClipspaceDialog.items[idx]); if(!item.contextPredicate || item.contextPredicate())
buttons.push(ClipspaceDialog.items[idx]);
} }
buttons.push( buttons.push(
$el("button", { $el("button", {
type: "button", type: "button",
textContent: "Close", textContent: "Close",
onclick: () => { onclick: () => { this.close(); }
ClipspaceDialog.is_opened = false;
this.close();
}
}) })
); );
return buttons; return buttons;
} }
createImgSelector() { createImgSettings() {
if(ComfyApp.clipspace.imgs != undefined) { if(ComfyApp.clipspace.imgs) {
const combo_items = []; const combo_items = [];
const imgs = ComfyApp.clipspace.imgs; const imgs = ComfyApp.clipspace.imgs;
for(let i=0; i < imgs.length; i++) { for(let i=0; i < imgs.length; i++) {
combo_items.push($el("option", {value:i}, [`${i}`])); combo_items.push($el("option", {value:i}, [`${i}`]));
} }
const combo = $el("select", const combo1 = $el("select",
{id:"clipspace_img_selector", onchange:(event) => { {id:"clipspace_img_selector", onchange:(event) => {
ComfyApp.clipspace['selectedIndex'] = event.target.selectedIndex; ComfyApp.clipspace['selectedIndex'] = event.target.selectedIndex;
ClipspaceDialog.invalidatePreview(); ClipspaceDialog.invalidatePreview();
} }, combo_items); } }, combo_items);
return combo;
const row1 =
$el("tr", {},[
$el("td", {}, [$el("font", {color:"white"}, ["Select Image"])]),
$el("td", {}, [combo1])
]);
const combo2 = $el("select",
{id:"clipspace_img_paste_mode", onchange:(event) => {
ComfyApp.clipspace['img_paste_mode'] = event.target.value;
} },
[
$el("option", {value:'all'}, 'all'),
$el("option", {value:'selected'}, 'selected')
]);
const row2 =
$el("tr", {},[
$el("td", {}, [$el("font", {color:"white"}, ["Paste Mode"])]),
$el("td", {}, [combo2])
]);
const td = $el("td", {align:'center', width:'100px', height:'100px', colSpan:'2'},
[ $el("img",{id:"clipspace_preview"},[]) ]
);
const row3 =
$el("tr", {}, [td]);
return $el("table", {}, [row1, row2, row3]);
} }
else { else {
return []; return [];
@ -78,7 +129,7 @@ export class ClipspaceDialog extends ComfyDialog {
} }
createImgPreview() { createImgPreview() {
if(ComfyApp.clipspace.imgs != undefined) { if(ComfyApp.clipspace.imgs) {
return $el("img",{id:"clipspace_preview"}); return $el("img",{id:"clipspace_preview"});
} }
else else
@ -86,10 +137,8 @@ export class ClipspaceDialog extends ComfyDialog {
} }
show() { show() {
ClipspaceDialog.is_opened = true;
const img_preview = document.getElementById("clipspace_preview"); const img_preview = document.getElementById("clipspace_preview");
img_preview.src = ComfyApp.clipspace.imgs[0].src; ClipspaceDialog.invalidate();
img_preview.style.height = "100px";
this.element.style.display = "block"; this.element.style.display = "block";
} }
@ -100,13 +149,16 @@ app.registerExtension({
init(app) { init(app) {
app.openClipspace = app.openClipspace =
function () { function () {
if(!ClipspaceDialog.is_opened) { if(!ClipspaceDialog.instance) {
let dlg = new ClipspaceDialog(app); ClipspaceDialog.instance = new ClipspaceDialog(app);
if(ComfyApp.clipspace) ComfyApp.clipspace_invalidate_handler = ClipspaceDialog.invalidate;
dlg.show(); }
else
app.ui.dialog.show("Clipspace is Empty!"); if(ComfyApp.clipspace) {
} ClipspaceDialog.instance.show();
}
else
app.ui.dialog.show("Clipspace is Empty!");
}; };
} }
}); });

View File

@ -42,7 +42,7 @@ async function uploadMask(filepath, formData) {
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']] = new Image(); ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']] = new Image();
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src = `view?filename=${filepath.filename}&type=${filepath.type}`; ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src = `view?filename=${filepath.filename}&type=${filepath.type}`;
ComfyApp.clipspace.images = [filepath]; ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']] = filepath;
ClipspaceDialog.invalidatePreview(); ClipspaceDialog.invalidatePreview();
} }
@ -562,6 +562,7 @@ app.registerExtension({
dlg.show(); dlg.show();
}; };
ClipspaceDialog.registerButton("MaskEditor", callback); const context_predicate = () => ComfyApp.clipspace && ComfyApp.clipspace.imgs && ComfyApp.clipspace.imgs.length > 0
ClipspaceDialog.registerButton("MaskEditor", context_predicate, callback);
} }
}); });

View File

@ -25,6 +25,7 @@ export class ComfyApp {
* @type {serialized node object} * @type {serialized node object}
*/ */
static clipspace = null; static clipspace = null;
static clipspace_invalidate_handler = null;
constructor() { constructor() {
this.ui = new ComfyUI(this); this.ui = new ComfyUI(this);
@ -164,8 +165,13 @@ export class ComfyApp {
'imgs': imgs, 'imgs': imgs,
'original_imgs': orig_imgs, 'original_imgs': orig_imgs,
'images': this.images, 'images': this.images,
'selectedIndex': 0 'selectedIndex': 0,
'img_paste_mode': 'all'
}; };
if(ComfyApp.clipspace_invalidate_handler) {
ComfyApp.clipspace_invalidate_handler();
}
} }
}); });
@ -174,31 +180,52 @@ export class ComfyApp {
{ {
content: "Paste (Clipspace)", content: "Paste (Clipspace)",
callback: () => { callback: () => {
if(ComfyApp.clipspace != null) { if(ComfyApp.clipspace) {
// image paste // image paste
if(ComfyApp.clipspace.imgs != undefined && this.imgs != undefined && this.widgets != null) { if(ComfyApp.clipspace.imgs && this.imgs) {
var filename = ""; var filename = "";
if(this.images && ComfyApp.clipspace.images) { if(this.images && ComfyApp.clipspace.images) {
this.images = ComfyApp.clipspace.images; if(ComfyApp.clipspace['img_paste_mode'] == 'selected') {
app.nodeOutputs[this.id + ""].images = this.images = [ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']]];
}
else
app.nodeOutputs[this.id + ""].images = this.images = ComfyApp.clipspace.images;
} }
if(ComfyApp.clipspace.images != undefined) { if(ComfyApp.clipspace.imgs) {
const clip_image = ComfyApp.clipspace.images[0]; // deep-copy to cut link with clipspace
if(ComfyApp.clipspace['img_paste_mode'] == 'selected') {
const img = new Image();
img.src = ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src;
this.imgs = [img];
}
else {
const imgs = [];
for(let i=0; i<ComfyApp.clipspace.imgs.length; i++) {
imgs[i] = new Image();
imgs[i].src = ComfyApp.clipspace.imgs[i].src;
this.imgs = imgs;
}
}
}
if(ComfyApp.clipspace.images) {
const clip_image = ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']];
if(clip_image.subfolder != '') if(clip_image.subfolder != '')
filename = `${clip_image.subfolder}/`; filename = `${clip_image.subfolder}/`;
filename += `${clip_image.filename} [${clip_image.type}]`; filename += `${clip_image.filename} [${clip_image.type}]`;
} }
else if(ComfyApp.clipspace.widgets != undefined) { else if(ComfyApp.clipspace.widgets) {
const index_in_clip = ComfyApp.clipspace.widgets.findIndex(obj => obj.name === 'image'); const index_in_clip = ComfyApp.clipspace.widgets.findIndex(obj => obj.name === 'image');
if(index_in_clip >= 0) { if(index_in_clip >= 0) {
filename = `${ComfyApp.clipspace.widgets[index_in_clip].value}`; filename = `${ComfyApp.clipspace.widgets[index_in_clip].value}`;
} }
} }
const index = this.widgets.findIndex(obj => obj.name === 'image'); // for Load Image node.
if(index >= 0 && filename != "" && ComfyApp.clipspace.imgs != undefined) { const index = this.widgets.findIndex(obj => obj.name === 'image');
this.imgs = ComfyApp.clipspace.imgs; if(index >= 0 && filename != "") {
this.widgets[index].value = filename; this.widgets[index].value = filename;
if(this.widgets_values != undefined) { if(this.widgets_values != undefined) {
this.widgets_values[index] = filename; this.widgets_values[index] = filename;
@ -207,7 +234,7 @@ export class ComfyApp {
} }
// ensure render after update widget_value // ensure render after update widget_value
if(ComfyApp.clipspace.widgets != null && this.widgets != null) { if(ComfyApp.clipspace.widgets && this.widgets) {
ComfyApp.clipspace.widgets.forEach(({ type, name, value }) => { ComfyApp.clipspace.widgets.forEach(({ type, name, value }) => {
const prop = Object.values(this.widgets).find(obj => obj.type === type && obj.name === name); const prop = Object.values(this.widgets).find(obj => obj.type === type && obj.name === name);
if (prop && prop.type != 'button') { if (prop && prop.type != 'button') {
@ -216,6 +243,8 @@ export class ComfyApp {
}); });
} }
} }
app.graph.setDirtyCanvas(true);
} }
} }
); );