Add custom nodes, Civitai loras (LFS), and vast.ai setup script
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Includes 30 custom nodes committed directly, 7 Civitai-exclusive loras stored via Git LFS, and a setup script that installs all dependencies and downloads HuggingFace-hosted models on vast.ai. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
// 1.0.2
|
||||
import { app } from "../../../../scripts/app.js";
|
||||
import { GroupNodeConfig } from "../../../../extensions/core/groupNode.js";
|
||||
import { api } from "../../../../scripts/api.js";
|
||||
import { $t } from "../common/i18n.js"
|
||||
|
||||
const nodeTemplateShortcutId = "Comfy.EasyUse.NodeTemplateShortcut"
|
||||
const processBarId = "Comfy.EasyUse.queueProcessBar"
|
||||
|
||||
let enableNodeTemplateShortcut = true
|
||||
let enableQueueProcess = false
|
||||
|
||||
export function addNodeTemplateShortcutSetting(app) {
|
||||
app.ui.settings.addSetting({
|
||||
id: nodeTemplateShortcutId,
|
||||
name: $t("Enable ALT+1~9 to paste nodes from nodes template (ComfyUI-Easy-Use)"),
|
||||
type: "boolean",
|
||||
defaultValue: enableNodeTemplateShortcut,
|
||||
onChange(value) {
|
||||
enableNodeTemplateShortcut = !!value;
|
||||
},
|
||||
});
|
||||
}
|
||||
export function addQueueProcessSetting(app) {
|
||||
app.ui.settings.addSetting({
|
||||
id: processBarId,
|
||||
name: $t("Enable process bar in queue button (ComfyUI-Easy-Use)"),
|
||||
type: "boolean",
|
||||
defaultValue: enableQueueProcess,
|
||||
onChange(value) {
|
||||
enableQueueProcess = !!value;
|
||||
},
|
||||
});
|
||||
}
|
||||
const getEnableNodeTemplateShortcut = _ => app.ui.settings.getSettingValue(nodeTemplateShortcutId, true)
|
||||
const getQueueProcessSetting = _ => app.ui.settings.getSettingValue(processBarId, false)
|
||||
|
||||
function loadTemplate(){
|
||||
return localStorage['Comfy.NodeTemplates'] ? JSON.parse(localStorage['Comfy.NodeTemplates']) : null
|
||||
}
|
||||
const clipboardAction = async (cb) => {
|
||||
const old = localStorage.getItem("litegrapheditor_clipboard");
|
||||
await cb();
|
||||
localStorage.setItem("litegrapheditor_clipboard", old);
|
||||
};
|
||||
async function addTemplateToCanvas(t){
|
||||
const data = JSON.parse(t.data);
|
||||
await GroupNodeConfig.registerFromWorkflow(data.groupNodes, {});
|
||||
localStorage.setItem("litegrapheditor_clipboard", t.data);
|
||||
app.canvas.pasteFromClipboard();
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: 'comfy.easyUse.quick',
|
||||
init() {
|
||||
const keybindListener = async function (event) {
|
||||
let modifierPressed = event.altKey;
|
||||
const isEnabled = getEnableNodeTemplateShortcut()
|
||||
if(isEnabled){
|
||||
const mac_alt_nums = ['¡','™','£','¢','∞','§','¶','•','ª']
|
||||
const nums = ['1','2','3','4','5','6','7','8','9']
|
||||
let key = event.key
|
||||
if(mac_alt_nums.includes(key)){
|
||||
const idx = mac_alt_nums.findIndex(cate=> cate == key)
|
||||
key = nums[idx]
|
||||
modifierPressed = true
|
||||
}
|
||||
if(['1','2','3','4','5','6','7','8','9'].includes(key) && modifierPressed) {
|
||||
const template = loadTemplate()
|
||||
const idx = parseInt(key) - 1
|
||||
if (template && template[idx]) {
|
||||
let t = template[idx]
|
||||
try{
|
||||
let data = JSON.parse(t.data)
|
||||
data.title = t.name
|
||||
t.data = JSON.stringify(data)
|
||||
clipboardAction(_ => {
|
||||
addTemplateToCanvas(t)
|
||||
})
|
||||
}catch (e){
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
}
|
||||
if (event.ctrlKey || event.altKey || event.metaKey) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
window.addEventListener("keydown", keybindListener, true);
|
||||
},
|
||||
|
||||
setup(app) {
|
||||
addNodeTemplateShortcutSetting(app)
|
||||
addQueueProcessSetting(app)
|
||||
registerListeners()
|
||||
}
|
||||
});
|
||||
|
||||
const registerListeners = () => {
|
||||
const queue_button = document.getElementById("queue-button")
|
||||
const old_queue_button_text = queue_button.innerText
|
||||
api.addEventListener('progress', ({
|
||||
detail,
|
||||
}) => {
|
||||
const isEnabled = getQueueProcessSetting()
|
||||
if(isEnabled){
|
||||
const {
|
||||
value, max, node,
|
||||
} = detail;
|
||||
const progress = Math.floor((value / max) * 100);
|
||||
// console.log(progress)
|
||||
if (!isNaN(progress) && progress >= 0 && progress <= 100) {
|
||||
queue_button.innerText = progress ==0 || progress == 100 ? old_queue_button_text : "ㅤ "
|
||||
const width = progress ==0 || progress == 100 ? '0%' : progress.toString() + '%'
|
||||
let bar = document.createElement("div")
|
||||
queue_button.setAttribute('data-attr', progress ==0 || progress == 100 ? "" : progress.toString() + '%')
|
||||
document.documentElement.style.setProperty('--process-bar-width', width)
|
||||
}
|
||||
}
|
||||
|
||||
}, false);
|
||||
|
||||
api.addEventListener('status', ({
|
||||
detail,
|
||||
}) => {
|
||||
const queueRemaining = detail?.exec_info.queue_remaining;
|
||||
if(queueRemaining === 0){
|
||||
let queue_button = document.getElementById("queue-button")
|
||||
queue_button.innerText = old_queue_button_text
|
||||
queue_button.setAttribute('data-attr', "")
|
||||
document.documentElement.style.setProperty('--process-bar-width', '0%')
|
||||
}
|
||||
}, false);
|
||||
};
|
||||
|
||||
|
||||
// 修改粘贴指令
|
||||
LGraphCanvas.prototype.pasteFromClipboard = function(isConnectUnselected = false) {
|
||||
// if ctrl + shift + v is off, return when isConnectUnselected is true (shift is pressed) to maintain old behavior
|
||||
if (!LiteGraph.ctrl_shift_v_paste_connect_unselected_outputs && isConnectUnselected) {
|
||||
return;
|
||||
}
|
||||
var data = localStorage.getItem("litegrapheditor_clipboard");
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.graph.beforeChange();
|
||||
|
||||
//create nodes
|
||||
var clipboard_info = JSON.parse(data);
|
||||
// calculate top-left node, could work without this processing but using diff with last node pos :: clipboard_info.nodes[clipboard_info.nodes.length-1].pos
|
||||
var posMin = false;
|
||||
var posMinIndexes = false;
|
||||
for (var i = 0; i < clipboard_info.nodes.length; ++i) {
|
||||
if (posMin){
|
||||
if(posMin[0]>clipboard_info.nodes[i].pos[0]){
|
||||
posMin[0] = clipboard_info.nodes[i].pos[0];
|
||||
posMinIndexes[0] = i;
|
||||
}
|
||||
if(posMin[1]>clipboard_info.nodes[i].pos[1]){
|
||||
posMin[1] = clipboard_info.nodes[i].pos[1];
|
||||
posMinIndexes[1] = i;
|
||||
}
|
||||
}
|
||||
else{
|
||||
posMin = [clipboard_info.nodes[i].pos[0], clipboard_info.nodes[i].pos[1]];
|
||||
posMinIndexes = [i, i];
|
||||
}
|
||||
}
|
||||
var nodes = [];
|
||||
var left_arr = [], right_arr = [], top_arr =[], bottom_arr =[];
|
||||
|
||||
for (var i = 0; i < clipboard_info.nodes.length; ++i) {
|
||||
var node_data = clipboard_info.nodes[i];
|
||||
var node = LiteGraph.createNode(node_data.type);
|
||||
if (node) {
|
||||
|
||||
node.configure(node_data);
|
||||
//paste in last known mouse position
|
||||
node.pos[0] += this.graph_mouse[0] - posMin[0]; //+= 5;
|
||||
node.pos[1] += this.graph_mouse[1] - posMin[1]; //+= 5;
|
||||
|
||||
left_arr.push(node.pos[0])
|
||||
right_arr.push(node.pos[0] + node.size[0])
|
||||
top_arr.push(node.pos[1])
|
||||
bottom_arr.push(node.pos[1] + node.size[1])
|
||||
|
||||
this.graph.add(node,{doProcessChange:false});
|
||||
|
||||
nodes.push(node);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(clipboard_info.title){
|
||||
var l = Math.min(...left_arr) - 15;
|
||||
var r = Math.max(...right_arr) - this.graph_mouse[0] + 30;
|
||||
var t = Math.min(...top_arr) - 100;
|
||||
var b = Math.max(...bottom_arr) - this.graph_mouse[1] + 130;
|
||||
|
||||
// create group
|
||||
const groups = [
|
||||
{
|
||||
"title": clipboard_info.title,
|
||||
"bounding": [
|
||||
l,
|
||||
t,
|
||||
r,
|
||||
b
|
||||
],
|
||||
"color": "#3f789e",
|
||||
"font_size": 24,
|
||||
"locked": false
|
||||
}
|
||||
]
|
||||
|
||||
for (var i = 0; i < groups.length; ++i) {
|
||||
var group = new LiteGraph.LGraphGroup();
|
||||
group.configure(groups[i]);
|
||||
this.graph.add(group);
|
||||
}
|
||||
}
|
||||
|
||||
//create links
|
||||
for (var i = 0; i < clipboard_info.links.length; ++i) {
|
||||
var link_info = clipboard_info.links[i];
|
||||
var origin_node;
|
||||
var origin_node_relative_id = link_info[0];
|
||||
if (origin_node_relative_id != null) {
|
||||
origin_node = nodes[origin_node_relative_id];
|
||||
} else if (LiteGraph.ctrl_shift_v_paste_connect_unselected_outputs && isConnectUnselected) {
|
||||
var origin_node_id = link_info[4];
|
||||
if (origin_node_id) {
|
||||
origin_node = this.graph.getNodeById(origin_node_id);
|
||||
}
|
||||
}
|
||||
var target_node = nodes[link_info[2]];
|
||||
if( origin_node && target_node )
|
||||
origin_node.connect(link_info[1], target_node, link_info[3]);
|
||||
else
|
||||
console.warn("Warning, nodes missing on pasting");
|
||||
}
|
||||
|
||||
this.selectNodes(nodes);
|
||||
this.graph.afterChange();
|
||||
};
|
||||
Reference in New Issue
Block a user