Allow creating floating reroutes from new link menu (#818)

Adds an `Add Reroute` option to the new link menu. Creates a new
floating reroute connected to the source slot.
This commit is contained in:
filtered
2025-03-22 09:23:20 +11:00
committed by GitHub
parent 7c6245ab1c
commit 2dbd5f4cf0
3 changed files with 50 additions and 7 deletions

View File

@@ -5292,8 +5292,7 @@ export class LGraphCanvas implements ConnectionColorContext {
const node_left = graph.getNodeById(origin_id)
const fromType = node_left?.outputs?.[origin_slot]?.type
const options = ["Add Node", null, "Delete", null]
options.splice(1, 0, "Add Reroute")
const options = ["Add Node", "Add Reroute", null, "Delete", null]
const menu = new LiteGraph.ContextMenu<string>(options, {
event: e,
@@ -5511,6 +5510,7 @@ export class LGraphCanvas implements ConnectionColorContext {
showSearchBox: this.showSearchBox,
}, optPass || {})
const that = this
const { graph } = this
const { afterRerouteId } = opts
const isFrom = opts.nodeFrom && opts.slotFrom
@@ -5553,7 +5553,7 @@ export class LGraphCanvas implements ConnectionColorContext {
return
}
const options = ["Add Node", null]
const options = ["Add Node", "Add Reroute", null]
if (opts.allow_searchbox) {
options.push("Search", null)
@@ -5577,6 +5577,7 @@ export class LGraphCanvas implements ConnectionColorContext {
// build menu
const menu = new LiteGraph.ContextMenu<string>(options, {
event: opts.e,
extra: slotX,
title:
(slotX && slotX.name != ""
? slotX.name + (fromSlotType ? " | " : "")
@@ -5584,8 +5585,10 @@ export class LGraphCanvas implements ConnectionColorContext {
callback: inner_clicked,
})
const dirty = () => this.#dirty()
// callback
function inner_clicked(v: string, options: unknown, e: MouseEvent) {
function inner_clicked(v: string | undefined, options: IContextMenuOptions<string, INodeInputSlot | INodeOutputSlot>, e: MouseEvent) {
// console.log("Process showConnectionMenu selection");
switch (v) {
case "Add Node":
@@ -5599,6 +5602,21 @@ export class LGraphCanvas implements ConnectionColorContext {
}
})
break
case "Add Reroute":{
const node = isFrom ? opts.nodeFrom : opts.nodeTo
const slot = options.extra
if (!graph) throw new NullGraphError()
if (!node) throw new TypeError("Cannot add reroute: node was null")
if (!slot) throw new TypeError("Cannot add reroute: slot was null")
if (!opts.e) throw new TypeError("Cannot add reroute: CanvasPointerEvent was null")
const reroute = node.connectFloatingReroute([opts.e.canvasX, opts.e.canvasY], slot)
if (!reroute) throw new Error("Failed to create reroute")
dirty()
break
}
case "Search":
if (isFrom) {
opts.showSearchBox(e, { node_from: opts.nodeFrom, slot_from: slotX, type_filter_in: fromSlotType })

View File

@@ -20,7 +20,7 @@ import type {
Size,
} from "./interfaces"
import type { LGraph } from "./LGraph"
import type { RerouteId } from "./Reroute"
import type { Reroute, RerouteId } from "./Reroute"
import type { CanvasMouseEvent } from "./types/events"
import type { ISerialisedNode } from "./types/serialisation"
import type { IBaseWidget, IWidget, IWidgetOptions, TWidgetType, TWidgetValue } from "./types/widgets"
@@ -2545,6 +2545,31 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
return link
}
connectFloatingReroute(pos: Point, slot: INodeInputSlot | INodeOutputSlot): Reroute {
const { graph, id } = this
if (!graph) throw new NullGraphError()
// Assertion: It's either there or it isn't.
const inputIndex = this.inputs.indexOf(slot as INodeInputSlot)
const outputIndex = this.outputs.indexOf(slot as INodeOutputSlot)
if (inputIndex === -1 && outputIndex === -1) throw new Error("Invalid slot")
const link = new LLink(
-1,
slot.type,
outputIndex === -1 ? -1 : id,
outputIndex,
inputIndex === -1 ? -1 : id,
inputIndex,
)
const slotType = outputIndex === -1 ? "input" : "output"
const reroute = graph.setReroute({ pos, linkIds: [], floating: { slotType } })
link.parentId = reroute.id
graph.addFloatingLink(link)
return reroute
}
/**
* disconnect one output to an specific node
* @param slot (could be the number of the slot or the string with the name of the slot)

View File

@@ -341,11 +341,11 @@ interface IContextMenuBase {
}
/** ContextMenu */
export interface IContextMenuOptions<TValue = unknown> extends IContextMenuBase {
export interface IContextMenuOptions<TValue = unknown, TExtra = unknown> extends IContextMenuBase {
ignore_item_callbacks?: boolean
parentMenu?: ContextMenu<TValue>
event?: MouseEvent
extra?: unknown
extra?: TExtra
/** @deprecated Context menu scrolling is now controlled by the browser */
scroll_speed?: number
left?: number