diff --git a/groupNode/groupNodes.json b/groupNode/groupNodes.json index 9e26dfe..7a2db8d 100644 --- a/groupNode/groupNodes.json +++ b/groupNode/groupNodes.json @@ -1 +1,243 @@ -{} \ No newline at end of file +{ + "胜多负少": { + "nodes": [ + { + "id": -1, + "type": "KSampler", + "pos": [ + 980, + 197 + ], + "size": [ + 315, + 262 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "label": "模型", + "localized_name": "模型", + "name": "model", + "type": "MODEL", + "link": null + }, + { + "label": "正面条件", + "localized_name": "正面条件", + "name": "positive", + "type": "CONDITIONING", + "link": null + }, + { + "label": "负面条件", + "localized_name": "负面条件", + "name": "negative", + "type": "CONDITIONING", + "link": null + }, + { + "label": "Latent", + "localized_name": "Latent图像", + "name": "latent_image", + "type": "LATENT", + "link": null + }, + { + "localized_name": "随机种", + "name": "seed", + "type": "INT", + "widget": { + "name": "seed" + }, + "link": null + }, + { + "localized_name": "步数", + "name": "steps", + "type": "INT", + "widget": { + "name": "steps" + }, + "link": null + }, + { + "localized_name": "CFG", + "name": "cfg", + "type": "FLOAT", + "widget": { + "name": "cfg" + }, + "link": null + }, + { + "localized_name": "采样器", + "name": "sampler_name", + "type": "COMBO", + "widget": { + "name": "sampler_name" + }, + "link": null + }, + { + "localized_name": "调度器", + "name": "scheduler", + "type": "COMBO", + "widget": { + "name": "scheduler" + }, + "link": null + }, + { + "localized_name": "降噪", + "name": "denoise", + "type": "FLOAT", + "widget": { + "name": "denoise" + }, + "link": null + } + ], + "outputs": [ + { + "label": "Latent", + "localized_name": "Latent", + "name": "LATENT", + "type": "LATENT", + "slot_index": 0, + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "KSampler" + }, + "widgets_values": [ + 156680208700286, + "randomize", + 20, + 8, + "euler", + "normal", + 1 + ], + "index": 0 + }, + { + "id": -1, + "type": "VAEDecode", + "pos": [ + 1326, + 199 + ], + "size": [ + 210, + 46 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "label": "Latent", + "localized_name": "Latent", + "name": "samples", + "type": "LATENT", + "link": null + }, + { + "label": "VAE", + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": null + } + ], + "outputs": [ + { + "label": "图像", + "localized_name": "图像", + "name": "IMAGE", + "type": "IMAGE", + "slot_index": 0, + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "VAEDecode" + }, + "index": 1 + } + ], + "links": [ + [ + null, + 0, + 0, + 0, + 4, + "MODEL" + ], + [ + null, + 0, + 0, + 1, + 6, + "CONDITIONING" + ], + [ + null, + 0, + 0, + 2, + 7, + "CONDITIONING" + ], + [ + null, + 0, + 0, + 3, + 5, + "LATENT" + ], + [ + 0, + 0, + 1, + 0, + 19, + "LATENT" + ], + [ + null, + 2, + 1, + 1, + 4, + "VAE" + ] + ], + "external": [ + [ + 1, + 0, + "IMAGE" + ] + ], + "widgets_values": [ + 156680208700286, + "randomize", + 20, + 8, + "euler", + "normal", + 1 + ] + } +} \ No newline at end of file diff --git a/js/AppParams.js b/js/AppParams.js index e7a1973..2d1d2cf 100644 --- a/js/AppParams.js +++ b/js/AppParams.js @@ -1,29 +1,29 @@ import { app } from "/scripts/app.js"; import { ComfyWidgets } from "/scripts/widgets.js"; -import { GroupNodeConfig,GroupNodeHandler } from "/extensions/core/groupNode.js"; -import { $el,ComfyDialog } from "../../../scripts/ui.js"; +import { GroupNodeConfig, GroupNodeHandler } from "/extensions/core/groupNode.js"; +import { $el, ComfyDialog } from "../../../scripts/ui.js"; import { api } from "../../../scripts/api.js"; // Displays input text on a node const CONVERTED_TYPE = "converted-widget"; -const type2paramType={ - "STRING": "text", - "combo":"select", - "number":"number", - "toggle":"toggle", - "BOOLEAN":"switch", - "text":"text", - "string":"text", - "customtext":"customtext" +const type2paramType = { + "STRING": "text", + "combo": "select", + "number": "number", + "toggle": "toggle", + "BOOLEAN": "switch", + "text": "text", + "string": "text", + "customtext": "customtext" } var update_comfyui_button = null; var switch_comfyui_button = null; var fetch_updates_button = null; var update_all_button = null; let share_option = 'all'; -let manager_instance =null; +let manager_instance = null; $el("style", { - textContent: ` + textContent: ` /*表单样式*/ .lam_app_form { @@ -135,143 +135,155 @@ $el("style", { } `, -parent: document.body, + parent: document.body, }) -let initData={} +let initData = {} class ManagerMenuDialog extends ComfyDialog { createControlsLeft() { - let self = this; - let authorIds=initData?.base?.authorIds || [] - let commands=initData?.commands||[] - let authorEls=[] - for(let id of authorIds){ - authorEls.push($el('ol',{style:{marginRight:'10px'}},[ - $el('span',{textContent:id}), - $el('button',{textContent:'删除',dataset:{authorId:id},$:(el) => { - el.onclick = () => { - initData.base.authorIds=authorIds.filter(id=>id!=el.dataset.authorId) - manager_instance.initElement(); + let self = this; + let authorIds = initData?.base?.authorIds || [] + let commands = initData?.commands || [] + let authorEls = [] + for (let id of authorIds) { + authorEls.push($el('ol', { style: { marginRight: '10px' } }, [ + $el('span', { textContent: id }), + $el('button', { + textContent: '删除', dataset: { authorId: id }, $: (el) => { + el.onclick = () => { + initData.base.authorIds = authorIds.filter(id => id != el.dataset.authorId) + manager_instance.initElement(); + } } - }}), + }), ])) } - let commonEls=[] - for(let command in commands){ - commonEls.push($el('ol',{style:{marginRight:'10px'}},[ - $el('span',{textContent:command}), - $el('button',{textContent:'删除',dataset:{command:command},$:(el) => { - el.onclick = () => { - delete initData.commands[command] - manager_instance.initElement(); + let commonEls = [] + for (let command in commands) { + commonEls.push($el('ol', { style: { marginRight: '10px' } }, [ + $el('span', { textContent: command }), + $el('button', { + textContent: '删除', dataset: { command: command }, $: (el) => { + el.onclick = () => { + delete initData.commands[command] + manager_instance.initElement(); + } } - }}), + }), ])) } - let from =$el("from", [ - $el("div.txtb", [ - $el("label", { textContent: "应用标题:" }), - $el("input", { - name: "appTitle", - value: initData?.base?.appTitle, - onchange: (e) => { - initData.base.appTitle = e.target.value; - }, - }), - ]), - $el("div.txtb", [ - $el("label", { textContent: "应用logo:" }), - $el("input", { - name: "appLogo", - value: initData?.base?.appLogo, - onchange: (e) => { - initData.base.appLogo = e.target.value; - }, - }), - ]), - $el("div.txtb", [ - $el("label", { textContent: "免费次数(0为无限):" }), - $el("input", { - name: "freeSize", - value: initData?.base?.freeSize, - onchange: (e) => { - let value=e.target.value - if(isNaN(value)){ - value=0 - }else{ - value=parseInt(value) - } - initData.base.freeSize = value; - }, - }), - ]), - $el("div.txtb", [ - $el("label", { textContent: "授权编号:" },[ - $el('button',{textContent:'添加',$:(el) => { + let from = $el("from", [ + $el("div.txtb", [ + $el("label", { textContent: "应用标题:" }), + $el("input", { + name: "appTitle", + value: initData?.base?.appTitle, + onchange: (e) => { + initData.base.appTitle = e.target.value; + }, + }), + ]), + $el("div.txtb", [ + $el("label", { textContent: "应用logo:" }), + $el("input", { + name: "appLogo", + value: initData?.base?.appLogo, + onchange: (e) => { + initData.base.appLogo = e.target.value; + }, + }), + ]), + $el("div.txtb", [ + $el("label", { textContent: "免费次数(0为无限):" }), + $el("input", { + name: "freeSize", + value: initData?.base?.freeSize, + onchange: (e) => { + let value = e.target.value + if (isNaN(value)) { + value = 0 + } else { + value = parseInt(value) + } + initData.base.freeSize = value; + }, + }), + ]), + $el("div.txtb", [ + $el("label", { textContent: "授权编号:" }, [ + $el('button', { + textContent: '添加', $: (el) => { el.onclick = () => { //随机字符串 let authorId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); initData.base.authorIds.push(authorId) manager_instance.initElement(); } - }}) - ]), - $el("ul.scroll-container",authorEls) + } + }) ]), - $el("div.txtb", [ - $el("label", { textContent: "应用管理:" }), - $el("ul.scroll-container",commonEls) - ]), - ]) - return [$el('div.lam_app_form',[from, - $el('span.btn',{textContent:'提交',$:(el) => { - el.onclick = () => { - updateInitData() + $el("ul.scroll-container", authorEls) + ]), + $el("div.txtb", [ + $el("label", { textContent: "应用管理:" }), + $el("ul.scroll-container", commonEls) + ]), + ]) + return [$el('div.lam_app_form', [from, + $el('span.btn', { + textContent: '提交', $: (el) => { + el.onclick = () => { + updateInitData() + } } - }}), - $el('span.btn',{textContent:'应用预览',onclick:()=>{ - openAppPage('default') - }}), - $el('span.btn',{textContent:'画板预览',onclick:()=>{ - openAppPage() - }}) + }), + $el('span.btn', { + textContent: '应用预览', onclick: () => { + openAppPage('default') + } + }), + $el('span.btn', { + textContent: '画板预览', onclick: () => { + openAppPage() + } + }) ])]; } - constructor() { - super(); + constructor() { + super(); const close_button = $el("button", { id: "cm-close-button", type: "button", textContent: "Close", onclick: () => this.close() }); - const content = - $el("div.comfy-modal-content", - [ - $el("tr.cm-title", {}, [ - $el("font", {size:6, color:"white"}, [`应用管理`])] - ), - $el("br", {}, []), - $el("div.cm-menu-container", - [ - ...this.createControlsLeft() - ]), + const content = + $el("div.comfy-modal-content", + [ + $el("tr.cm-title", {}, [ + $el("font", { size: 6, color: "white" }, [`应用管理`])] + ), + $el("br", {}, []), + $el("div.cm-menu-container", + [ + ...this.createControlsLeft() + ]), - $el("br", {}, []), - close_button, - ] - ); + $el("br", {}, []), + close_button, + ] + ); - content.style.width = '100%'; - content.style.height = '80%'; - this.element = $el("div.comfy-modal", { id:'cm-manager-dialog', parent: document.body,style:{maxWidth:'700px',height:'800px'} }, [ content ]); - } - - initElement(){ - this.element.children[0].children[2].innerHTML='' - this.element.children[0].children[2].appendChild( ...this.createControlsLeft()) + content.style.width = '100%'; + content.style.height = '80%'; + this.element = $el("div.comfy-modal", { id: 'cm-manager-dialog', parent: document.body, style: { maxWidth: '700px', height: '800px' } }, [content]); } - show() { + initElement() { + this.element.children[0].children[2].innerHTML = '' + this.element.children[0].children[2].appendChild(...this.createControlsLeft()) + } + + show() { this.initElement() - this.element.style.display = "block"; - } + this.element.style.display = "block"; + } } async function openAppPage(type) { try { @@ -279,7 +291,7 @@ async function openAppPage(type) { if (resp.status === 200) { let data = await resp.json(); //打开新标签页面 - window.open('/wechatauth/'+(type=='default'?'app':'index')+'?openId='+data.data); + window.open('/wechatauth/' + (type == 'default' ? 'app' : 'index') + '?openId=' + data.data); return true; } throw new Error(resp.data.msg); @@ -288,14 +300,14 @@ async function openAppPage(type) { } } -async function getAppInit(){ +async function getAppInit() { try { const resp = await api.fetchApi(`/lam/getInitData`); if (resp.status === 200) { let data = await resp.json(); - if(data.success){ + if (data.success) { console.log(data) - initData=data.data + initData = data.data manager_instance.show(); } return true; @@ -308,11 +320,12 @@ async function getAppInit(){ async function updateInitData() { try { - let data={appTitle:initData.base.appTitle, - appLogo:initData.base.appLogo, - freeSize:initData.base.freeSize, - authorIds:initData.base.authorIds, - commands:initData.commands + let data = { + appTitle: initData.base.appTitle, + appLogo: initData.base.appLogo, + freeSize: initData.base.freeSize, + authorIds: initData.base.authorIds, + commands: initData.commands } const response = await api.fetchApi("/lam/updateAppData", { method: "POST", @@ -333,8 +346,8 @@ async function updateInitData() { async function setAppParams(data) { try { - let workflow= await app.graphToPrompt(); - data['workflow']=workflow['output'] + let workflow = await app.graphToPrompt(); + data['workflow'] = workflow['output'] const response = await api.fetchApi("/lam/setAppParams", { method: "POST", headers: { @@ -351,61 +364,67 @@ async function setAppParams(data) { console.error(error); } } -function add_param(w,appNode){ - let typeEl=null; - if(w.type=='number'||w.type=='slider'){ - typeEl=$el('td',[ - $el('select',{value:w.type,$:(el) =>{el.onchange=()=>{ - appNode.properties['paramList'].find(obj => obj.id === el.parentNode.parentNode.dataset.id).type=el.value - }}},[ - $el('option',{selected:w.type=='number',textContent:'数值输入',value:'number'}), - $el('option',{selected:w.type=='slider',textContent:'数值滑条',value:'slider'}), +function add_param(w, appNode) { + let typeEl = null; + if (w.type == 'number' || w.type == 'slider') { + typeEl = $el('td', [ + $el('select', { + value: w.type, $: (el) => { + el.onchange = () => { + appNode.properties['paramList'].find(obj => obj.id === el.parentNode.parentNode.dataset.id).type = el.value + } + } + }, [ + $el('option', { selected: w.type == 'number', textContent: '数值输入', value: 'number' }), + $el('option', { selected: w.type == 'slider', textContent: '数值滑条', value: 'slider' }), ]) ]) - }else{ - typeEl=$el('td',{textContent:w.type}) + } else { + typeEl = $el('td', { textContent: w.type }) } - let maskEl=null; - let maskd=appNode.properties['paramList'].find(obj => obj.id==w?.maskKey) - if(w.type=='image'){ - maskEl=$el('td',[ - $el('span',{textContent:maskd?'已关联:'+maskd.zhName:'关联遮罩',$:(el) => { - el.onclick = () => { - let thIndex=appNode.properties['paramList'].findIndex(obj => obj.id==el.parentNode.parentNode.dataset.id) - let imgs=appNode.properties['paramList'].filter(obj => obj.type === 'image'&&obj.id!=el.parentNode.parentNode.dataset.id) - let maskKey=appNode.properties['paramList'][thIndex]?.maskKey - if(imgs.length>0){ - if(!maskKey){ - appNode.properties['paramList'][thIndex]['maskKey']=imgs[0].id - el.innerHTML='已关联:'+imgs[0].zhName - }else{ - if(imgs.length==1){ - appNode.properties['paramList'][thIndex]['maskKey']=null - el.innerHTML='关联遮罩' - }else{ - let imgIndex=imgs.findIndex(obj => obj.id === maskKey) - if(imgIndex==-1||imgIndex+1>=imgs.length){ - appNode.properties['paramList'][thIndex]['maskKey']=null - el.innerHTML='关联遮罩' - }else{ - appNode.properties['paramList'][thIndex]['maskKey']=imgs[imgIndex+1].id - el.innerHTML='已关联:'+imgs[imgIndex+1].zhName + let maskEl = null; + let maskd = appNode.properties['paramList'].find(obj => obj.id == w?.maskKey) + if (w.type == 'image') { + maskEl = $el('td', [ + $el('span', { + textContent: maskd ? '已关联:' + maskd.zhName : '关联遮罩', $: (el) => { + el.onclick = () => { + let thIndex = appNode.properties['paramList'].findIndex(obj => obj.id == el.parentNode.parentNode.dataset.id) + let imgs = appNode.properties['paramList'].filter(obj => obj.type === 'image' && obj.id != el.parentNode.parentNode.dataset.id) + let maskKey = appNode.properties['paramList'][thIndex]?.maskKey + if (imgs.length > 0) { + if (!maskKey) { + appNode.properties['paramList'][thIndex]['maskKey'] = imgs[0].id + el.innerHTML = '已关联:' + imgs[0].zhName + } else { + if (imgs.length == 1) { + appNode.properties['paramList'][thIndex]['maskKey'] = null + el.innerHTML = '关联遮罩' + } else { + let imgIndex = imgs.findIndex(obj => obj.id === maskKey) + if (imgIndex == -1 || imgIndex + 1 >= imgs.length) { + appNode.properties['paramList'][thIndex]['maskKey'] = null + el.innerHTML = '关联遮罩' + } else { + appNode.properties['paramList'][thIndex]['maskKey'] = imgs[imgIndex + 1].id + el.innerHTML = '已关联:' + imgs[imgIndex + 1].zhName + } } } + } else { + el.innerHTML = '关联遮罩' + alert('请先添加遮罩图片参数') } - }else{ - el.innerHTML='关联遮罩' - alert('请先添加遮罩图片参数') + } - - }} + } }) ]) - }else{ - maskEl=$el('td') + } else { + maskEl = $el('td') } - - return $el('tr',{ + + return $el('tr', { dataset: { id: w.id, name: w.name, @@ -413,68 +432,76 @@ function add_param(w,appNode){ type: w.type, value: w.value } - },[ - $el('td',{textContent:w.name}), - $el('td',{},[ - $el('input',{name:w.name,value:w.zhName,$:(el) =>{el.onchange=()=>{ - appNode.properties['paramList'].find(obj => obj.id === el.parentNode.parentNode.dataset.id).zhName=el.value - }}}) + }, [ + $el('td', { textContent: w.name }), + $el('td', {}, [ + $el('input', { + name: w.name, value: w.zhName, $: (el) => { + el.onchange = () => { + appNode.properties['paramList'].find(obj => obj.id === el.parentNode.parentNode.dataset.id).zhName = el.value + } + } + }) ]), typeEl, maskEl, - $el('td',{},[$el('button',{textContent:'删除',$:(el) => { - el.onclick = () => { - appNode.properties['paramList'].splice(appNode.properties['paramList'].findIndex(obj => obj.id === el.parentNode.parentNode.dataset.id),1) - el.parentNode.parentNode.parentNode.removeChild(el.parentNode.parentNode) - }} + $el('td', {}, [$el('button', { + textContent: '删除', $: (el) => { + el.onclick = () => { + appNode.properties['paramList'].splice(appNode.properties['paramList'].findIndex(obj => obj.id === el.parentNode.parentNode.dataset.id), 1) + el.parentNode.parentNode.parentNode.removeChild(el.parentNode.parentNode) + } } + } )]), ]) } app.registerExtension({ name: "AppParams", async beforeRegisterNodeDef(nodeType, nodeData, app) { - var names=["AppParams"] - if (names.indexOf(nodeData.name)>=0) { + var names = ["AppParams"] + if (names.indexOf(nodeData.name) >= 0) { const onNodeCreated = nodeType.prototype.onNodeCreated; - nodeType.prototype.onNodeCreated = function() { + nodeType.prototype.onNodeCreated = function () { const r = onNodeCreated?.apply(this, arguments); this.setProperty("paramList", []) - const list = $el("table.lam_app_params_list",[ - $el('tr',[ - $el('td',{textContent:'参数名'}), - $el('td',{textContent:'中文名'}), - $el('td',{textContent:'组件类型'}), - $el('td',{textContent:'绘制遮罩'}), - $el('td',{textContent:'操作'}), + const list = $el("table.lam_app_params_list", [ + $el('tr', [ + $el('td', { textContent: '参数名' }), + $el('td', { textContent: '中文名' }), + $el('td', { textContent: '组件类型' }), + $el('td', { textContent: '绘制遮罩' }), + $el('td', { textContent: '操作' }), ]) ]); - let params=this.addDOMWidget('styles',"list",$el('div.lam_app_param_div',[$el('button',{ - textContent:'应用预览', - style:{}, - onclick:()=>{ + let params = this.addDOMWidget('styles', "list", $el('div.lam_app_param_div', [$el('button', { + textContent: '应用预览', + style: {}, + onclick: () => { let appType = this.widgets[this.widgets.findIndex(obj => obj.name === 'appType')]; openAppPage(appType.value) - }}),$el('button',{ - textContent:'参数应用', - style:{}, - onclick:()=>{ - let paramList=this.properties['paramList'] - let appName = this.widgets[this.widgets.findIndex(obj => obj.name === 'appName')]; - let appType = this.widgets[this.widgets.findIndex(obj => obj.name === 'appType')]; - let appDesc = this.widgets[this.widgets.findIndex(obj => obj.name === 'appDesc')]; - - if(!appName.value){ - alert('请输入应用名称'); - return ; - } - if(paramList.length<=0){ - alert('请至少选择一个参数'); - return ; - } - let data={appName:appName.value,appType:appType.value,appDesc:appDesc.value,paramList:paramList} - setAppParams(data) - }}),list])); + } + }), $el('button', { + textContent: '参数应用', + style: {}, + onclick: () => { + let paramList = this.properties['paramList'] + let appName = this.widgets[this.widgets.findIndex(obj => obj.name === 'appName')]; + let appType = this.widgets[this.widgets.findIndex(obj => obj.name === 'appType')]; + let appDesc = this.widgets[this.widgets.findIndex(obj => obj.name === 'appDesc')]; + + if (!appName.value) { + alert('请输入应用名称'); + return; + } + if (paramList.length <= 0) { + alert('请至少选择一个参数'); + return; + } + let data = { appName: appName.value, appType: appType.value, appDesc: appDesc.value, paramList: paramList } + setAppParams(data) + } + }), list])); this.setSize([500, 600]); return r; }; @@ -483,10 +510,10 @@ app.registerExtension({ loadedGraphNode(node, _) { if (node.type === "AppParams") { node.properties['paramList'].forEach(el => { - node.widgets[3].element.children[2].appendChild(add_param(el,node)) + node.widgets[3].element.children[2].appendChild(add_param(el, node)) }); } - }, + }, }); async function addConvertToGroupOptions() { @@ -494,9 +521,9 @@ async function addConvertToGroupOptions() { const getNodeMenuOptions = LGraphCanvas.prototype.getNodeMenuOptions; LGraphCanvas.prototype.getNodeMenuOptions = function (node) { const options = getNodeMenuOptions.apply(this, arguments); - if (!GroupNodeHandler.isGroupNode(node)&&node.type!='AppParams'&&node.widgets){ + if (!GroupNodeHandler.isGroupNode(node) && node.type != 'AppParams' && node.widgets) { let toInput = []; - let wNames=node.inputs.filter(obj => obj.widget !== undefined && obj.link === null).map(obj => obj.name); + let wNames = node.inputs.filter(obj => obj.widget !== undefined && obj.link === null).map(obj => obj.name); for (const w of node.widgets) { if (w.options?.forceInput || !wNames.includes(w.name)) { continue; @@ -506,72 +533,72 @@ async function addConvertToGroupOptions() { content: `添加 ${w.label} 到输入参数`, callback: async () => { console.log(w) - let nodes=graph.computeExecutionOrder(false) - let appNode=nodes[nodes.findIndex(obj => obj.type === 'AppParams')] - if(!appNode){ + let nodes = graph.computeExecutionOrder(false) + let appNode = nodes[nodes.findIndex(obj => obj.type === 'AppParams')] + if (!appNode) { alert('请先添加AppParams节点'); return; } let appTypeEl = appNode.widgets[appNode.widgets.findIndex(obj => obj.name === 'appType')]; - if(!w.type in type2paramType){ + if (!w.type in type2paramType) { return; } - let paramData={id:'n'+node.id+'_'+w.name,keys:[''+node.id,'inputs',w.name],name:w.name,zhName:w.label,type:w.type,default:w.value,isRequired:false} - if(w.type=='number'){ - paramData['min']=w.options.min - paramData['max']=w.options.max - paramData['step']=w.options.round - }else if(w.type=='toggle'||w.type=='boolean'||w.type=='BOOLEAN'){ - paramData['type']='switch' - paramData['onVal']=true - paramData['offVal']=false - }else if(w.type=='STRING'){ - paramData['type']='text' - }else if(w.type=='combo'){ - paramData['type']='select' - let values=w.options.values - paramData['options']={} - for(let i=0;i obj.id === paramData.id) - if(index>=0){ + let index = appNode.properties['paramList'].findIndex(obj => obj.id === paramData.id) + if (index >= 0) { return; } appNode.properties['paramList'].push(paramData) - let tr=add_param(paramData,appNode) + let tr = add_param(paramData, appNode) appNode.widgets[3].element.children[2].appendChild(tr) } }); } } const index = options.findIndex((o) => o?.content === "Outputs") + 1 || options.length - 1; - toInput.length>0&&options.splice(index + 1, null, { + toInput.length > 0 && options.splice(index + 1, null, { content: `设置应用参数`, submenu: { options: toInput @@ -581,12 +608,12 @@ async function addConvertToGroupOptions() { return options; }; - let cmGroup = new (await import("../../scripts/ui/components/buttonGroup.js")).ComfyButtonGroup( - new(await import("../../scripts/ui/components/button.js")).ComfyButton({ + let cmGroup = new (await import("../../scripts/ui/components/buttonGroup.js")).ComfyButtonGroup( + new (await import("../../scripts/ui/components/button.js")).ComfyButton({ icon: "puzzle", action: () => { - if(!manager_instance){ - manager_instance= new ManagerMenuDialog(); + if (!manager_instance) { + manager_instance = new ManagerMenuDialog(); } getAppInit() }, @@ -596,7 +623,7 @@ async function addConvertToGroupOptions() { }).element ); app.menu?.settingsGroup.element.before(cmGroup.element); - + } const id = "Lam.AppParams"; @@ -612,12 +639,10 @@ const ext = { // // Store this so we can mutate it later with group nodes // globalDefs = defs; // }, - nodeCreated(node) { - if (!GroupNodeHandler.isGroupNode(node)) { - - } - - }, + // nodeCreated(node) { + // if (!GroupNodeHandler.isGroupNode(node)) { + // } + // }, }; app.registerExtension(ext); \ No newline at end of file diff --git a/js/LamSwitch.js b/js/LamSwitch.js new file mode 100644 index 0000000..4e844e4 --- /dev/null +++ b/js/LamSwitch.js @@ -0,0 +1,67 @@ +import { app } from "/scripts/app.js"; + + +function adaptWidgetsToConnection(node) { + if (!node.outputs || node.outputs.length === 0) { + return + } + console.log("到这里==================") +} + +function setupParameterNode(nodeType) { + const onAdded = nodeType.prototype.onAdded + nodeType.prototype.onAdded = function () { + onAdded?.apply(this, arguments) + adaptWidgetsToConnection(this) + } + + const onAfterGraphConfigured = nodeType.prototype.onAfterGraphConfigured + nodeType.prototype.onAfterGraphConfigured = function () { + onAfterGraphConfigured?.apply(this, arguments) + adaptWidgetsToConnection(this) + } + + const onConnectOutput = nodeType.prototype.onConnectOutput + nodeType.prototype.onConnectOutput = function (slot, type, input, target_node, target_slot) { + if (!input.widget) { + return false + } else if (onConnectOutput) { + result = onConnectOutput.apply(this, arguments) + return result + } + return true + } + + const onConnectionsChange = nodeType.prototype.onConnectionsChange + nodeType.prototype.onConnectionsChange = function (_, index, connected) { + if (!app.configuringGraph) { + adaptWidgetsToConnection(this) + } + onConnectionsChange?.apply(this, arguments) + } +} + +const id = "Lam.Switch"; +const ext = { + name: id, + setup() { + //addConvertToGroupOptions(); + //添加按钮可以 + }, + async beforeConfigureGraph(graphData, missingNodeTypes) { + //加载配置 + }, + beforeRegisterNodeDef(nodeType /*typeof LGraphNode*/, nodeData /*ComfyObjectInfo*/, app) { + if (nodeData.name === "LamSwitchStart") { + setupParameterNode(nodeType) + } + }, + addCustomNodeDefs(defs) { + // 将其存储起来,以便稍后使用组节点对其进行修改 + }, + nodeCreated(node) { + //节点创建 + }, +}; + +app.registerExtension(ext); \ No newline at end of file diff --git a/pages/app.html b/pages/app.html index b762db4..97650b4 100644 --- a/pages/app.html +++ b/pages/app.html @@ -1,10 +1,11 @@ + {{appTitle}} - + @@ -20,15 +21,17 @@ - + + + -
-
-
-
-
历史记录
+
+
+
+
+
历史记录
-
+