Spaces:
Configuration error
Configuration error
// 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(); | |
}; |