3v324v23's picture
lfs
1e3b872
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
import { ComfyDialog, $el } from "../../scripts/ui.js";
export function rebootAPI() {
if (confirm("Are you sure you'd like to reboot the server?")) {
try {
api.fetchApi("/ttN/reboot");
}
catch(exception) {
console.log("Failed to reboot: " + exception);
}
return true;
}
return false;
}
export function wait(ms = 16, value) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(value);
}, ms);
});
}
const CONVERTED_TYPE = "converted-widget";
const GET_CONFIG = Symbol();
export function getConfig(widgetName, node) {
const { nodeData } = node.constructor;
return nodeData?.input?.required[widgetName] ?? nodeData?.input?.optional?.[widgetName];
}
export function hideWidget(node, widget, suffix = "") {
widget.origType = widget.type;
widget.origComputeSize = widget.computeSize;
widget.origSerializeValue = widget.serializeValue;
widget.computeSize = () => [0, -4]; // -4 is due to the gap litegraph adds between widgets automatically
widget.type = CONVERTED_TYPE + suffix;
widget.serializeValue = () => {
// Prevent serializing the widget if we have no input linked
if (!node.inputs) {
return undefined;
}
let node_input = node.inputs.find((i) => i.widget?.name === widget.name);
if (!node_input || !node_input.link) {
return undefined;
}
return widget.origSerializeValue ? widget.origSerializeValue() : widget.value;
};
// Hide any linked widgets, e.g. seed+seedControl
if (widget.linkedWidgets) {
for (const w of widget.linkedWidgets) {
hideWidget(node, w, ":" + widget.name);
}
}
}
export function getWidgetType(config) {
// Special handling for COMBO so we restrict links based on the entries
let type = config[0];
if (type instanceof Array) {
type = "COMBO";
}
return { type };
}
export function convertToInput(node, widget, config) {
hideWidget(node, widget);
const { type } = getWidgetType(config);
// Add input and store widget config for creating on primitive node
const sz = node.size;
node.addInput(widget.name, type, {
widget: { name: widget.name, [GET_CONFIG]: () => config },
});
for (const widget of node.widgets) {
widget.last_y += LiteGraph.NODE_SLOT_HEIGHT;
}
// Restore original size but grow if needed
node.setSize([Math.max(sz[0], node.size[0]), Math.max(sz[1], node.size[1])]);
}
export function tinyterraReloadNode(node) {
// Retrieves original values or uses current ones as fallback. Options for creating a new node.
const { title: nodeTitle, color: nodeColor, bgcolor: bgColor } = node.properties.origVals || node;
const options = {
size: [...node.size],
color: nodeColor,
bgcolor: bgColor,
pos: [...node.pos]
};
// Store a reference to the old node before it gets replaced.
const oldNode = node
// Track connections to re-establish later.
const inputConnections = [], outputConnections = [];
if (node.inputs) {
for (const input of node.inputs ?? []) {
if (input.link) {
const input_name = input.name
const input_slot = node.findInputSlot(input_name)
const input_node = node.getInputNode(input_slot)
const input_link = node.getInputLink(input_slot)
inputConnections.push([input_link.origin_slot, input_node, input_name])
}
}
}
if (node.outputs) {
for (const output of node.outputs) {
if (output.links) {
const output_name = output.name
for (const linkID of output.links) {
const output_link = graph.links[linkID]
const output_node = graph._nodes_by_id[output_link.target_id]
outputConnections.push([output_name, output_node, output_link.target_slot])
}
}
}
}
// Remove old node and create a new one.
app.graph.remove(node)
const newNode = app.graph.add(LiteGraph.createNode(node.constructor.type, nodeTitle, options));
if (newNode?.constructor?.hasOwnProperty('ttNnodeVersion')) {
newNode.properties.ttNnodeVersion = newNode.constructor.ttNnodeVersion;
}
// A function to handle reconnection of links to the new node.
function handleLinks() {
for (let ow of oldNode.widgets) {
if (ow.type === CONVERTED_TYPE) {
const config = getConfig(ow.name, oldNode)
const WidgetToConvert = newNode.widgets.find((nw) => nw.name === ow.name);
if (WidgetToConvert && !newNode?.inputs?.find((i) => i.name === ow.name)) {
convertToInput(newNode, WidgetToConvert, config);
}
}
}
// replace input and output links
for (let input of inputConnections) {
const [output_slot, output_node, input_name] = input;
output_node.connect(output_slot, newNode.id, input_name)
}
for (let output of outputConnections) {
const [output_name, input_node, input_slot] = output;
newNode.connect(output_name, input_node, input_slot)
}
}
// fix widget values
let values = oldNode.widgets_values;
if (!values) {
console.log('NO VALUES')
newNode.widgets.forEach((newWidget, index) => {
let pass = false
while ((index < oldNode.widgets.length) && !pass) {
const oldWidget = oldNode.widgets[index];
if (newWidget.type === oldWidget.type) {
newWidget.value = oldWidget.value;
pass = true
}
index++;
}
});
}
else {
let isValid = false
const isIterateForwards = values.length <= newNode.widgets.length;
let valueIndex = isIterateForwards ? 0 : values.length - 1;
const parseWidgetValue = (value, widget) => {
if (['', null].includes(value) && (widget.type === "button" || widget.type === "converted-widget")) {
return { value, isValid: true };
}
if (typeof value === "boolean" && widget.options?.on && widget.options?.off) {
return { value, isValid: true };
}
if (widget.options?.values?.includes(value)) {
return { value, isValid: true };
}
if (widget.inputEl) {
if (typeof value === "string" || value === widget.value) {
return { value, isValid: true };
}
}
if (!isNaN(value)) {
value = parseFloat(value);
if (widget.options?.min <= value && value <= widget.options?.max) {
return { value, isValid: true };
}
}
return { value: widget.value, isValid: false };
};
function updateValue(widgetIndex) {
const oldWidget = oldNode.widgets[widgetIndex];
let newWidget = newNode.widgets[widgetIndex];
let newValueIndex = valueIndex
if (newWidget.name === oldWidget.name && (newWidget.type === oldWidget.type || oldWidget.type === 'ttNhidden' || newWidget.type === 'ttNhidden')) {
while ((isIterateForwards ? newValueIndex < values.length : newValueIndex >= 0) && !isValid) {
let { value, isValid } = parseWidgetValue(values[newValueIndex], newWidget);
if (isValid && value !== NaN) {
newWidget.value = value;
break;
}
newValueIndex += isIterateForwards ? 1 : -1;
}
if (isIterateForwards) {
if (newValueIndex === valueIndex) {
valueIndex++;
}
if (newValueIndex === valueIndex + 1) {
valueIndex++;
valueIndex++;
}
} else {
if (newValueIndex === valueIndex) {
valueIndex--;
}
if (newValueIndex === valueIndex - 1) {
valueIndex--;
valueIndex--;
}
}
//console.log('\n')
}
};
if (isIterateForwards) {
for (let widgetIndex = 0; widgetIndex < newNode.widgets.length; widgetIndex++) {
updateValue(widgetIndex);
}
} else {
for (let widgetIndex = newNode.widgets.length - 1; widgetIndex >= 0; widgetIndex--) {
updateValue(widgetIndex);
}
}
}
handleLinks();
newNode.setSize(options.size)
newNode.onResize([0,0]);
};