Spaces:
Configuration error
Configuration error
| import {app} from "../../../../scripts/app.js"; | |
| import {api} from "../../../../scripts/api.js"; | |
| import {$el} from "../../../../scripts/ui.js"; | |
| const propmts = ["easy wildcards", "easy positive", "easy negative", "easy stylesSelector", "easy promptConcat", "easy promptReplace"] | |
| const loaders = ["easy a1111Loader", "easy comfyLoader", "easy fullLoader", "easy svdLoader", "easy cascadeLoader", "easy sv3dLoader"] | |
| const preSamplingNodes = ["easy preSampling", "easy preSamplingAdvanced", "easy preSamplingNoiseIn", "easy preSamplingCustom", "easy preSamplingDynamicCFG","easy preSamplingSdTurbo", "easy preSamplingLayerDiffusion"] | |
| const kSampler = ["easy kSampler", "easy kSamplerTiled","easy kSamplerInpainting", "easy kSamplerDownscaleUnet", "easy kSamplerSDTurbo"] | |
| const controlNetNodes = ["easy controlnetLoader", "easy controlnetLoaderADV"] | |
| const instantIDNodes = ["easy instantIDApply", "easy instantIDApplyADV"] | |
| const ipadapterNodes = ["easy ipadapterApply", "easy ipadapterApplyADV" , "easy ipadapterStyleComposition"] | |
| const pipeNodes = ['easy pipeIn','easy pipeOut', 'easy pipeEdit'] | |
| const xyNodes = ['easy XYPlot', 'easy XYPlotAdvanced'] | |
| const extraNodes = ['easy setNode'] | |
| const modelNormalNodes = [...["Reroute"],...['RescaleCFG','LoraLoaderModelOnly','LoraLoader','FreeU','FreeU_v2'],...ipadapterNodes,...extraNodes] | |
| const suggestions = { | |
| // prompt | |
| "easy seed":{ | |
| "from":{ | |
| "INT": [...["Reroute"],...preSamplingNodes,...['easy fullkSampler']] | |
| } | |
| }, | |
| "easy positive":{ | |
| "from":{ | |
| "STRING": [...["Reroute"],...propmts] | |
| } | |
| }, | |
| "easy negative":{ | |
| "from":{ | |
| "STRING": [...["Reroute"],...propmts] | |
| } | |
| }, | |
| "easy wildcards":{ | |
| "from":{ | |
| "STRING": [...["Reroute","easy showAnything"],...propmts,] | |
| } | |
| }, | |
| "easy stylesSelector":{ | |
| "from":{ | |
| "STRING": [...["Reroute","easy showAnything"],...propmts,] | |
| } | |
| }, | |
| "easy promptConcat":{ | |
| "from":{ | |
| "STRING": [...["Reroute","easy showAnything"],...propmts,] | |
| } | |
| }, | |
| "easy promptReplace":{ | |
| "from":{ | |
| "STRING": [...["Reroute","easy showAnything"],...propmts,] | |
| } | |
| }, | |
| // sd相关 | |
| "easy fullLoader": { | |
| "from":{ | |
| "PIPE_LINE": [...["Reroute"],...preSamplingNodes,...['easy fullkSampler'],...pipeNodes,...extraNodes], | |
| "MODEL":modelNormalNodes | |
| }, | |
| "to":{ | |
| "STRING": [...["Reroute"],...propmts] | |
| } | |
| }, | |
| "easy a1111Loader": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...preSamplingNodes, ...controlNetNodes, ...instantIDNodes, ...pipeNodes, ...extraNodes], | |
| "MODEL": modelNormalNodes | |
| }, | |
| "to":{ | |
| "STRING": [...["Reroute"],...propmts] | |
| } | |
| }, | |
| "easy comfyLoader": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...preSamplingNodes, ...controlNetNodes, ...instantIDNodes, ...pipeNodes, ...extraNodes], | |
| "MODEL": modelNormalNodes | |
| }, | |
| "to":{ | |
| "STRING": [...["Reroute"],...propmts] | |
| } | |
| }, | |
| "easy svdLoader":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...["easy preSampling", "easy preSamplingAdvanced", "easy preSamplingDynamicCFG"], ...pipeNodes, ...extraNodes], | |
| "MODEL": modelNormalNodes | |
| }, | |
| "to":{ | |
| "STRING": [...["Reroute"],...propmts] | |
| } | |
| }, | |
| "easy zero123Loader":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...["easy preSampling", "easy preSamplingAdvanced", "easy preSamplingDynamicCFG"], ...pipeNodes, ...extraNodes], | |
| "MODEL": modelNormalNodes | |
| }, | |
| "to":{ | |
| "STRING": [...["Reroute"],...propmts] | |
| } | |
| }, | |
| "easy sv3dLoader":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...["easy preSampling", "easy preSamplingAdvanced", "easy preSamplingDynamicCFG"], ...pipeNodes, ...extraNodes], | |
| "MODEL": modelNormalNodes | |
| }, | |
| "to":{ | |
| "STRING": [...["Reroute"],...propmts] | |
| } | |
| }, | |
| "easy preSampling": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...kSampler, ...pipeNodes, ...controlNetNodes, ...xyNodes, ...extraNodes] | |
| }, | |
| }, | |
| "easy preSamplingAdvanced": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...kSampler, ...pipeNodes, ...controlNetNodes, ...xyNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy preSamplingDynamicCFG": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...kSampler, ...pipeNodes, ...controlNetNodes, ...xyNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy preSamplingCustom": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...kSampler, ...pipeNodes, ...controlNetNodes, ...xyNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy preSamplingLayerDiffusion": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute", "easy kSamplerLayerDiffusion"], ...kSampler, ...pipeNodes, ...controlNetNodes, ...xyNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy preSamplingNoiseIn": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...kSampler, ...pipeNodes, ...controlNetNodes, ...xyNodes, ...extraNodes] | |
| } | |
| }, | |
| // ksampler | |
| "easy fullkSampler": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...pipeNodes.reverse(), ...['easy preDetailerFix', 'easy preMaskDetailerFix'], ...preSamplingNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy kSampler": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...pipeNodes.reverse(), ...['easy preDetailerFix', 'easy preMaskDetailerFix', 'easy hiresFix'], ...preSamplingNodes, ...extraNodes], | |
| } | |
| }, | |
| // cn | |
| "easy controlnetLoader": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...preSamplingNodes, ...controlNetNodes, ...instantIDNodes, ...pipeNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy controlnetLoaderADV":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...preSamplingNodes, ...controlNetNodes, ...instantIDNodes, ...pipeNodes, ...extraNodes] | |
| } | |
| }, | |
| // instant | |
| "easy instantIDApply": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...preSamplingNodes, ...controlNetNodes, ...instantIDNodes, ...pipeNodes, ...extraNodes], | |
| "MODEL": modelNormalNodes | |
| }, | |
| "to":{ | |
| "COMBO": [...["Reroute", "easy promptLine"]] | |
| } | |
| }, | |
| "easy instantIDApplyADV":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...preSamplingNodes, ...controlNetNodes, ...instantIDNodes, ...pipeNodes, ...extraNodes], | |
| "MODEL": modelNormalNodes | |
| }, | |
| "to":{ | |
| "COMBO": [...["Reroute", "easy promptLine"]] | |
| } | |
| }, | |
| "easy ipadapterApply":{ | |
| "to":{ | |
| "COMBO": [...["Reroute", "easy promptLine"]] | |
| } | |
| }, | |
| "easy ipadapterApplyADV":{ | |
| "to":{ | |
| "STRING": [...["Reroute", "easy sliderControl"], ...propmts], | |
| "COMBO": [...["Reroute", "easy promptLine"]] | |
| } | |
| }, | |
| "easy ipadapterStyleComposition":{ | |
| "to":{ | |
| "COMBO": [...["Reroute", "easy promptLine"]] | |
| } | |
| }, | |
| // fix | |
| "easy preDetailerFix":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute", "easy detailerFix"], ...pipeNodes, ...extraNodes] | |
| }, | |
| "to":{ | |
| "PIPE_LINE": [...["Reroute", "easy ultralyticsDetectorPipe", "easy samLoaderPipe", "easy kSampler", "easy fullkSampler"]] | |
| } | |
| }, | |
| "easy preMaskDetailerFix":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute", "easy detailerFix"], ...pipeNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy samLoaderPipe": { | |
| "from":{ | |
| "PIPE_LINE": [...["Reroute", "easy preDetailerFix"], ...pipeNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy ultralyticsDetectorPipe": { | |
| "from":{ | |
| "PIPE_LINE": [...["Reroute", "easy preDetailerFix"], ...pipeNodes, ...extraNodes] | |
| } | |
| }, | |
| // cascade相关 | |
| "easy cascadeLoader":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...["easy fullCascadeKSampler", 'easy preSamplingCascade'], ...controlNetNodes, ...pipeNodes, ...extraNodes], | |
| "MODEL": modelNormalNodes.filter(cate => !ipadapterNodes.includes(cate)) | |
| } | |
| }, | |
| "easy fullCascadeKSampler":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...["easy preSampling", "easy preSamplingAdvanced"], ...pipeNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy preSamplingCascade":{ | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...["easy cascadeKSampler",], ...pipeNodes, ...extraNodes] | |
| } | |
| }, | |
| "easy cascadeKSampler": { | |
| "from": { | |
| "PIPE_LINE": [...["Reroute"], ...["easy preSampling", "easy preSamplingAdvanced"], ...pipeNodes, ...extraNodes] | |
| } | |
| }, | |
| } | |
| app.registerExtension({ | |
| name: "comfy.easyuse.suggestions", | |
| async setup(app) { | |
| LGraphCanvas.prototype.createDefaultNodeForSlot = function(optPass) { // addNodeMenu for connection | |
| var optPass = optPass || {}; | |
| var opts = Object.assign({ nodeFrom: null // input | |
| ,slotFrom: null // input | |
| ,nodeTo: null // output | |
| ,slotTo: null // output | |
| ,position: [] // pass the event coords | |
| ,nodeType: null // choose a nodetype to add, AUTO to set at first good | |
| ,posAdd:[0,0] // adjust x,y | |
| ,posSizeFix:[0,0] // alpha, adjust the position x,y based on the new node size w,h | |
| } | |
| ,optPass | |
| ); | |
| var that = this; | |
| var isFrom = opts.nodeFrom && opts.slotFrom!==null; | |
| var isTo = !isFrom && opts.nodeTo && opts.slotTo!==null; | |
| if (!isFrom && !isTo){ | |
| console.warn("No data passed to createDefaultNodeForSlot "+opts.nodeFrom+" "+opts.slotFrom+" "+opts.nodeTo+" "+opts.slotTo); | |
| return false; | |
| } | |
| if (!opts.nodeType){ | |
| console.warn("No type to createDefaultNodeForSlot"); | |
| return false; | |
| } | |
| var nodeX = isFrom ? opts.nodeFrom : opts.nodeTo; | |
| var slotX = isFrom ? opts.slotFrom : opts.slotTo; | |
| var nodeType = nodeX.type | |
| var iSlotConn = false; | |
| switch (typeof slotX){ | |
| case "string": | |
| iSlotConn = isFrom ? nodeX.findOutputSlot(slotX,false) : nodeX.findInputSlot(slotX,false); | |
| slotX = isFrom ? nodeX.outputs[slotX] : nodeX.inputs[slotX]; | |
| break; | |
| case "object": | |
| // ok slotX | |
| iSlotConn = isFrom ? nodeX.findOutputSlot(slotX.name) : nodeX.findInputSlot(slotX.name); | |
| break; | |
| case "number": | |
| iSlotConn = slotX; | |
| slotX = isFrom ? nodeX.outputs[slotX] : nodeX.inputs[slotX]; | |
| break; | |
| case "undefined": | |
| default: | |
| // bad ? | |
| //iSlotConn = 0; | |
| console.warn("Cant get slot information "+slotX); | |
| return false; | |
| } | |
| if (slotX===false || iSlotConn===false){ | |
| console.warn("createDefaultNodeForSlot bad slotX "+slotX+" "+iSlotConn); | |
| } | |
| // check for defaults nodes for this slottype | |
| var fromSlotType = slotX.type==LiteGraph.EVENT?"_event_":slotX.type; | |
| var slotTypesDefault = isFrom ? LiteGraph.slot_types_default_out : LiteGraph.slot_types_default_in; | |
| if(slotTypesDefault && slotTypesDefault[fromSlotType]){ | |
| if (slotX.link !== null) { | |
| // is connected | |
| }else{ | |
| // is not not connected | |
| } | |
| let nodeNewType = false; | |
| const fromOrTo = isFrom ? 'from' : 'to' | |
| if(suggestions[nodeType] && suggestions[nodeType][fromOrTo] && suggestions[nodeType][fromOrTo][fromSlotType]?.length>0){ | |
| for(var typeX in suggestions[nodeType][fromOrTo][fromSlotType]){ | |
| if (opts.nodeType == suggestions[nodeType][fromOrTo][fromSlotType][typeX] || opts.nodeType == "AUTO") { | |
| nodeNewType = suggestions[nodeType][fromOrTo][fromSlotType][typeX]; | |
| break | |
| } | |
| } | |
| } | |
| else if(typeof slotTypesDefault[fromSlotType] == "object" || typeof slotTypesDefault[fromSlotType] == "array"){ | |
| for(var typeX in slotTypesDefault[fromSlotType]){ | |
| if (opts.nodeType == slotTypesDefault[fromSlotType][typeX] || opts.nodeType == "AUTO"){ | |
| nodeNewType = slotTypesDefault[fromSlotType][typeX]; | |
| // console.log("opts.nodeType == slotTypesDefault[fromSlotType][typeX] :: "+opts.nodeType); | |
| break; // -------- | |
| } | |
| } | |
| }else{ | |
| if (opts.nodeType == slotTypesDefault[fromSlotType] || opts.nodeType == "AUTO") nodeNewType = slotTypesDefault[fromSlotType]; | |
| } | |
| if (nodeNewType) { | |
| var nodeNewOpts = false; | |
| if (typeof nodeNewType == "object" && nodeNewType.node){ | |
| nodeNewOpts = nodeNewType; | |
| nodeNewType = nodeNewType.node; | |
| } | |
| //that.graph.beforeChange(); | |
| var newNode = LiteGraph.createNode(nodeNewType); | |
| if(newNode){ | |
| // if is object pass options | |
| if (nodeNewOpts){ | |
| if (nodeNewOpts.properties) { | |
| for (var i in nodeNewOpts.properties) { | |
| newNode.addProperty( i, nodeNewOpts.properties[i] ); | |
| } | |
| } | |
| if (nodeNewOpts.inputs) { | |
| newNode.inputs = []; | |
| for (var i in nodeNewOpts.inputs) { | |
| newNode.addOutput( | |
| nodeNewOpts.inputs[i][0], | |
| nodeNewOpts.inputs[i][1] | |
| ); | |
| } | |
| } | |
| if (nodeNewOpts.outputs) { | |
| newNode.outputs = []; | |
| for (var i in nodeNewOpts.outputs) { | |
| newNode.addOutput( | |
| nodeNewOpts.outputs[i][0], | |
| nodeNewOpts.outputs[i][1] | |
| ); | |
| } | |
| } | |
| if (nodeNewOpts.title) { | |
| newNode.title = nodeNewOpts.title; | |
| } | |
| if (nodeNewOpts.json) { | |
| newNode.configure(nodeNewOpts.json); | |
| } | |
| } | |
| // add the node | |
| that.graph.add(newNode); | |
| newNode.pos = [ opts.position[0]+opts.posAdd[0]+(opts.posSizeFix[0]?opts.posSizeFix[0]*newNode.size[0]:0) | |
| ,opts.position[1]+opts.posAdd[1]+(opts.posSizeFix[1]?opts.posSizeFix[1]*newNode.size[1]:0)]; //that.last_click_position; //[e.canvasX+30, e.canvasX+5];*/ | |
| //that.graph.afterChange(); | |
| // connect the two! | |
| if (isFrom){ | |
| opts.nodeFrom.connectByType( iSlotConn, newNode, fromSlotType ); | |
| }else{ | |
| opts.nodeTo.connectByTypeOutput( iSlotConn, newNode, fromSlotType ); | |
| } | |
| // if connecting in between | |
| if (isFrom && isTo){ | |
| // TODO | |
| } | |
| return true; | |
| }else{ | |
| console.log("failed creating "+nodeNewType); | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| LGraphCanvas.prototype.showConnectionMenu = function(optPass) { // addNodeMenu for connection | |
| var optPass = optPass || {}; | |
| var opts = Object.assign({ nodeFrom: null // input | |
| ,slotFrom: null // input | |
| ,nodeTo: null // output | |
| ,slotTo: null // output | |
| ,e: null | |
| } | |
| ,optPass | |
| ); | |
| var that = this; | |
| var isFrom = opts.nodeFrom && opts.slotFrom; | |
| var isTo = !isFrom && opts.nodeTo && opts.slotTo; | |
| if (!isFrom && !isTo){ | |
| console.warn("No data passed to showConnectionMenu"); | |
| return false; | |
| } | |
| var nodeX = isFrom ? opts.nodeFrom : opts.nodeTo; | |
| var slotX = isFrom ? opts.slotFrom : opts.slotTo; | |
| var iSlotConn = false; | |
| switch (typeof slotX){ | |
| case "string": | |
| iSlotConn = isFrom ? nodeX.findOutputSlot(slotX,false) : nodeX.findInputSlot(slotX,false); | |
| slotX = isFrom ? nodeX.outputs[slotX] : nodeX.inputs[slotX]; | |
| break; | |
| case "object": | |
| // ok slotX | |
| iSlotConn = isFrom ? nodeX.findOutputSlot(slotX.name) : nodeX.findInputSlot(slotX.name); | |
| break; | |
| case "number": | |
| iSlotConn = slotX; | |
| slotX = isFrom ? nodeX.outputs[slotX] : nodeX.inputs[slotX]; | |
| break; | |
| default: | |
| // bad ? | |
| //iSlotConn = 0; | |
| console.warn("Cant get slot information "+slotX); | |
| return false; | |
| } | |
| var options = ["Add Node",null]; | |
| if (that.allow_searchbox){ | |
| options.push("Search"); | |
| options.push(null); | |
| } | |
| // get defaults nodes for this slottype | |
| var fromSlotType = slotX.type==LiteGraph.EVENT?"_event_":slotX.type; | |
| var slotTypesDefault = isFrom ? LiteGraph.slot_types_default_out : LiteGraph.slot_types_default_in; | |
| var nodeType = nodeX.type | |
| if(slotTypesDefault && slotTypesDefault[fromSlotType]){ | |
| const fromOrTo = isFrom ? 'from' : 'to' | |
| if(suggestions[nodeType] && suggestions[nodeType][fromOrTo] && suggestions[nodeType][fromOrTo][fromSlotType]?.length>0){ | |
| for(var typeX in suggestions[nodeType][fromOrTo][fromSlotType]){ | |
| options.push(suggestions[nodeType][fromOrTo][fromSlotType][typeX]); | |
| } | |
| } | |
| else if(typeof slotTypesDefault[fromSlotType] == "object" || typeof slotTypesDefault[fromSlotType] == "array"){ | |
| for(var typeX in slotTypesDefault[fromSlotType]){ | |
| options.push(slotTypesDefault[fromSlotType][typeX]); | |
| } | |
| }else{ | |
| options.push(slotTypesDefault[fromSlotType]); | |
| } | |
| } | |
| // build menu | |
| var menu = new LiteGraph.ContextMenu(options, { | |
| event: opts.e, | |
| title: (slotX && slotX.name!="" ? (slotX.name + (fromSlotType?" | ":"")) : "")+(slotX && fromSlotType ? fromSlotType : ""), | |
| callback: inner_clicked | |
| }); | |
| // callback | |
| function inner_clicked(v,options,e) { | |
| //console.log("Process showConnectionMenu selection"); | |
| switch (v) { | |
| case "Add Node": | |
| LGraphCanvas.onMenuAdd(null, null, e, menu, function(node){ | |
| if (isFrom){ | |
| opts.nodeFrom.connectByType( iSlotConn, node, fromSlotType ); | |
| }else{ | |
| opts.nodeTo.connectByTypeOutput( iSlotConn, node, fromSlotType ); | |
| } | |
| }); | |
| break; | |
| case "Search": | |
| if(isFrom){ | |
| that.showSearchBox(e,{node_from: opts.nodeFrom, slot_from: slotX, type_filter_in: fromSlotType}); | |
| }else{ | |
| that.showSearchBox(e,{node_to: opts.nodeTo, slot_from: slotX, type_filter_out: fromSlotType}); | |
| } | |
| break; | |
| default: | |
| // check for defaults nodes for this slottype | |
| var nodeCreated = that.createDefaultNodeForSlot(Object.assign(opts,{ position: [opts.e.canvasX, opts.e.canvasY] | |
| ,nodeType: v | |
| })); | |
| if (nodeCreated){ | |
| // new node created | |
| //console.log("node "+v+" created") | |
| }else{ | |
| // failed or v is not in defaults | |
| } | |
| break; | |
| } | |
| } | |
| return false; | |
| }; | |
| } | |
| }) |