226 lines
6.7 KiB
JavaScript
226 lines
6.7 KiB
JavaScript
import { app } from "../../scripts/app.js";
|
|
import { api } from "../../scripts/api.js";
|
|
|
|
console.log("[TestNodeB] Extension loading...");
|
|
|
|
app.registerExtension({
|
|
name: "Test.NodeB",
|
|
|
|
async setup(app) {
|
|
api.addEventListener("test_node_b_init", testNodeBInitHandler);
|
|
api.addEventListener("executed", testNodeBExecutedHandler);
|
|
},
|
|
});
|
|
|
|
function testNodeBInitHandler(event) {
|
|
const nodeId = event.detail.node;
|
|
const node = app.graph.getNodeById(nodeId);
|
|
|
|
if (!node) {
|
|
return;
|
|
}
|
|
|
|
if (node.constructor.comfyClass !== "TestNodeB") {
|
|
return;
|
|
}
|
|
|
|
const e = event.detail.output;
|
|
const seed = e.seed?.[0];
|
|
const filename = e.filename?.[0];
|
|
const seedChanged = Boolean(e.seed_changed?.[0]);
|
|
const grabAndContinue = Boolean(e.grab_and_continue?.[0]);
|
|
|
|
console.log("[TestNodeB] Parsed values:", {
|
|
seed,
|
|
filename,
|
|
seedChanged,
|
|
grabAndContinue,
|
|
});
|
|
|
|
// Get current snapshot_data widget value
|
|
const snapshotDataWidget = node.widgets?.find(
|
|
(w) => w.name === "snapshot_data"
|
|
);
|
|
const currentSnapshotData = snapshotDataWidget?.value || "{}";
|
|
console.log("[TestNodeB] Current snapshot_data:", currentSnapshotData);
|
|
|
|
if (seedChanged && grabAndContinue) {
|
|
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
// Load and flip the input image from Node A
|
|
const loadAndFlipImage = (inputFilename) => {
|
|
return new Promise((resolve, reject) => {
|
|
console.log("[TestNodeB] Loading input image:", inputFilename);
|
|
|
|
// Construct URL to load the image from test_node_b subfolder
|
|
const imageUrl = `/view?filename=${encodeURIComponent(
|
|
inputFilename
|
|
)}&type=input&subfolder=test_node_b&rand=${Math.random()}`;
|
|
|
|
const img = new Image();
|
|
img.crossOrigin = "anonymous";
|
|
|
|
img.onload = () => {
|
|
console.log("[TestNodeB] Image loaded, creating flipped canvas...");
|
|
|
|
const canvas = document.createElement("canvas");
|
|
canvas.width = img.width;
|
|
canvas.height = img.height;
|
|
const ctx = canvas.getContext("2d");
|
|
|
|
// Flip the image horizontally
|
|
ctx.save();
|
|
ctx.scale(-1, 1);
|
|
ctx.drawImage(img, -canvas.width, 0);
|
|
ctx.restore();
|
|
|
|
// Add text showing the seed and snapshot_data
|
|
ctx.fillStyle = "red";
|
|
ctx.strokeStyle = "white";
|
|
ctx.lineWidth = 3;
|
|
ctx.font = "bold 48px Arial";
|
|
ctx.textAlign = "center";
|
|
|
|
// Stroke (outline) and fill the text
|
|
//ctx.strokeText(`Seed: ${seed}`, canvas.width / 2, 60);
|
|
ctx.fillText(`Seed: ${seed}`, canvas.width / 2, 60);
|
|
console.log("writing snapshot data", currentSnapshotData);
|
|
ctx.fillText(
|
|
`snapshot_data: ${currentSnapshotData}`,
|
|
canvas.width / 2,
|
|
110
|
|
);
|
|
|
|
resolve(canvas);
|
|
};
|
|
|
|
img.onerror = () => {
|
|
console.error("[TestNodeB] Failed to load image:", imageUrl);
|
|
reject(new Error("Failed to load input image"));
|
|
};
|
|
|
|
img.src = imageUrl;
|
|
});
|
|
};
|
|
|
|
// Upload canvas as blob
|
|
const uploadCanvas = (canvas, uploadFilename) => {
|
|
return new Promise((resolve, reject) => {
|
|
canvas.toBlob(
|
|
(blob) => {
|
|
const formData = new FormData();
|
|
formData.append("image", blob, uploadFilename);
|
|
formData.append("subfolder", "test_node_b");
|
|
formData.append("type", "input");
|
|
formData.append("overwrite", "true");
|
|
|
|
console.log("[TestNodeB] Uploading:", uploadFilename);
|
|
|
|
fetch("/upload/image", {
|
|
method: "POST",
|
|
body: formData,
|
|
})
|
|
.then((response) => response.json())
|
|
.then((data) => {
|
|
console.log("[TestNodeB] Upload response:", data);
|
|
|
|
// set the uploaded_image widget value
|
|
const uploadedImageWidget = node.widgets?.find(
|
|
(w) => w.name === "uploaded_image"
|
|
);
|
|
|
|
if (uploadedImageWidget) {
|
|
uploadedImageWidget.value = uploadFilename;
|
|
}
|
|
|
|
resolve(data);
|
|
})
|
|
.catch(reject);
|
|
},
|
|
"image/png",
|
|
0.95
|
|
);
|
|
});
|
|
};
|
|
|
|
// Execute the sequence
|
|
wait(100)
|
|
.then(() => {
|
|
return loadAndFlipImage(filename, seed);
|
|
})
|
|
.then((canvas) => {
|
|
// Upload with fixed filename
|
|
debugger;
|
|
const uploadFilename = "test_node_b_snapshot.png";
|
|
console.log("[TestNodeB] Uploading flipped image");
|
|
|
|
return uploadCanvas(canvas, uploadFilename).then((uploadData) => ({
|
|
uploadFilename,
|
|
}));
|
|
})
|
|
.then(({ uploadFilename }) => {
|
|
console.log("[TestNodeB] Upload complete:", uploadFilename);
|
|
|
|
// Update snapshot_data widget with current seed (like fabricData with seed)
|
|
// This is the cache invalidator - changes when seed changes
|
|
const snapshotDataWidget = node.widgets?.find(
|
|
(w) => w.name === "snapshot_data"
|
|
);
|
|
if (snapshotDataWidget) {
|
|
const snapshotData = {
|
|
seed: seed,
|
|
// timestamp: Date.now(),
|
|
};
|
|
snapshotDataWidget.value = JSON.stringify(snapshotData);
|
|
|
|
const uploadedImageWidget = node.widgets?.find(
|
|
(w) => w.name === "uploaded_image"
|
|
);
|
|
// console.log(
|
|
// "[TestNodeB] snapshot_data updated:",
|
|
// snapshotDataWidget.value
|
|
// );
|
|
}
|
|
|
|
return wait(100);
|
|
})
|
|
.then(() => {
|
|
console.log("[TestNodeB] Re-queueing workflow...");
|
|
return app.queuePrompt(0, 1);
|
|
})
|
|
.then(() => {
|
|
console.log("[TestNodeB] Workflow re-queued successfully");
|
|
console.log(
|
|
"[TestNodeB] Next execution should show SUCCESS with different color!"
|
|
);
|
|
})
|
|
.catch((error) => {
|
|
console.error("[TestNodeB] Auto-continue sequence failed:", error);
|
|
});
|
|
} else {
|
|
console.log(
|
|
"[TestNodeB] No auto-continue (seedChanged=" +
|
|
seedChanged +
|
|
", grabAndContinue=" +
|
|
grabAndContinue +
|
|
")"
|
|
);
|
|
}
|
|
|
|
console.log("[TestNodeB] ================================\n");
|
|
}
|
|
|
|
function testNodeBExecutedHandler(event) {
|
|
const nodeId = event.detail.node;
|
|
const node = app.graph.getNodeById(nodeId);
|
|
|
|
if (!node || node.constructor.comfyClass !== "TestNodeB") {
|
|
return;
|
|
}
|
|
|
|
console.log("\n[TestNodeB] ========== EXECUTED EVENT ==========");
|
|
console.log("[TestNodeB] Node executed for nodeId:", nodeId);
|
|
console.log("[TestNodeB] Event detail:", event.detail);
|
|
console.log("[TestNodeB] ===================================\n");
|
|
}
|