261 lines
8.8 KiB
JavaScript
261 lines
8.8 KiB
JavaScript
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]);
|
|
}; |