diff --git a/nodes/Utils.py b/nodes/Utils.py index 39ec5940..fbd9ca42 100644 --- a/nodes/Utils.py +++ b/nodes/Utils.py @@ -434,12 +434,12 @@ class AppInfo: def INPUT_TYPES(s): return {"required": { "name": ("STRING",{"multiline": False,"default": "Mixlab-App","dynamicPrompts": False}), - "image": ("IMAGE",), "input_ids":("STRING",{"multiline": True,"default": "\n".join(["1","2","3"]),"dynamicPrompts": False}), "output_ids":("STRING",{"multiline": True,"default": "\n".join(["5","9"]),"dynamicPrompts": False}), }, "optional":{ + "LOGO": ("IMAGE",), "description":("STRING",{"multiline": True,"default": "","dynamicPrompts": False}), "version":("INT", { "default": 1, @@ -451,12 +451,13 @@ def INPUT_TYPES(s): "share_prefix":("STRING",{"multiline": False,"default": "","dynamicPrompts": False}), "link":("STRING",{"multiline": False,"default": "https://","dynamicPrompts": False}), "category":("STRING",{"multiline": False,"default": "","dynamicPrompts": False}), + "auto_save": (["enable","disable"],), } } - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("IMAGE",) + RETURN_TYPES = () + # RETURN_NAMES = ("IMAGE",) FUNCTION = "run" @@ -464,11 +465,16 @@ def INPUT_TYPES(s): OUTPUT_NODE = True INPUT_IS_LIST = True - OUTPUT_IS_LIST = (True,) + # OUTPUT_IS_LIST = (True,) - def run(self,name,image,input_ids,output_ids,description,version,share_prefix,link,category): + def run(self,name,input_ids,output_ids,image,description,version,share_prefix,link,category,auto_save): name=name[0] - im=image[0][0] + + im=None + if image: + im=image[0][0] + #TODO batch 的方式需要处理 + im=create_temp_file(im) # image [img,] img[batch,w,h,a] 列表里面是batch, input_ids=input_ids[0] @@ -478,13 +484,10 @@ def run(self,name,image,input_ids,output_ids,description,version,share_prefix,li share_prefix=share_prefix[0] link=link[0] category=category[0] - - #TODO batch 的方式需要处理 - im=create_temp_file(im) # id=get_json_hash([name,im,input_ids,output_ids,description,version]) - return {"ui": {"json": [name,im,input_ids,output_ids,description,version,share_prefix,link,category]}, "result": (image,)} + return {"ui": {"json": [name,im,input_ids,output_ids,description,version,share_prefix,link,category]}, "result": ()} diff --git a/web/javascript/app_mixlab.js b/web/javascript/app_mixlab.js index 7beeeb51..bfde8eb0 100644 --- a/web/javascript/app_mixlab.js +++ b/web/javascript/app_mixlab.js @@ -108,8 +108,7 @@ function extractInputAndOutputData (jsonData, inputIds = [], outputIds = []) { } } - if(node.type=='Color'){ - + if (node.type == 'Color') { } input[inputIds.indexOf(id)] = { @@ -126,11 +125,11 @@ function extractInputAndOutputData (jsonData, inputIds = [], outputIds = []) { output[outputIds.indexOf(id)] = { ...data[id], title: node.title, id } } - if (node.type === 'KSampler'||node.type=='SamplerCustom') { + if (node.type === 'KSampler' || node.type == 'SamplerCustom') { // seed 的类型收集 try { seed[id] = node.widgets.filter( - w => (w.name === 'seed'||w.name=='noise_seed') + w => w.name === 'seed' || w.name == 'noise_seed' )[0].linkedWidgets[0].value } catch (error) {} } @@ -188,7 +187,7 @@ function downloadJsonFile (jsonData, fileName = 'mix_app.json') { }, 0) } -async function save (json, download = false) { +async function save (json, download = false, showInfo = true) { const name = json[0], version = json[5], share_prefix = json[6], //用于分享的功能扩展 @@ -237,22 +236,53 @@ async function save (json, download = false) { if (download) { await downloadJsonFile(data, data.app.filename) } - let open = window.confirm( - `You can now access the standalone application on a new page!\n${getUrl()}/mixlab/app?filename=${encodeURIComponent( - data.app.filename - )}&category=${encodeURIComponent(data.app.category)}` - ) - if (open) - window.open( - `${getUrl()}/mixlab/app?filename=${encodeURIComponent( + + if (showInfo) { + let open = window.confirm( + `You can now access the standalone application on a new page!\n${getUrl()}/mixlab/app?filename=${encodeURIComponent( data.app.filename )}&category=${encodeURIComponent(data.app.category)}` ) + if (open) + window.open( + `${getUrl()}/mixlab/app?filename=${encodeURIComponent( + data.app.filename + )}&category=${encodeURIComponent(data.app.category)}` + ) + } } catch (error) { console.log('###error', error) } } +function getInputsAndOutputs () { + const inputs = + `LoadImage CLIPTextEncode PromptSlide TextInput_ Color FloatSlider IntNumber CheckpointLoaderSimple LoraLoader`.split( + ' ' + ), + outputs = `PreviewImage SaveImage ShowTextForGPT VHS_VideoCombine`.split( + ' ' + ) + + let inputsId = [], + outputsId = [] + + for (let node of app.graph._nodes) { + if (inputs.includes(node.type)) { + inputsId.push(node.id) + } + + if (outputs.includes(node.type)) { + outputsId.push(node.id) + } + } + + return { + input: inputsId, + output: outputsId + } +} + app.registerExtension({ name: 'Mixlab.utils.AppInfo', async beforeRegisterNodeDef (nodeType, nodeData, app) { @@ -260,7 +290,16 @@ app.registerExtension({ const orig_nodeCreated = nodeType.prototype.onNodeCreated nodeType.prototype.onNodeCreated = function () { orig_nodeCreated?.apply(this, arguments) - console.log('#orig_nodeCreated', this) + // console.log('#orig_nodeCreated', this) + + // 自动计算workflow里哪些节点支持 + let input_ids = this.widgets.filter(w => w.name == 'input_ids')[0], + output_ids = this.widgets.filter(w => w.name == 'output_ids')[0] + + const { input, output } = getInputsAndOutputs() + input_ids.value = input.join('\n') + output_ids.value = output.join('\n') + const widget = { type: 'div', name: 'AppInfoRun', @@ -339,6 +378,12 @@ app.registerExtension({ console.log(message.json) window._mixlab_app_json = message.json try { + let a = this.widgets.filter(w => w.name === 'AppInfoRun')[0] + if (a) { + if (!a.value) a.value = 0 + a.value += 1 + } + const div = this.widgets.filter(w => w.div)[0].div Array.from( div.querySelectorAll('button'), @@ -347,5 +392,31 @@ app.registerExtension({ } catch (error) {} } } + }, + async loadedGraphNode (node, app) { + if (node.type === 'AppInfo') { + let auto_save = node.widgets.filter(w => w.name == 'auto_save')[0] + if (auto_save) { + if (!['enable', 'disable'].includes(auto_save.value)) { + auto_save.value = 'enable' + } + } + } + } +}) + +api.addEventListener('executed', async ({ detail }) => { + console.log('#executed', detail) + const { output } = getInputsAndOutputs() + if (output.includes(parseInt(detail.node))) { + let appinfo = app.graph.findNodesByType('AppInfo')[0] + if (appinfo) { + let auto_save = appinfo.widgets.filter(w => w.name == 'auto_save')[0] + if (auto_save?.value === 'enable') { + // 自动保存 + console.log('auto_save') + if (window._mixlab_app_json) save(window._mixlab_app_json,false,false) + } + } } })