diff --git a/src/extensions/core/groupNode.js b/src/extensions/core/groupNode.ts similarity index 97% rename from src/extensions/core/groupNode.js rename to src/extensions/core/groupNode.ts index c0a575d9e..f1ba5982a 100644 --- a/src/extensions/core/groupNode.js +++ b/src/extensions/core/groupNode.ts @@ -2,6 +2,7 @@ import { app } from "../../scripts/app"; import { api } from "../../scripts/api"; import { mergeIfValid } from "./widgetInputs"; import { ManageGroupDialog } from "./groupNodeManage"; +import type { LGraphNode } from "/types/litegraph"; const GROUP = Symbol(); @@ -14,7 +15,9 @@ const Workflow = { isInUseGroupNode(name) { const id = `workflow/${name}`; // Check if lready registered/in use in this workflow + // @ts-ignore if (app.graph.extra?.groupNodes?.[name]) { + // @ts-ignore if (app.graph._nodes.find((n) => n.type === id)) { return Workflow.InUse.InWorkflow; } else { @@ -24,7 +27,9 @@ const Workflow = { return Workflow.InUse.Free; }, storeGroupNode(name, data) { + // @ts-ignore let extra = app.graph.extra; + // @ts-ignore if (!extra) app.graph.extra = extra = {}; let groupNodes = extra.groupNodes; if (!groupNodes) extra.groupNodes = groupNodes = {}; @@ -33,6 +38,9 @@ const Workflow = { }; class GroupNodeBuilder { + nodes: LGraphNode[]; + nodeData: any; + constructor(nodes) { this.nodes = nodes; } @@ -120,6 +128,8 @@ class GroupNodeBuilder { // Use the built in copyToClipboard function to generate the node data we need const backup = localStorage.getItem("litegrapheditor_clipboard"); try { + // @ts-ignore + // TODO Figure out if copyToClipboard is really taking this param app.canvas.copyToClipboard(this.nodes); const config = JSON.parse(localStorage.getItem("litegrapheditor_clipboard")); @@ -134,6 +144,25 @@ class GroupNodeBuilder { } export class GroupNodeConfig { + name: string; + nodeData: any; + inputCount: number; + oldToNewOutputMap: {}; + newToOldOutputMap: {}; + oldToNewInputMap: {}; + oldToNewWidgetMap: {}; + newToOldWidgetMap: {}; + primitiveDefs: {}; + widgetToPrimitive: {}; + primitiveToWidget: {}; + nodeInputs: {}; + outputVisibility: any[]; + nodeDef: any; + inputs: any[]; + linksFrom: {}; + linksTo: {}; + externalFrom: {}; + constructor(name, nodeData) { this.name = name; this.nodeData = nodeData; @@ -289,6 +318,7 @@ export class GroupNodeConfig { null, widget ); + // @ts-ignore config = res?.customConfig ?? config; } } @@ -312,6 +342,7 @@ export class GroupNodeConfig { } } + // @ts-ignore config.forceInput = true; return { input: { @@ -328,7 +359,7 @@ export class GroupNodeConfig { console.warn("Skipping virtual node " + node.type + " when building group node " + this.name); } - getInputConfig(node, inputName, seenInputs, config, extra) { + getInputConfig(node, inputName, seenInputs, config, extra?) { const customConfig = this.nodeData.config?.[node.index]?.input?.[inputName]; let name = customConfig?.name ?? node.inputs?.find((inp) => inp.name === inputName)?.label ?? inputName; let key = name; @@ -580,6 +611,7 @@ export class GroupNodeConfig { export class GroupNodeHandler { node; groupData; + innerNodes: any; constructor(node) { this.node = node; @@ -624,6 +656,8 @@ export class GroupNodeHandler { let link = app.graph.links[linkId]; // Use the outer link, but update the target to the inner node + // @ts-ignore + // TODO: Fix this link = { ...link, target_id: innerNode.id, @@ -676,6 +710,7 @@ export class GroupNodeHandler { this.groupData.nodeData.nodes.map((n, i) => { const innerNode = LiteGraph.createNode(n.type); innerNode.configure(n); + // @ts-ignore innerNode.id = `${this.node.id}:${i}`; return innerNode; }) @@ -1225,7 +1260,9 @@ function addConvertToGroupOptions() { } // Add to canvas + // @ts-ignore const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions; + // @ts-ignore LGraphCanvas.prototype.getCanvasMenuOptions = function () { const options = getCanvasMenuOptions.apply(this, arguments); const index = options.findIndex((o) => o?.content === "Add Group") + 1 || options.length; @@ -1235,7 +1272,9 @@ function addConvertToGroupOptions() { }; // Add to nodes + // @ts-ignore const getNodeMenuOptions = LGraphCanvas.prototype.getNodeMenuOptions; + // @ts-ignore LGraphCanvas.prototype.getNodeMenuOptions = function (node) { const options = getNodeMenuOptions.apply(this, arguments); if (!GroupNodeHandler.isGroupNode(node)) { diff --git a/src/extensions/core/widgetInputs.js b/src/extensions/core/widgetInputs.js index fc705f467..38aefa7ca 100644 --- a/src/extensions/core/widgetInputs.js +++ b/src/extensions/core/widgetInputs.js @@ -158,11 +158,11 @@ export function mergeIfValid(output, config2, forceUpdate, recreateWidget, confi } if (config1[0] instanceof Array) { - if (!isValidCombo(config1[0], config2[0])) return false; + if (!isValidCombo(config1[0], config2[0])) return; } else if (config1[0] !== config2[0]) { // Types dont match console.log(`connection rejected: types dont match`, config1[0], config2[0]); - return false; + return; } const keys = new Set([...Object.keys(config1[1] ?? {}), ...Object.keys(config2[1] ?? {})]); @@ -192,7 +192,7 @@ export function mergeIfValid(output, config2, forceUpdate, recreateWidget, confi const theirMax = config2[1]?.["max"]; if (theirMax != null && v1 > theirMax) { console.log("connection rejected: min > max", v1, theirMax); - return false; + return; } getCustomConfig()[k] = v1 == null ? v2 : v2 == null ? v1 : Math.max(v1, v2); continue; @@ -200,7 +200,7 @@ export function mergeIfValid(output, config2, forceUpdate, recreateWidget, confi const theirMin = config2[1]?.["min"]; if (theirMin != null && v1 < theirMin) { console.log("connection rejected: max < min", v1, theirMin); - return false; + return; } getCustomConfig()[k] = v1 == null ? v2 : v2 == null ? v1 : Math.min(v1, v2); continue; @@ -221,7 +221,7 @@ export function mergeIfValid(output, config2, forceUpdate, recreateWidget, confi } if (v1 % v2) { console.log("connection rejected: steps not divisible", "current:", v1, "new:", v2); - return false; + return; } step = v1; @@ -233,7 +233,7 @@ export function mergeIfValid(output, config2, forceUpdate, recreateWidget, confi } console.log(`connection rejected: config ${k} values dont match`, v1, v2); - return false; + return; } } @@ -302,7 +302,7 @@ app.registerExtension({ } } } - + //Convert.. main menu if (toInput.length) { if (useConversionSubmenusSetting.value) { diff --git a/src/types/litegraph.d.ts b/src/types/litegraph.d.ts index 1069d257c..28a5563a1 100644 --- a/src/types/litegraph.d.ts +++ b/src/types/litegraph.d.ts @@ -52,6 +52,9 @@ export type WidgetCallback = ( ) => void; export interface IWidget { + // linked widgets, e.g. seed+seedControl + linkedWidgets: IWidget[]; + name: string | null; value: TValue; options?: TOptions; @@ -162,6 +165,7 @@ export declare class LGraph { static supported_types: string[]; static STATUS_STOPPED: 1; static STATUS_RUNNING: 2; + extra: any; constructor(o?: object); @@ -407,6 +411,11 @@ export type SerializedLGraphNode = { /** https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md#lgraphnode */ export declare class LGraphNode { + // Used in group node + setInnerNodes(nodes: any) { + throw new Error("Method not implemented."); + } + static title_color: string; static title: string; static type: null | string;