mirror of
https://github.com/justUmen/Bjornulf_custom_nodes.git
synced 2026-03-21 20:52:11 -03:00
0.76
This commit is contained in:
38
web/js/global_seed_manager.js
Normal file
38
web/js/global_seed_manager.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { app } from "../../../scripts/app.js";
|
||||
import { api } from "../../../scripts/api.js";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Bjornulf.GlobalSeedManager",
|
||||
async nodeCreated(node) {
|
||||
// Ensure the button is added only to RandomSeedNode
|
||||
if (node.comfyClass !== "Bjornulf_GlobalSeedManager") return;
|
||||
|
||||
// Add a button widget to the node
|
||||
const deleteButton = node.addWidget(
|
||||
"button", // Widget type
|
||||
"Delete Seeds LIST", // Button label
|
||||
null, // Initial value (not needed for buttons)
|
||||
async () => {
|
||||
// Ensure the node is still in the graph
|
||||
if (!node.graph) return;
|
||||
|
||||
try {
|
||||
// Make a POST request to the delete endpoint
|
||||
const response = await fetch("/delete_random_seeds", {
|
||||
method: "POST",
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
// Show feedback to the user
|
||||
if (data.success) {
|
||||
app.ui.dialog.show("Seeds file deleted successfully.");
|
||||
} else {
|
||||
app.ui.dialog.show(`Failed to delete seeds file: ${data.error}`);
|
||||
}
|
||||
} catch (error) {
|
||||
app.ui.dialog.show("An error occurred while deleting the seeds file.");
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -1,80 +1,44 @@
|
||||
import { app } from "../../../scripts/app.js";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Bjornulf.ImageNoteLoadImage",
|
||||
async nodeCreated(node) {
|
||||
// Ensure the node is of the specific class
|
||||
if (node.comfyClass !== "Bjornulf_ImageNoteLoadImage") return;
|
||||
console.log("node created");
|
||||
|
||||
setTimeout(() => {
|
||||
// Update widget positions
|
||||
node.onResize(node.size);
|
||||
|
||||
// Refresh all widgets
|
||||
node.widgets.forEach(w => {
|
||||
if (w.onShow?.(true)) {
|
||||
w.onShow?.(false);
|
||||
// Store the initial node size
|
||||
let prevSize = [...node.size];
|
||||
let stableCount = 0;
|
||||
const minStableFrames = 3; // Number of frames the size must remain stable
|
||||
|
||||
// Function to check if the node's size has stabilized
|
||||
const checkSizeStable = () => {
|
||||
if (node.size[0] === prevSize[0] && node.size[1] === prevSize[1]) {
|
||||
stableCount++;
|
||||
if (stableCount >= minStableFrames) {
|
||||
// Size has been stable, simulate a resize to trigger layout update
|
||||
const originalSize = [...node.size];
|
||||
node.setSize([originalSize[0] + 1, originalSize[1]]); // Slightly increase width
|
||||
setTimeout(() => {
|
||||
node.setSize(originalSize); // Revert to original size
|
||||
app.graph.setDirtyCanvas(true, true); // Trigger canvas redraw
|
||||
}, 0);
|
||||
} else {
|
||||
// Size is stable but not for enough frames yet, check again
|
||||
requestAnimationFrame(checkSizeStable);
|
||||
}
|
||||
});
|
||||
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}, 500);
|
||||
} else {
|
||||
// Size changed, reset counter and update prevSize
|
||||
prevSize = [...node.size];
|
||||
stableCount = 0;
|
||||
requestAnimationFrame(checkSizeStable);
|
||||
}
|
||||
};
|
||||
|
||||
// Start checking after a short delay to allow node initialization
|
||||
setTimeout(() => {
|
||||
requestAnimationFrame(checkSizeStable);
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
|
||||
// app.registerExtension({
|
||||
// name: "Bjornulf.ImageNote",
|
||||
// async nodeCreated(node) {
|
||||
// if (node.comfyClass !== "Bjornulf_ImageNote") return;
|
||||
|
||||
// // Add Save Note button
|
||||
// node.addWidget("button", "Save Note", null, () => {
|
||||
// const imagePathWidget = node.widgets.find(w => w.name === "image_path");
|
||||
// const noteTextWidget = node.widgets.find(w => w.name === "note_text");
|
||||
|
||||
// if (!imagePathWidget?.value) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// fetch("/save_note", {
|
||||
// method: "POST",
|
||||
// body: JSON.stringify({
|
||||
// image_path: imagePathWidget.value,
|
||||
// note_text: noteTextWidget?.value || ""
|
||||
// }),
|
||||
// headers: { "Content-Type": "application/json" }
|
||||
// })
|
||||
// .then(response => response.json())
|
||||
// .catch(error => {
|
||||
// console.error("Error saving note:", error);
|
||||
// });
|
||||
// });
|
||||
|
||||
// // Add Load Note button
|
||||
// node.addWidget("button", "Load Note", null, () => {
|
||||
// const imagePathWidget = node.widgets.find(w => w.name === "image_path");
|
||||
|
||||
// if (!imagePathWidget?.value) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// fetch("/load_note", {
|
||||
// method: "POST",
|
||||
// body: JSON.stringify({ image_path: imagePathWidget.value }),
|
||||
// headers: { "Content-Type": "application/json" }
|
||||
// })
|
||||
// .then(response => response.json())
|
||||
// .then(data => {
|
||||
// if (data.success) {
|
||||
// const noteTextWidget = node.widgets.find(w => w.name === "note_text");
|
||||
// if (noteTextWidget) {
|
||||
// noteTextWidget.value = data.note_text;
|
||||
// // Trigger widget changed event to update UI
|
||||
// app.graph.setDirtyCanvas(true);
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// .catch(error => {
|
||||
// console.error("Error loading note:", error);
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
90
web/js/switches.js
Normal file
90
web/js/switches.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import { app } from "/scripts/app.js"; // Adjust path based on ComfyUI's structure
|
||||
|
||||
app.registerExtension({
|
||||
name: "Bjornulf.SwitchText",
|
||||
async nodeCreated(node) {
|
||||
if (node.comfyClass === "Bjornulf_SwitchText") {
|
||||
// Store original colors
|
||||
const originalColor = ""; // Default ComfyUI node color
|
||||
|
||||
// Function to update color based on switch value
|
||||
const updateNodeColor = () => {
|
||||
const switchWidget = node.widgets?.find(w => w.name === "switch");
|
||||
if (switchWidget) {
|
||||
const isTrue = switchWidget.value;
|
||||
node.color = isTrue ? originalColor : "#640000"; // Red when false
|
||||
}
|
||||
};
|
||||
|
||||
const updateNodeColorPickMe = () => {
|
||||
const pickMeWidget = node.widgets?.find(w => w.name === "ONLY_ME_combine_text");
|
||||
if (pickMeWidget) {
|
||||
const isPicked = pickMeWidget.value;
|
||||
node.color = isPicked ? "#000064" : originalColor; // Red when false
|
||||
}
|
||||
}
|
||||
|
||||
// Initial color update
|
||||
updateNodeColor();
|
||||
|
||||
// Hook into widget value changes
|
||||
const originalSetValue = node.widgets?.find(w => w.name === "switch")?.callback;
|
||||
node.widgets.find(w => w.name === "switch").callback = function(value) {
|
||||
updateNodeColor();
|
||||
if (originalSetValue) {
|
||||
originalSetValue.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// Hook into widget value changes
|
||||
const originalSetValuePickMe = node.widgets?.find(w => w.name === "ONLY_ME_combine_text")?.callback;
|
||||
node.widgets.find(w => w.name === "ONLY_ME_combine_text").callback = function(value) {
|
||||
updateNodeColorPickMe();
|
||||
if (originalSetValuePickMe) {
|
||||
originalSetValuePickMe.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// Cleanup on node removal (optional but good practice)
|
||||
node.onRemoved = function() {
|
||||
node.color = originalColor;
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.registerExtension({
|
||||
name: "Bjornulf.SwitchAnything",
|
||||
async nodeCreated(node) {
|
||||
if (node.comfyClass === "Bjornulf_SwitchAnything") {
|
||||
// Store original colors
|
||||
const originalColor = ""; // Default ComfyUI node color
|
||||
|
||||
// Function to update color based on switch value
|
||||
const updateNodeColor = () => {
|
||||
const switchWidget = node.widgets?.find(w => w.name === "switch");
|
||||
if (switchWidget) {
|
||||
const isTrue = switchWidget.value;
|
||||
node.color = isTrue ? originalColor : "#640000"; // Red when false
|
||||
}
|
||||
};
|
||||
|
||||
// Initial color update
|
||||
updateNodeColor();
|
||||
|
||||
// Hook into widget value changes
|
||||
const originalSetValue = node.widgets?.find(w => w.name === "switch")?.callback;
|
||||
node.widgets.find(w => w.name === "switch").callback = function(value) {
|
||||
updateNodeColor();
|
||||
if (originalSetValue) {
|
||||
originalSetValue.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// Cleanup on node removal (optional but good practice)
|
||||
node.onRemoved = function() {
|
||||
node.color = originalColor;
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { api } from '../../../scripts/api.js';
|
||||
import { app } from "../../../scripts/app.js";
|
||||
|
||||
function displayVideoPreview(component, filename, category) {
|
||||
function displayVideoPreview(component, filename, category, autoplay, mute) {
|
||||
let videoWidget = component._videoWidget;
|
||||
if (!videoWidget) {
|
||||
// Create the widget if it doesn't exist
|
||||
@@ -61,6 +61,10 @@ function displayVideoPreview(component, filename, category) {
|
||||
"rand": Math.random().toString().slice(2, 12)
|
||||
};
|
||||
const urlParams = new URLSearchParams(params);
|
||||
if(mute) videoWidget.videoElement.muted = true;
|
||||
else videoWidget.videoElement.muted = false;
|
||||
if(autoplay) videoWidget.videoElement.autoplay = !videoWidget.value.paused && !videoWidget.value.hidden;
|
||||
else videoWidget.videoElement.autoplay = false;
|
||||
videoWidget.videoElement.src = `http://localhost:8188/api/view?${urlParams.toString()}`;
|
||||
|
||||
adjustSize(component); // Adjust the component size
|
||||
@@ -76,8 +80,10 @@ app.registerExtension({
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, appInstance) {
|
||||
if (nodeData?.name == "Bjornulf_VideoPreview") {
|
||||
nodeType.prototype.onExecuted = function (data) {
|
||||
displayVideoPreview(this, data.video[0], data.video[1]);
|
||||
const autoplay = this.widgets.find(w => w.name === "autoplay")?.value ?? false;
|
||||
const mute = this.widgets.find(w => w.name === "mute")?.value ?? true;
|
||||
displayVideoPreview(this, data.video[0], data.video[1], autoplay, mute);
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -2,56 +2,73 @@ import { app } from "../../../scripts/app.js";
|
||||
|
||||
// Helper function to clean up widget DOM elements
|
||||
function cleanupWidgetDOM(widget) {
|
||||
if (widget && widget.inputEl) {
|
||||
if (widget.inputEl.parentElement) {
|
||||
widget.inputEl.parentElement.remove();
|
||||
} else {
|
||||
widget.inputEl.remove();
|
||||
}
|
||||
if (widget && widget.inputEl) {
|
||||
if (widget.inputEl.parentElement) {
|
||||
widget.inputEl.parentElement.remove();
|
||||
} else {
|
||||
widget.inputEl.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getChainNodes(startNode) {
|
||||
const nodes = [];
|
||||
let currentNode = startNode;
|
||||
const nodes = [];
|
||||
let currentNode = startNode;
|
||||
const visitedUpstream = new Set();
|
||||
|
||||
// First traverse upstream to find the root node
|
||||
while (true) {
|
||||
const input = currentNode.inputs.find(i => i.name === "pickme_chain");
|
||||
if (input?.link) {
|
||||
const link = app.graph.links[input.link];
|
||||
const prevNode = app.graph.getNodeById(link.origin_id);
|
||||
if (prevNode?.comfyClass === "Bjornulf_WriteTextPickMeChain") {
|
||||
currentNode = prevNode;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
// First traverse upstream to find the root node
|
||||
while (true) {
|
||||
if (visitedUpstream.has(currentNode.id)) {
|
||||
throw new Error(
|
||||
"Infinite loop detected! Nodes form a circular chain through 'pickme_chain' inputs"
|
||||
);
|
||||
}
|
||||
visitedUpstream.add(currentNode.id);
|
||||
|
||||
// Now traverse downstream from root
|
||||
while (currentNode) {
|
||||
nodes.push(currentNode);
|
||||
const output = currentNode.outputs.find(o => o.name === "chain_text");
|
||||
if (output?.links) {
|
||||
let nextNode = null;
|
||||
for (const linkId of output.links) {
|
||||
const link = app.graph.links[linkId];
|
||||
const targetNode = app.graph.getNodeById(link.target_id);
|
||||
if (targetNode?.comfyClass === "Bjornulf_WriteTextPickMeChain") {
|
||||
nextNode = targetNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentNode = nextNode;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
const input = currentNode.inputs.find((i) => i.name === "pickme_chain");
|
||||
if (input?.link) {
|
||||
const link = app.graph.links[input.link];
|
||||
const prevNode = app.graph.getNodeById(link.origin_id);
|
||||
if (prevNode?.comfyClass === "Bjornulf_WriteTextPickMeChain") {
|
||||
currentNode = prevNode;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
// Now traverse downstream from root
|
||||
const visitedDownstream = new Set();
|
||||
while (currentNode) {
|
||||
if (visitedDownstream.has(currentNode.id)) {
|
||||
app.ui.dialog.show("Infinite loop detected! Nodes form a circular chain through 'chain_text' outputs");
|
||||
throw new Error(
|
||||
"Infinite loop detected! Nodes form a circular chain through 'chain_text' outputs"
|
||||
);
|
||||
}
|
||||
visitedDownstream.add(currentNode.id);
|
||||
nodes.push(currentNode);
|
||||
|
||||
const output = currentNode.outputs.find((o) => o.name === "chain_text");
|
||||
if (output?.links) {
|
||||
let nextNode = null;
|
||||
for (const linkId of output.links) {
|
||||
const link = app.graph.links[linkId];
|
||||
const targetNode = app.graph.getNodeById(link.target_id);
|
||||
if (targetNode?.comfyClass === "Bjornulf_WriteTextPickMeChain") {
|
||||
nextNode = targetNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentNode = nextNode;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function pickNode(node) {
|
||||
@@ -67,8 +84,6 @@ function pickNode(node) {
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}
|
||||
|
||||
// Rest of the code remains the same as previous working version
|
||||
|
||||
function findAndPickNext(removedNode) {
|
||||
const chainNodes = getChainNodes(removedNode);
|
||||
const remaining = chainNodes.filter(n => n.id !== removedNode.id);
|
||||
@@ -76,97 +91,100 @@ function findAndPickNext(removedNode) {
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: "Bjornulf.WriteTextPickMeChain",
|
||||
async nodeCreated(node) {
|
||||
if (node.comfyClass === "Bjornulf_WriteTextPickMeChain") {
|
||||
// Store original onRemoved if it exists
|
||||
const origOnRemoved = node.onRemoved;
|
||||
// Create widgets in specific order to maintain layout
|
||||
// const textWidget = node.widgets.find(w => w.name === "text");
|
||||
// if (textWidget) {
|
||||
// textWidget.computeSize = function() {
|
||||
// return [node.size[0] - 20, 150];
|
||||
// };
|
||||
// }
|
||||
name: "Bjornulf.WriteTextPickMeChain",
|
||||
async nodeCreated(node) {
|
||||
if (node.comfyClass === "Bjornulf_WriteTextPickMeChain") {
|
||||
// Store original onRemoved if it exists
|
||||
const origOnRemoved = node.onRemoved;
|
||||
// Create widgets in specific order to maintain layout
|
||||
// const textWidget = node.widgets.find(w => w.name === "text");
|
||||
// if (textWidget) {
|
||||
// textWidget.computeSize = function() {
|
||||
// return [node.size[0] - 20, 150];
|
||||
// };
|
||||
// }
|
||||
|
||||
// Handle picked widget
|
||||
let pickedWidget = node.widgets.find(w => w.name === "picked");
|
||||
if (!pickedWidget) {
|
||||
pickedWidget = node.addWidget("BOOLEAN", "picked", false, null);
|
||||
}
|
||||
pickedWidget.visible = false;
|
||||
// Handle picked widget
|
||||
let pickedWidget = node.widgets.find((w) => w.name === "picked");
|
||||
if (!pickedWidget) {
|
||||
pickedWidget = node.addWidget("BOOLEAN", "picked", false, null);
|
||||
}
|
||||
pickedWidget.visible = false;
|
||||
|
||||
// Add button after textarea
|
||||
const buttonWidget = node.addWidget("button", "PICK ME", null, () => pickNode(node));
|
||||
buttonWidget.computeSize = function() {
|
||||
return [node.size[0] - 20, 30];
|
||||
};
|
||||
// Add button after textarea
|
||||
const buttonWidget = node.addWidget("button", "PICK ME", null, () =>
|
||||
pickNode(node)
|
||||
);
|
||||
buttonWidget.computeSize = function () {
|
||||
return [node.size[0] - 20, 30];
|
||||
};
|
||||
|
||||
// Set initial node size
|
||||
// node.size = [node.size[0], 200];
|
||||
// node.size = [200, 200];
|
||||
setTimeout(() => {
|
||||
// Update widget positions
|
||||
node.onResize(node.size);
|
||||
|
||||
// Refresh all widgets
|
||||
node.widgets.forEach(w => {
|
||||
if (w.onShow?.(true)) {
|
||||
w.onShow?.(false);
|
||||
}
|
||||
});
|
||||
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}, 10);
|
||||
// Set initial node size
|
||||
// node.size = [node.size[0], 200];
|
||||
// node.size = [200, 200];
|
||||
setTimeout(() => {
|
||||
// Update widget positions
|
||||
node.onResize(node.size);
|
||||
|
||||
// Enhanced cleanup on node removal
|
||||
node.onRemoved = function() {
|
||||
// Call original onRemoved if it exists
|
||||
if (origOnRemoved) {
|
||||
origOnRemoved.call(this);
|
||||
}
|
||||
// Refresh all widgets
|
||||
node.widgets.forEach((w) => {
|
||||
if (w.onShow?.(true)) {
|
||||
w.onShow?.(false);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle chain updates
|
||||
if (this.widgets.find(w => w.name === "picked")?.value) {
|
||||
findAndPickNext(this);
|
||||
}
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}, 10);
|
||||
|
||||
// Clean up all widgets
|
||||
for (const widget of this.widgets) {
|
||||
cleanupWidgetDOM(widget);
|
||||
}
|
||||
|
||||
// Force DOM cleanup and canvas update
|
||||
if (this.domElement) {
|
||||
this.domElement.remove();
|
||||
}
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
};
|
||||
|
||||
const updateColors = () => {
|
||||
const picked = node.widgets.find(w => w.name === "picked")?.value;
|
||||
node.color = picked ? "#006400" : "";
|
||||
};
|
||||
|
||||
const origSetNodeState = node.setNodeState;
|
||||
node.setNodeState = function(state) {
|
||||
origSetNodeState?.apply(this, arguments);
|
||||
if (state.picked !== undefined) {
|
||||
const widget = this.widgets.find(w => w.name === "picked");
|
||||
if (widget) widget.value = state.picked;
|
||||
}
|
||||
updateColors();
|
||||
};
|
||||
|
||||
const origGetNodeState = node.getNodeState;
|
||||
node.getNodeState = function() {
|
||||
const state = origGetNodeState?.apply(this, arguments) || {};
|
||||
state.picked = this.widgets.find(w => w.name === "picked")?.value ?? false;
|
||||
return state;
|
||||
};
|
||||
|
||||
// Force initial layout update
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
// Enhanced cleanup on node removal
|
||||
node.onRemoved = function () {
|
||||
// Call original onRemoved if it exists
|
||||
if (origOnRemoved) {
|
||||
origOnRemoved.call(this);
|
||||
}
|
||||
|
||||
// Handle chain updates
|
||||
if (this.widgets.find((w) => w.name === "picked")?.value) {
|
||||
findAndPickNext(this);
|
||||
}
|
||||
|
||||
// Clean up all widgets
|
||||
for (const widget of this.widgets) {
|
||||
cleanupWidgetDOM(widget);
|
||||
}
|
||||
|
||||
// Force DOM cleanup and canvas update
|
||||
if (this.domElement) {
|
||||
this.domElement.remove();
|
||||
}
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
};
|
||||
|
||||
const updateColors = () => {
|
||||
const picked = node.widgets.find((w) => w.name === "picked")?.value;
|
||||
node.color = picked ? "#006400" : "";
|
||||
};
|
||||
|
||||
const origSetNodeState = node.setNodeState;
|
||||
node.setNodeState = function (state) {
|
||||
origSetNodeState?.apply(this, arguments);
|
||||
if (state.picked !== undefined) {
|
||||
const widget = this.widgets.find((w) => w.name === "picked");
|
||||
if (widget) widget.value = state.picked;
|
||||
}
|
||||
updateColors();
|
||||
};
|
||||
|
||||
const origGetNodeState = node.getNodeState;
|
||||
node.getNodeState = function () {
|
||||
const state = origGetNodeState?.apply(this, arguments) || {};
|
||||
state.picked =
|
||||
this.widgets.find((w) => w.name === "picked")?.value ?? false;
|
||||
return state;
|
||||
};
|
||||
|
||||
// Force initial layout update
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}
|
||||
},
|
||||
});
|
||||
85
web/js/write_pickme_global.js
Normal file
85
web/js/write_pickme_global.js
Normal file
@@ -0,0 +1,85 @@
|
||||
import { app } from "../../../scripts/app.js";
|
||||
|
||||
// Function to pick a node within its global_pickme_id group
|
||||
function pickGlobalNode(node) {
|
||||
const global_pickme_idWidget = node.widgets.find(w => w.name === "global_pickme_id");
|
||||
const global_pickme_id = global_pickme_idWidget ? global_pickme_idWidget.value : "default";
|
||||
|
||||
// Iterate through all nodes in the graph
|
||||
app.graph._nodes.forEach(n => {
|
||||
if (n.comfyClass === "Bjornulf_WriteTextPickMeGlobal") {
|
||||
const nglobal_pickme_idWidget = n.widgets.find(w => w.name === "global_pickme_id");
|
||||
const nglobal_pickme_id = nglobal_pickme_idWidget ? nglobal_pickme_idWidget.value : "default";
|
||||
if (nglobal_pickme_id === global_pickme_id) { // Only affect nodes in the same group
|
||||
const pickedWidget = n.widgets.find(w => w.name === "picked");
|
||||
if (pickedWidget) {
|
||||
pickedWidget.value = (n === node); // Pick this node, unpick others in group
|
||||
}
|
||||
n.color = (n === node) ? "#006400" : ""; // Green for picked, default otherwise
|
||||
}
|
||||
}
|
||||
});
|
||||
app.graph.setDirtyCanvas(true, true); // Refresh the canvas
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: "Bjornulf.WriteTextPickMeGlobal",
|
||||
async nodeCreated(node) {
|
||||
if (node.comfyClass === "Bjornulf_WriteTextPickMeGlobal") {
|
||||
// Hide the picked widget from the UI
|
||||
const pickedWidget = node.widgets.find(w => w.name === "picked");
|
||||
if (pickedWidget && pickedWidget.inputEl) {
|
||||
pickedWidget.inputEl.style.display = "none";
|
||||
}
|
||||
|
||||
// Add "PICK ME" button
|
||||
const buttonWidget = node.addWidget("button", "PICK ME", null, () => {
|
||||
pickGlobalNode(node); // Handle picking within the group
|
||||
});
|
||||
buttonWidget.computeSize = function () {
|
||||
return [node.size[0] - 20, 30]; // Size the button
|
||||
};
|
||||
|
||||
// Function to update node color based on picked state
|
||||
const updateColors = () => {
|
||||
const picked = node.widgets.find(w => w.name === "picked")?.value;
|
||||
node.color = picked ? "#006400" : ""; // Green if picked
|
||||
};
|
||||
updateColors(); // Set initial color
|
||||
|
||||
// Handle global_pickme_id changes
|
||||
const global_pickme_idWidget = node.widgets.find(w => w.name === "global_pickme_id");
|
||||
if (global_pickme_idWidget) {
|
||||
global_pickme_idWidget.onChange = function() {
|
||||
const pickedWidget = node.widgets.find(w => w.name === "picked");
|
||||
if (pickedWidget && pickedWidget.value) {
|
||||
pickedWidget.value = false; // Unpick if global_pickme_id changes
|
||||
node.color = "";
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// State management for saving/loading
|
||||
const origSetNodeState = node.setNodeState;
|
||||
node.setNodeState = function (state) {
|
||||
origSetNodeState?.apply(this, arguments);
|
||||
if (state.picked !== undefined) {
|
||||
const widget = this.widgets.find(w => w.name === "picked");
|
||||
if (widget) widget.value = state.picked;
|
||||
}
|
||||
updateColors();
|
||||
};
|
||||
|
||||
const origGetNodeState = node.getNodeState;
|
||||
node.getNodeState = function () {
|
||||
const state = origGetNodeState?.apply(this, arguments) || {};
|
||||
state.picked = this.widgets.find(w => w.name === "picked")?.value ?? false;
|
||||
return state;
|
||||
};
|
||||
|
||||
// Refresh canvas on load
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user