Add split workflow nodes and profile controls
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
|
||||
const EXTENSION = "ethanfel.prompt_builder.profile_buttons";
|
||||
|
||||
function widget(node, name) {
|
||||
return node.widgets?.find((w) => w.name === name);
|
||||
}
|
||||
|
||||
function hideWidget(w) {
|
||||
if (!w) return;
|
||||
if (w.origType === undefined) w.origType = w.type;
|
||||
w.type = "hidden";
|
||||
w.hidden = true;
|
||||
w.computeSize = () => [0, -4];
|
||||
}
|
||||
|
||||
function resizeNode(node) {
|
||||
const size = node.computeSize?.();
|
||||
if (size) node.setSize?.(size);
|
||||
app.graph?.setDirtyCanvas(true, true);
|
||||
}
|
||||
|
||||
async function queueOnce(node, triggerName) {
|
||||
const trigger = widget(node, triggerName);
|
||||
if (!trigger) {
|
||||
alert(`Missing trigger widget: ${triggerName}`);
|
||||
return;
|
||||
}
|
||||
|
||||
trigger.value = true;
|
||||
node.setDirtyCanvas?.(true, true);
|
||||
try {
|
||||
try {
|
||||
await app.queuePrompt(0, 1);
|
||||
} catch (_err) {
|
||||
await app.queuePrompt(0);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[${EXTENSION}] queue failed`, err);
|
||||
alert(`Queue failed: ${err}`);
|
||||
} finally {
|
||||
trigger.value = false;
|
||||
node.setDirtyCanvas?.(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
function setupSaveNode(node) {
|
||||
hideWidget(widget(node, "save_now"));
|
||||
if (!node._sxcpSaveButton) {
|
||||
node._sxcpSaveButton = node.addWidget("button", "Save Profile Now", null, () => queueOnce(node, "save_now"));
|
||||
}
|
||||
resizeNode(node);
|
||||
}
|
||||
|
||||
function setupLoadNode(node) {
|
||||
hideWidget(widget(node, "delete_now"));
|
||||
hideWidget(widget(node, "rename_now"));
|
||||
if (!node._sxcpDeleteButton) {
|
||||
node._sxcpDeleteButton = node.addWidget("button", "Delete Selected Profile", null, () => {
|
||||
const profile = widget(node, "profile_name")?.value || "";
|
||||
if (!profile || profile === "manual") {
|
||||
alert("Select a saved profile before deleting.");
|
||||
return;
|
||||
}
|
||||
if (!confirm(`Delete saved profile "${profile}"?`)) return;
|
||||
queueOnce(node, "delete_now");
|
||||
});
|
||||
}
|
||||
if (!node._sxcpRenameButton) {
|
||||
node._sxcpRenameButton = node.addWidget("button", "Rename Selected Profile", null, () => {
|
||||
const profile = widget(node, "profile_name")?.value || "";
|
||||
const target = widget(node, "rename_to")?.value || "";
|
||||
if (!profile || profile === "manual") {
|
||||
alert("Select a saved profile before renaming.");
|
||||
return;
|
||||
}
|
||||
if (!target.trim()) {
|
||||
alert("Fill rename_to before renaming.");
|
||||
return;
|
||||
}
|
||||
if (!confirm(`Rename saved profile "${profile}" to "${target}"?`)) return;
|
||||
queueOnce(node, "rename_now");
|
||||
});
|
||||
}
|
||||
resizeNode(node);
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: EXTENSION,
|
||||
|
||||
async beforeRegisterNodeDef(nodeType, nodeData) {
|
||||
if (nodeData.name !== "SxCPCharacterProfileSave" && nodeData.name !== "SxCPCharacterProfileLoad") return;
|
||||
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const result = onNodeCreated?.apply(this, arguments);
|
||||
if (nodeData.name === "SxCPCharacterProfileSave") setupSaveNode(this);
|
||||
if (nodeData.name === "SxCPCharacterProfileLoad") setupLoadNode(this);
|
||||
return result;
|
||||
};
|
||||
|
||||
const onConfigure = nodeType.prototype.onConfigure;
|
||||
nodeType.prototype.onConfigure = function () {
|
||||
const result = onConfigure?.apply(this, arguments);
|
||||
queueMicrotask(() => {
|
||||
if (nodeData.name === "SxCPCharacterProfileSave") setupSaveNode(this);
|
||||
if (nodeData.name === "SxCPCharacterProfileLoad") setupLoadNode(this);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user