|
|
@ -5,6 +5,11 @@ const CONVERTED_TYPE = "converted-widget"; |
|
|
|
const VALID_TYPES = ["STRING", "combo", "number", "BOOLEAN"]; |
|
|
|
const VALID_TYPES = ["STRING", "combo", "number", "BOOLEAN"]; |
|
|
|
const CONFIG = Symbol(); |
|
|
|
const CONFIG = Symbol(); |
|
|
|
const GET_CONFIG = Symbol(); |
|
|
|
const GET_CONFIG = Symbol(); |
|
|
|
|
|
|
|
const TARGET = Symbol(); // Used for reroutes to specify the real target widget
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function getWidgetConfig(slot) { |
|
|
|
|
|
|
|
return slot.widget[CONFIG] ?? slot.widget[GET_CONFIG](); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getConfig(widgetName) { |
|
|
|
function getConfig(widgetName) { |
|
|
|
const { nodeData } = this.constructor; |
|
|
|
const { nodeData } = this.constructor; |
|
|
@ -100,7 +105,6 @@ function getWidgetType(config) { |
|
|
|
return { type }; |
|
|
|
return { type }; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function isValidCombo(combo, obj) { |
|
|
|
function isValidCombo(combo, obj) { |
|
|
|
// New input isnt a combo
|
|
|
|
// New input isnt a combo
|
|
|
|
if (!(obj instanceof Array)) { |
|
|
|
if (!(obj instanceof Array)) { |
|
|
@ -121,6 +125,31 @@ function isValidCombo(combo, obj) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function setWidgetConfig(slot, config, target) { |
|
|
|
|
|
|
|
if (!slot.widget) return; |
|
|
|
|
|
|
|
if (config) { |
|
|
|
|
|
|
|
slot.widget[GET_CONFIG] = () => config; |
|
|
|
|
|
|
|
slot.widget[TARGET] = target; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
delete slot.widget; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (slot.link) { |
|
|
|
|
|
|
|
const link = app.graph.links[slot.link]; |
|
|
|
|
|
|
|
if (link) { |
|
|
|
|
|
|
|
const originNode = app.graph.getNodeById(link.origin_id); |
|
|
|
|
|
|
|
if (originNode.type === "PrimitiveNode") { |
|
|
|
|
|
|
|
if (config) { |
|
|
|
|
|
|
|
originNode.recreateWidget(); |
|
|
|
|
|
|
|
} else if(!app.configuringGraph) { |
|
|
|
|
|
|
|
originNode.disconnectOutput(0); |
|
|
|
|
|
|
|
originNode.onLastDisconnect(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function mergeIfValid(output, config2, forceUpdate, recreateWidget, config1) { |
|
|
|
export function mergeIfValid(output, config2, forceUpdate, recreateWidget, config1) { |
|
|
|
if (!config1) { |
|
|
|
if (!config1) { |
|
|
|
config1 = output.widget[CONFIG] ?? output.widget[GET_CONFIG](); |
|
|
|
config1 = output.widget[CONFIG] ?? output.widget[GET_CONFIG](); |
|
|
@ -434,14 +463,20 @@ app.registerExtension({ |
|
|
|
for (const linkInfo of links) { |
|
|
|
for (const linkInfo of links) { |
|
|
|
const node = this.graph.getNodeById(linkInfo.target_id); |
|
|
|
const node = this.graph.getNodeById(linkInfo.target_id); |
|
|
|
const input = node.inputs[linkInfo.target_slot]; |
|
|
|
const input = node.inputs[linkInfo.target_slot]; |
|
|
|
const widgetName = input.widget.name; |
|
|
|
let widget; |
|
|
|
if (widgetName) { |
|
|
|
if (input.widget[TARGET]) { |
|
|
|
const widget = node.widgets.find((w) => w.name === widgetName); |
|
|
|
widget = input.widget[TARGET]; |
|
|
|
if (widget) { |
|
|
|
} else { |
|
|
|
widget.value = this.widgets[0].value; |
|
|
|
const widgetName = input.widget.name; |
|
|
|
if (widget.callback) { |
|
|
|
if (widgetName) { |
|
|
|
widget.callback(widget.value, app.canvas, node, app.canvas.graph_mouse, {}); |
|
|
|
widget = node.widgets.find((w) => w.name === widgetName); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (widget) { |
|
|
|
|
|
|
|
widget.value = this.widgets[0].value; |
|
|
|
|
|
|
|
if (widget.callback) { |
|
|
|
|
|
|
|
widget.callback(widget.value, app.canvas, node, app.canvas.graph_mouse, {}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -494,14 +529,13 @@ app.registerExtension({ |
|
|
|
this.#mergeWidgetConfig(); |
|
|
|
this.#mergeWidgetConfig(); |
|
|
|
|
|
|
|
|
|
|
|
if (!links?.length) { |
|
|
|
if (!links?.length) { |
|
|
|
this.#onLastDisconnect(); |
|
|
|
this.onLastDisconnect(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onConnectOutput(slot, type, input, target_node, target_slot) { |
|
|
|
onConnectOutput(slot, type, input, target_node, target_slot) { |
|
|
|
// Fires before the link is made allowing us to reject it if it isn't valid
|
|
|
|
// Fires before the link is made allowing us to reject it if it isn't valid
|
|
|
|
|
|
|
|
|
|
|
|
// No widget, we cant connect
|
|
|
|
// No widget, we cant connect
|
|
|
|
if (!input.widget) { |
|
|
|
if (!input.widget) { |
|
|
|
if (!(input.type in ComfyWidgets)) return false; |
|
|
|
if (!(input.type in ComfyWidgets)) return false; |
|
|
@ -519,6 +553,10 @@ app.registerExtension({ |
|
|
|
|
|
|
|
|
|
|
|
#onFirstConnection(recreating) { |
|
|
|
#onFirstConnection(recreating) { |
|
|
|
// First connection can fire before the graph is ready on initial load so random things can be missing
|
|
|
|
// First connection can fire before the graph is ready on initial load so random things can be missing
|
|
|
|
|
|
|
|
if (!this.outputs[0].links) { |
|
|
|
|
|
|
|
this.onLastDisconnect(); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
const linkId = this.outputs[0].links[0]; |
|
|
|
const linkId = this.outputs[0].links[0]; |
|
|
|
const link = this.graph.links[linkId]; |
|
|
|
const link = this.graph.links[linkId]; |
|
|
|
if (!link) return; |
|
|
|
if (!link) return; |
|
|
@ -546,10 +584,10 @@ app.registerExtension({ |
|
|
|
this.outputs[0].name = type; |
|
|
|
this.outputs[0].name = type; |
|
|
|
this.outputs[0].widget = widget; |
|
|
|
this.outputs[0].widget = widget; |
|
|
|
|
|
|
|
|
|
|
|
this.#createWidget(widget[CONFIG] ?? config, theirNode, widget.name, recreating); |
|
|
|
this.#createWidget(widget[CONFIG] ?? config, theirNode, widget.name, recreating, widget[TARGET]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#createWidget(inputData, node, widgetName, recreating) { |
|
|
|
#createWidget(inputData, node, widgetName, recreating, targetWidget) { |
|
|
|
let type = inputData[0]; |
|
|
|
let type = inputData[0]; |
|
|
|
|
|
|
|
|
|
|
|
if (type instanceof Array) { |
|
|
|
if (type instanceof Array) { |
|
|
@ -563,7 +601,9 @@ app.registerExtension({ |
|
|
|
widget = this.addWidget(type, "value", null, () => {}, {}); |
|
|
|
widget = this.addWidget(type, "value", null, () => {}, {}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (node?.widgets && widget) { |
|
|
|
if (targetWidget) { |
|
|
|
|
|
|
|
widget.value = targetWidget.value; |
|
|
|
|
|
|
|
} else if (node?.widgets && widget) { |
|
|
|
const theirWidget = node.widgets.find((w) => w.name === widgetName); |
|
|
|
const theirWidget = node.widgets.find((w) => w.name === widgetName); |
|
|
|
if (theirWidget) { |
|
|
|
if (theirWidget) { |
|
|
|
widget.value = theirWidget.value; |
|
|
|
widget.value = theirWidget.value; |
|
|
@ -577,7 +617,7 @@ app.registerExtension({ |
|
|
|
} |
|
|
|
} |
|
|
|
addValueControlWidgets(this, widget, control_value, undefined, inputData); |
|
|
|
addValueControlWidgets(this, widget, control_value, undefined, inputData); |
|
|
|
let filter = this.widgets_values?.[2]; |
|
|
|
let filter = this.widgets_values?.[2]; |
|
|
|
if(filter && this.widgets.length === 3) { |
|
|
|
if (filter && this.widgets.length === 3) { |
|
|
|
this.widgets[2].value = filter; |
|
|
|
this.widgets[2].value = filter; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -610,12 +650,14 @@ app.registerExtension({ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#recreateWidget() { |
|
|
|
recreateWidget() { |
|
|
|
const values = this.widgets.map((w) => w.value); |
|
|
|
const values = this.widgets?.map((w) => w.value); |
|
|
|
this.#removeWidgets(); |
|
|
|
this.#removeWidgets(); |
|
|
|
this.#onFirstConnection(true); |
|
|
|
this.#onFirstConnection(true); |
|
|
|
for (let i = 0; i < this.widgets?.length; i++) this.widgets[i].value = values[i]; |
|
|
|
if (values?.length) { |
|
|
|
return this.widgets[0]; |
|
|
|
for (let i = 0; i < this.widgets?.length; i++) this.widgets[i].value = values[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return this.widgets?.[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#mergeWidgetConfig() { |
|
|
|
#mergeWidgetConfig() { |
|
|
@ -631,7 +673,7 @@ app.registerExtension({ |
|
|
|
if (links?.length < 2 && hasConfig) { |
|
|
|
if (links?.length < 2 && hasConfig) { |
|
|
|
// Copy the widget options from the source
|
|
|
|
// Copy the widget options from the source
|
|
|
|
if (links.length) { |
|
|
|
if (links.length) { |
|
|
|
this.#recreateWidget(); |
|
|
|
this.recreateWidget(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return; |
|
|
|
return; |
|
|
@ -657,7 +699,7 @@ app.registerExtension({ |
|
|
|
// Only allow connections where the configs match
|
|
|
|
// Only allow connections where the configs match
|
|
|
|
const output = this.outputs[0]; |
|
|
|
const output = this.outputs[0]; |
|
|
|
const config2 = input.widget[GET_CONFIG](); |
|
|
|
const config2 = input.widget[GET_CONFIG](); |
|
|
|
return !!mergeIfValid.call(this, output, config2, forceUpdate, this.#recreateWidget); |
|
|
|
return !!mergeIfValid.call(this, output, config2, forceUpdate, this.recreateWidget); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#removeWidgets() { |
|
|
|
#removeWidgets() { |
|
|
@ -672,7 +714,7 @@ app.registerExtension({ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#onLastDisconnect() { |
|
|
|
onLastDisconnect() { |
|
|
|
// We cant remove + re-add the output here as if you drag a link over the same link
|
|
|
|
// We cant remove + re-add the output here as if you drag a link over the same link
|
|
|
|
// it removes, then re-adds, causing it to break
|
|
|
|
// it removes, then re-adds, causing it to break
|
|
|
|
this.outputs[0].type = "*"; |
|
|
|
this.outputs[0].type = "*"; |
|
|
|