150 lines
4.9 KiB
JavaScript
150 lines
4.9 KiB
JavaScript
import { app } from "../../scripts/app.js";
|
|
|
|
const TypeSlot = {
|
|
Input: 1,
|
|
Output: 2,
|
|
};
|
|
|
|
const TypeSlotEvent = {
|
|
Connect: true,
|
|
Disconnect: false,
|
|
};
|
|
|
|
function node_add_dynamic(nodeType, prefix, type = '*', count = -1) {
|
|
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
|
nodeType.prototype.onNodeCreated = function () {
|
|
const me = onNodeCreated?.apply(this);
|
|
this.addInput(`${prefix}1`, type);
|
|
return me;
|
|
};
|
|
|
|
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
|
|
nodeType.prototype.onConnectionsChange = function (slotType, slot, event, link_info, data) {
|
|
const me = onConnectionsChange?.apply(this, arguments);
|
|
if (slotType === TypeSlot.Input) {
|
|
if (!this.inputs[slot].name.startsWith(prefix)) {
|
|
return;
|
|
}
|
|
|
|
// remove all non connected inputs
|
|
if (event == TypeSlotEvent.Disconnect && this.inputs.length > 1) {
|
|
if (this.widgets) {
|
|
const widget = this.widgets.find((w) => w.name === this.inputs[slot].name);
|
|
if (widget) {
|
|
widget.onRemoved?.();
|
|
this.widgets = this.widgets.filter((w) => w.name !== widget.name);
|
|
}
|
|
}
|
|
this.removeInput(slot)
|
|
|
|
// make inputs sequential again
|
|
for (let i = 0; i < this.inputs.length; i++) {
|
|
const name = `${prefix}${i + 1}`;
|
|
this.inputs[i].label = name;
|
|
this.inputs[i].name = name;
|
|
}
|
|
}
|
|
|
|
if (count - 1 < 0) {
|
|
count = 1000;
|
|
}
|
|
const length = this.inputs.length - 1;
|
|
if (length < count - 1 && this.inputs[length].link != undefined) {
|
|
const nextIndex = this.inputs.length;
|
|
const name = `${prefix}${nextIndex + 1}`;
|
|
this.addInput(name, type);
|
|
}
|
|
|
|
if (event === TypeSlotEvent.Connect && link_info) {
|
|
const fromNode = this.graph._nodes.find(
|
|
(otherNode) => otherNode.id == link_info.origin_id
|
|
);
|
|
if (fromNode) {
|
|
const old_type = fromNode.outputs[link_info.origin_slot].type;
|
|
this.inputs[slot].type = old_type;
|
|
}
|
|
} else if (event === TypeSlotEvent.Disconnect) {
|
|
this.inputs[slot].type = type;
|
|
this.inputs[slot].label = `${prefix}${slot + 1}`;
|
|
}
|
|
}
|
|
return me;
|
|
};
|
|
return nodeType;
|
|
}
|
|
|
|
app.registerExtension({
|
|
name: "Comfy.superbeastsai_nodes",
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
const dynamicInputConfigs = {
|
|
"Image Batch Manager (SuperBeasts.AI)": { type: "IMAGE", prefix: "image" },
|
|
"Mask Batch Manager (SuperBeasts.AI)": { type: "MASK", prefix: "mask" },
|
|
"String List Manager (SuperBeasts.AI)": { type: "STRING", prefix: "string" },
|
|
};
|
|
|
|
if (nodeData.name in dynamicInputConfigs) {
|
|
const { type, prefix } = dynamicInputConfigs[nodeData.name];
|
|
nodeType = node_add_dynamic(nodeType, prefix, type);
|
|
|
|
nodeType.prototype.onExecutionStart = function () {
|
|
|
|
// Assume 'this.widgets' contains all the widgets of the node
|
|
const max_images = getWidgetValueByName(this.widgets, 'max_images');
|
|
const randomOrderValue = getWidgetValueByName(this.widgets, 'random_order');
|
|
|
|
if (randomOrderValue) {
|
|
// Filter image inputs and ensure only valid image slots are considered
|
|
const imageInputs = this.inputs.filter(input => input.type === 'IMAGE');
|
|
|
|
// Determine the effective number of indices to consider
|
|
let effectiveLength = Math.min(imageInputs.length, max_images);
|
|
|
|
// Ensure we do not accidentally reduce the number of images if not needed
|
|
if (effectiveLength > 0 && imageInputs.length >= max_images) {
|
|
// Generate an array of indices based on the effective length
|
|
let indices = Array.from({length: effectiveLength}, (_, i) => i + 1);
|
|
shuffle(indices); // Shuffle the indices to randomize
|
|
|
|
// Convert indices to a string to set as the new value
|
|
const newOrder = indices.join(',');
|
|
|
|
// Set the 'new_manual_order' widget value
|
|
setWidgetValueByName(this.widgets, 'new_manual_order', newOrder);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// Helper function to shuffle an array (Fisher-Yates shuffle)
|
|
function shuffle(array) {
|
|
for (let i = array.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
[array[i], array[j]] = [array[j], array[i]]; // Swap elements
|
|
}
|
|
}
|
|
|
|
function getWidgetValueByName(widgets, widgetName) {
|
|
// Check if widgets are defined and iterable
|
|
if (!widgets || !Array.isArray(widgets)) {
|
|
return undefined;
|
|
}
|
|
|
|
// Find the widget by name
|
|
const widget = widgets.find(w => w.name === widgetName);
|
|
return widget ? widget.value : undefined;
|
|
}
|
|
|
|
function setWidgetValueByName(widgets, widgetName, value) {
|
|
if (!widgets || !Array.isArray(widgets)) {
|
|
return false;
|
|
}
|
|
|
|
const widget = widgets.find(w => w.name === widgetName);
|
|
if (widget) {
|
|
widget.value = value;
|
|
return true;
|
|
}
|
|
return false;
|
|
} |