Files
WainWong-ComfyUI-Loop-image/web/node/dynamicnode.js
T
WainWong abe0004331 Initial commit
Features:
- Implemented batch image processing nodes (Loop Open/Close)
- Implemented single image processing nodes
- Added Loop Index Switch for dynamic input control
- Added mask segmentation and merging functionality

Core components:
- flow_control.py: Main loop control implementation
- mask_split.py: Mask processing utilities
- web/node/dynamicnode.js: Dynamic input UI implementation

Documentation:
- Added detailed README in both English and Chinese
- Included usage instructions and node documentation
- Added acknowledgments and references"
2025-01-01 00:11:34 +08:00

109 lines
3.9 KiB
JavaScript

import { app } from "../../../scripts/app.js"
const _ID = "CyberEve_LoopIndexSwitch";
const _PREFIX = "while_";
const _TYPE = "*";
const MAX_INPUTS = 100;
app.registerExtension({
name: 'CyberEveLoop.LoopIndexSwitch',
async beforeRegisterNodeDef(nodeType, nodeData, app) {
// 添加调试信息
console.log("Registering extension for:", nodeData.name);
console.log("Looking for:", _ID);
if (nodeData.name !== _ID) {
return;
}
// 添加右键菜单选项
const onGetExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
nodeType.prototype.getExtraMenuOptions = function(_, options) {
if (onGetExtraMenuOptions) {
onGetExtraMenuOptions.apply(this, arguments);
}
// 添加输入槽
options.push({
content: "Add Loop Input",
callback: () => {
// 弹出对话框让用户输入循环次数
const number = prompt("Enter loop iteration number (0-99):", "0");
if (number === null || isNaN(number)) {
return;
}
const num = parseInt(number);
if (num < 0 || num >= MAX_INPUTS) {
alert(`Please enter a number between 0 and ${MAX_INPUTS-1}`);
return;
}
const slotName = `${_PREFIX}${num}`;
// 检查是否已存在该输入槽
if (this.inputs.find(input => input.name === slotName)) {
alert(`Input for iteration ${num} already exists!`);
return;
}
// 添加新的输入槽
this.addInput(slotName, _TYPE);
this.graph.setDirtyCanvas(true);
}
});
// 删除输入槽子菜单
const valueInputs = this.inputs.filter(input =>
input.name.startsWith(_PREFIX)
);
if (valueInputs.length > 0) {
const removeOptions = valueInputs.map(input => ({
content: `Remove iteration ${input.name.substring(_PREFIX.length)}`,
callback: () => {
const index = this.inputs.findIndex(i => i.name === input.name);
if (index !== -1) {
this.removeInput(index);
this.graph.setDirtyCanvas(true);
}
}
}));
options.push({
content: "Remove Loop Input",
submenu: {
options: removeOptions
}
});
}
};
// 序列化节点时保存输入槽信息
nodeType.prototype.serialize = function() {
const data = LGraphNode.prototype.serialize.apply(this);
data.inputSlots = this.inputs.filter(input =>
input.name.startsWith(_PREFIX)
).map(input => ({
name: input.name,
type: input.type
}));
return data;
};
// 反序列化时恢复输入槽
nodeType.prototype.configure = function(data) {
LGraphNode.prototype.configure.apply(this, arguments);
if (data.inputSlots) {
// 移除所有循环相关的输入
this.inputs = this.inputs.filter(input =>
!input.name.startsWith(_PREFIX)
);
// 恢复保存的输入槽
data.inputSlots.forEach(slot => {
this.addInput(slot.name, slot.type);
});
}
};
}
});