mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-08 00:50:05 +00:00
[Refactor] Split moving links (#839)
Splits moving links out to separate input and output classes.
This commit is contained in:
@@ -131,8 +131,6 @@ export class FloatingRenderLink implements RenderLink {
|
||||
this.fromSlot._floatingLinks?.delete(floatingLink)
|
||||
output._floatingLinks ??= new Set()
|
||||
output._floatingLinks.add(floatingLink)
|
||||
|
||||
console.debug(`Set origin_id:origin_slot [${floatingLink.origin_id}:${floatingLink.origin_slot}].`)
|
||||
}
|
||||
|
||||
connectToRerouteInput(
|
||||
@@ -148,8 +146,6 @@ export class FloatingRenderLink implements RenderLink {
|
||||
input._floatingLinks ??= new Set()
|
||||
input._floatingLinks.add(floatingLink)
|
||||
|
||||
console.debug(`Set target_id:target_slot [${floatingLink.target_id}:${floatingLink.target_slot}].`)
|
||||
|
||||
events.dispatch("input-moved", this)
|
||||
}
|
||||
|
||||
@@ -167,8 +163,6 @@ export class FloatingRenderLink implements RenderLink {
|
||||
output._floatingLinks ??= new Set()
|
||||
output._floatingLinks.add(floatingLink)
|
||||
|
||||
console.debug(`Set origin_id:origin_slot [${floatingLink.origin_id}:${floatingLink.origin_slot}].`)
|
||||
|
||||
events.dispatch("output-moved", this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ import { LLink } from "@/LLink"
|
||||
import { LinkDirection } from "@/types/globalEnums"
|
||||
|
||||
import { FloatingRenderLink } from "./FloatingRenderLink"
|
||||
import { MovingRenderLink } from "./MovingRenderLink"
|
||||
import { MovingInputLink } from "./MovingInputLink"
|
||||
import { MovingLinkBase } from "./MovingLinkBase"
|
||||
import { MovingOutputLink } from "./MovingOutputLink"
|
||||
import { ToInputRenderLink } from "./ToInputRenderLink"
|
||||
import { ToOutputRenderLink } from "./ToOutputRenderLink"
|
||||
|
||||
@@ -33,7 +35,7 @@ export interface LinkConnectorState {
|
||||
}
|
||||
|
||||
/** Discriminated union to simplify type narrowing. */
|
||||
type RenderLinkUnion = MovingRenderLink | FloatingRenderLink | ToInputRenderLink | ToOutputRenderLink
|
||||
type RenderLinkUnion = MovingInputLink | MovingOutputLink | FloatingRenderLink | ToInputRenderLink | ToOutputRenderLink
|
||||
|
||||
export interface LinkConnectorExport {
|
||||
renderLinks: RenderLink[]
|
||||
@@ -130,7 +132,7 @@ export class LinkConnector {
|
||||
|
||||
try {
|
||||
const reroute = network.getReroute(link.parentId)
|
||||
const renderLink = new MovingRenderLink(network, link, "input", reroute)
|
||||
const renderLink = new MovingInputLink(network, link, reroute)
|
||||
|
||||
const mayContinue = this.events.dispatch("before-move-input", renderLink)
|
||||
if (mayContinue === false) return
|
||||
@@ -196,7 +198,7 @@ export class LinkConnector {
|
||||
this.outputLinks.push(link)
|
||||
|
||||
try {
|
||||
const renderLink = new MovingRenderLink(network, link, "output", firstReroute, LinkDirection.RIGHT)
|
||||
const renderLink = new MovingOutputLink(network, link, firstReroute, LinkDirection.RIGHT)
|
||||
|
||||
const mayContinue = this.events.dispatch("before-move-output", renderLink)
|
||||
if (mayContinue === false) continue
|
||||
@@ -449,7 +451,7 @@ export class LinkConnector {
|
||||
// For external event only.
|
||||
if (this.state.connectingTo === "input") {
|
||||
for (const link of this.renderLinks) {
|
||||
if (link instanceof MovingRenderLink) {
|
||||
if (link instanceof MovingInputLink) {
|
||||
link.inputNode.disconnectInput(link.inputIndex, true)
|
||||
}
|
||||
}
|
||||
@@ -505,7 +507,7 @@ export class LinkConnector {
|
||||
#dropOnOutput(node: LGraphNode, output: INodeOutputSlot): void {
|
||||
for (const link of this.renderLinks) {
|
||||
if (!link.canConnectToOutput(node, output)) {
|
||||
if (link instanceof MovingRenderLink && link.link.parentId !== undefined) {
|
||||
if (link instanceof MovingOutputLink && link.link.parentId !== undefined) {
|
||||
// Reconnect link without reroutes
|
||||
link.outputNode.connectSlots(link.outputSlot, link.inputNode, link.inputSlot, undefined!)
|
||||
}
|
||||
@@ -560,7 +562,7 @@ export class LinkConnector {
|
||||
const input = fromSlotIsInput ? link.fromSlot as INodeInputSlot : null
|
||||
const output = fromSlotIsInput ? null : link.fromSlot as INodeOutputSlot
|
||||
|
||||
const afterRerouteId = link instanceof MovingRenderLink ? link.link?.parentId : link.fromReroute?.id
|
||||
const afterRerouteId = link instanceof MovingLinkBase ? link.link?.parentId : link.fromReroute?.id
|
||||
|
||||
return {
|
||||
node: link.node,
|
||||
@@ -634,7 +636,7 @@ export class LinkConnector {
|
||||
|
||||
/** Validates that a single {@link RenderLink} can be dropped on the specified reroute. */
|
||||
function canConnectInputLinkToReroute(
|
||||
link: ToInputRenderLink | MovingRenderLink | FloatingRenderLink,
|
||||
link: ToInputRenderLink | MovingInputLink | FloatingRenderLink,
|
||||
inputNode: LGraphNode,
|
||||
input: INodeInputSlot,
|
||||
reroute: Reroute,
|
||||
|
||||
78
src/canvas/MovingInputLink.ts
Normal file
78
src/canvas/MovingInputLink.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import type { LinkConnectorEventTarget } from "@/infrastructure/LinkConnectorEventTarget"
|
||||
import type { INodeInputSlot, INodeOutputSlot, LinkNetwork, Point } from "@/interfaces"
|
||||
import type { LGraphNode } from "@/LGraphNode"
|
||||
import type { LLink } from "@/LLink"
|
||||
import type { Reroute } from "@/Reroute"
|
||||
|
||||
import { LinkDirection } from "@/types/globalEnums"
|
||||
|
||||
import { MovingLinkBase } from "./MovingLinkBase"
|
||||
|
||||
export class MovingInputLink extends MovingLinkBase {
|
||||
readonly toType = "input"
|
||||
|
||||
readonly node: LGraphNode
|
||||
readonly fromSlot: INodeOutputSlot
|
||||
readonly fromPos: Point
|
||||
readonly fromDirection: LinkDirection
|
||||
readonly fromSlotIndex: number
|
||||
|
||||
constructor(network: LinkNetwork, link: LLink, fromReroute?: Reroute, dragDirection: LinkDirection = LinkDirection.CENTER) {
|
||||
super(network, link, "input", fromReroute, dragDirection)
|
||||
|
||||
this.node = this.outputNode
|
||||
this.fromSlot = this.outputSlot
|
||||
this.fromPos = fromReroute?.pos ?? this.outputPos
|
||||
this.fromDirection = LinkDirection.NONE
|
||||
this.fromSlotIndex = this.outputIndex
|
||||
}
|
||||
|
||||
canConnectToInput(inputNode: LGraphNode, input: INodeInputSlot): boolean {
|
||||
return this.node.canConnectTo(inputNode, input, this.outputSlot)
|
||||
}
|
||||
|
||||
canConnectToOutput(): false {
|
||||
return false
|
||||
}
|
||||
|
||||
canConnectToReroute(reroute: Reroute): boolean {
|
||||
return reroute.origin_id !== this.inputNode.id
|
||||
}
|
||||
|
||||
connectToInput(inputNode: LGraphNode, input: INodeInputSlot, events: LinkConnectorEventTarget): LLink | null | undefined {
|
||||
if (input === this.inputSlot) return
|
||||
|
||||
const link = this.outputNode.connectSlots(this.outputSlot, inputNode, input, this.fromReroute?.id)
|
||||
if (link) events.dispatch("input-moved", this)
|
||||
return link
|
||||
}
|
||||
|
||||
connectToOutput(): never {
|
||||
throw new Error("MovingInputLink cannot connect to an output.")
|
||||
}
|
||||
|
||||
connectToRerouteInput(
|
||||
reroute: Reroute,
|
||||
{ node: inputNode, input, link: existingLink }: { node: LGraphNode, input: INodeInputSlot, link: LLink },
|
||||
events: LinkConnectorEventTarget,
|
||||
originalReroutes: Reroute[],
|
||||
): void {
|
||||
const { outputNode, outputSlot, fromReroute } = this
|
||||
|
||||
// Clean up reroutes
|
||||
for (const reroute of originalReroutes) {
|
||||
if (reroute.id === this.link.parentId) break
|
||||
|
||||
if (reroute.totalLinks === 1) reroute.remove()
|
||||
}
|
||||
// Set the parentId of the reroute we dropped on, to the reroute we dragged from
|
||||
reroute.parentId = fromReroute?.id
|
||||
|
||||
const newLink = outputNode.connectSlots(outputSlot, inputNode, input, existingLink.parentId)
|
||||
if (newLink) events.dispatch("input-moved", this)
|
||||
}
|
||||
|
||||
connectToRerouteOutput(): never {
|
||||
throw new Error("MovingInputLink cannot connect to an output.")
|
||||
}
|
||||
}
|
||||
86
src/canvas/MovingLinkBase.ts
Normal file
86
src/canvas/MovingLinkBase.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import type { RenderLink } from "./RenderLink"
|
||||
import type { LinkConnectorEventTarget } from "@/infrastructure/LinkConnectorEventTarget"
|
||||
import type { INodeInputSlot, INodeOutputSlot, LinkNetwork, Point } from "@/interfaces"
|
||||
import type { LGraphNode, NodeId } from "@/LGraphNode"
|
||||
import type { LLink } from "@/LLink"
|
||||
import type { Reroute } from "@/Reroute"
|
||||
|
||||
import { LinkDirection } from "@/types/globalEnums"
|
||||
|
||||
/**
|
||||
* Represents an existing link that is currently being dragged by the user from one slot to another.
|
||||
*
|
||||
* This is a heavier, but short-lived convenience data structure.
|
||||
* All refs to {@link MovingInputLink} and {@link MovingOutputLink} should be discarded on drop.
|
||||
* @remarks
|
||||
* At time of writing, Litegraph is using several different styles and methods to handle link dragging.
|
||||
*
|
||||
* Once the library has undergone more substantial changes to the way links are managed,
|
||||
* many properties of this class will be superfluous and removable.
|
||||
*/
|
||||
|
||||
export abstract class MovingLinkBase implements RenderLink {
|
||||
abstract readonly node: LGraphNode
|
||||
abstract readonly fromSlot: INodeOutputSlot | INodeInputSlot
|
||||
abstract readonly fromPos: Point
|
||||
abstract readonly fromDirection: LinkDirection
|
||||
abstract readonly fromSlotIndex: number
|
||||
|
||||
readonly outputNodeId: NodeId
|
||||
readonly outputNode: LGraphNode
|
||||
readonly outputSlot: INodeOutputSlot
|
||||
readonly outputIndex: number
|
||||
readonly outputPos: Point
|
||||
|
||||
readonly inputNodeId: NodeId
|
||||
readonly inputNode: LGraphNode
|
||||
readonly inputSlot: INodeInputSlot
|
||||
readonly inputIndex: number
|
||||
readonly inputPos: Point
|
||||
|
||||
constructor(
|
||||
readonly network: LinkNetwork,
|
||||
readonly link: LLink,
|
||||
readonly toType: "input" | "output",
|
||||
readonly fromReroute?: Reroute,
|
||||
readonly dragDirection: LinkDirection = LinkDirection.CENTER,
|
||||
) {
|
||||
const {
|
||||
origin_id: outputNodeId,
|
||||
target_id: inputNodeId,
|
||||
origin_slot: outputIndex,
|
||||
target_slot: inputIndex,
|
||||
} = link
|
||||
|
||||
// Store output info
|
||||
const outputNode = network.getNodeById(outputNodeId) ?? undefined
|
||||
if (!outputNode) throw new Error(`Creating MovingRenderLink for link [${link.id}] failed: Output node [${outputNodeId}] not found.`)
|
||||
|
||||
const outputSlot = outputNode.outputs.at(outputIndex)
|
||||
if (!outputSlot) throw new Error(`Creating MovingRenderLink for link [${link.id}] failed: Output slot [${outputIndex}] not found.`)
|
||||
|
||||
this.outputNodeId = outputNodeId
|
||||
this.outputNode = outputNode
|
||||
this.outputSlot = outputSlot
|
||||
this.outputIndex = outputIndex
|
||||
this.outputPos = outputNode.getOutputPos(outputIndex)
|
||||
|
||||
// Store input info
|
||||
const inputNode = network.getNodeById(inputNodeId) ?? undefined
|
||||
if (!inputNode) throw new Error(`Creating DraggingRenderLink for link [${link.id}] failed: Input node [${inputNodeId}] not found.`)
|
||||
|
||||
const inputSlot = inputNode.inputs.at(inputIndex)
|
||||
if (!inputSlot) throw new Error(`Creating DraggingRenderLink for link [${link.id}] failed: Input slot [${inputIndex}] not found.`)
|
||||
|
||||
this.inputNodeId = inputNodeId
|
||||
this.inputNode = inputNode
|
||||
this.inputSlot = inputSlot
|
||||
this.inputIndex = inputIndex
|
||||
this.inputPos = inputNode.getInputPos(inputIndex)
|
||||
}
|
||||
|
||||
abstract connectToInput(node: LGraphNode, input: INodeInputSlot, events?: LinkConnectorEventTarget): void
|
||||
abstract connectToOutput(node: LGraphNode, output: INodeOutputSlot, events?: LinkConnectorEventTarget): void
|
||||
abstract connectToRerouteInput(reroute: Reroute, { node, input, link }: { node: LGraphNode, input: INodeInputSlot, link: LLink }, events: LinkConnectorEventTarget, originalReroutes: Reroute[]): void
|
||||
abstract connectToRerouteOutput(reroute: Reroute, outputNode: LGraphNode, output: INodeOutputSlot, events: LinkConnectorEventTarget): void
|
||||
}
|
||||
85
src/canvas/MovingOutputLink.ts
Normal file
85
src/canvas/MovingOutputLink.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import type { LinkConnectorEventTarget } from "@/infrastructure/LinkConnectorEventTarget"
|
||||
import type { INodeInputSlot, INodeOutputSlot, LinkNetwork, Point } from "@/interfaces"
|
||||
import type { LGraphNode } from "@/LGraphNode"
|
||||
import type { LLink } from "@/LLink"
|
||||
import type { Reroute } from "@/Reroute"
|
||||
|
||||
import { LinkDirection } from "@/types/globalEnums"
|
||||
|
||||
import { MovingLinkBase } from "./MovingLinkBase"
|
||||
|
||||
export class MovingOutputLink extends MovingLinkBase {
|
||||
readonly toType = "output"
|
||||
|
||||
readonly node: LGraphNode
|
||||
readonly fromSlot: INodeInputSlot
|
||||
readonly fromPos: Point
|
||||
readonly fromDirection: LinkDirection
|
||||
readonly fromSlotIndex: number
|
||||
|
||||
constructor(network: LinkNetwork, link: LLink, fromReroute?: Reroute, dragDirection: LinkDirection = LinkDirection.CENTER) {
|
||||
super(network, link, "output", fromReroute, dragDirection)
|
||||
|
||||
this.node = this.inputNode
|
||||
this.fromSlot = this.inputSlot
|
||||
this.fromPos = fromReroute?.pos ?? this.inputPos
|
||||
this.fromDirection = LinkDirection.LEFT
|
||||
this.fromSlotIndex = this.inputIndex
|
||||
}
|
||||
|
||||
canConnectToInput(): false {
|
||||
return false
|
||||
}
|
||||
|
||||
canConnectToOutput(outputNode: LGraphNode, output: INodeOutputSlot): boolean {
|
||||
return outputNode.canConnectTo(this.node, this.inputSlot, output)
|
||||
}
|
||||
|
||||
canConnectToReroute(reroute: Reroute): boolean {
|
||||
return reroute.origin_id !== this.outputNode.id
|
||||
}
|
||||
|
||||
connectToInput(): never {
|
||||
throw new Error("MovingOutputLink cannot connect to an input.")
|
||||
}
|
||||
|
||||
connectToOutput(outputNode: LGraphNode, output: INodeOutputSlot, events: LinkConnectorEventTarget): LLink | null | undefined {
|
||||
if (output === this.outputSlot) return
|
||||
|
||||
const link = outputNode.connectSlots(output, this.inputNode, this.inputSlot, this.link.parentId)
|
||||
if (link) events.dispatch("output-moved", this)
|
||||
return link
|
||||
}
|
||||
|
||||
connectToRerouteInput(): never {
|
||||
throw new Error("MovingOutputLink cannot connect to an input.")
|
||||
}
|
||||
|
||||
connectToRerouteOutput(
|
||||
reroute: Reroute,
|
||||
outputNode: LGraphNode,
|
||||
output: INodeOutputSlot,
|
||||
events: LinkConnectorEventTarget,
|
||||
): void {
|
||||
// Moving output side of links
|
||||
const { inputNode, inputSlot, fromReroute } = this
|
||||
|
||||
// Creating a new link removes floating prop - check before connecting
|
||||
const floatingTerminus = reroute?.floating?.slotType === "output"
|
||||
|
||||
// Connect the first reroute of the link being dragged to the reroute being dropped on
|
||||
if (fromReroute) {
|
||||
fromReroute.parentId = reroute.id
|
||||
} else {
|
||||
// If there are no reroutes, directly connect the link
|
||||
this.link.parentId = reroute.id
|
||||
}
|
||||
// Use the last reroute id on the link to retain all reroutes
|
||||
outputNode.connectSlots(output, inputNode, inputSlot, this.link.parentId)
|
||||
|
||||
// Connecting from the final reroute of a floating reroute chain
|
||||
if (floatingTerminus) reroute.removeAllFloatingLinks()
|
||||
|
||||
events.dispatch("output-moved", this)
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
import type { RenderLink } from "./RenderLink"
|
||||
import type { LinkConnectorEventTarget } from "@/infrastructure/LinkConnectorEventTarget"
|
||||
import type { INodeOutputSlot, LinkNetwork } from "@/interfaces"
|
||||
import type { INodeInputSlot } from "@/interfaces"
|
||||
import type { Point } from "@/interfaces"
|
||||
import type { LGraphNode, NodeId } from "@/LGraphNode"
|
||||
import type { LLink } from "@/LLink"
|
||||
import type { Reroute } from "@/Reroute"
|
||||
|
||||
import { LinkDirection } from "@/types/globalEnums"
|
||||
|
||||
/**
|
||||
* Represents an existing link that is currently being dragged by the user from one slot to another.
|
||||
*
|
||||
* This is a heavier, but short-lived convenience data structure. All refs to MovingRenderLinks should be discarded on drop.
|
||||
* @remarks
|
||||
* At time of writing, Litegraph is using several different styles and methods to handle link dragging.
|
||||
*
|
||||
* Once the library has undergone more substantial changes to the way links are managed,
|
||||
* many properties of this class will be superfluous and removable.
|
||||
*/
|
||||
export class MovingRenderLink implements RenderLink {
|
||||
readonly node: LGraphNode
|
||||
readonly fromSlot: INodeOutputSlot | INodeInputSlot
|
||||
readonly fromPos: Point
|
||||
readonly fromDirection: LinkDirection
|
||||
readonly fromSlotIndex: number
|
||||
|
||||
readonly outputNodeId: NodeId
|
||||
readonly outputNode: LGraphNode
|
||||
readonly outputSlot: INodeOutputSlot
|
||||
readonly outputIndex: number
|
||||
readonly outputPos: Point
|
||||
|
||||
readonly inputNodeId: NodeId
|
||||
readonly inputNode: LGraphNode
|
||||
readonly inputSlot: INodeInputSlot
|
||||
readonly inputIndex: number
|
||||
readonly inputPos: Point
|
||||
|
||||
constructor(
|
||||
readonly network: LinkNetwork,
|
||||
readonly link: LLink,
|
||||
readonly toType: "input" | "output",
|
||||
readonly fromReroute?: Reroute,
|
||||
readonly dragDirection: LinkDirection = LinkDirection.CENTER,
|
||||
) {
|
||||
const {
|
||||
origin_id: outputNodeId,
|
||||
target_id: inputNodeId,
|
||||
origin_slot: outputIndex,
|
||||
target_slot: inputIndex,
|
||||
} = link
|
||||
|
||||
// Store output info
|
||||
const outputNode = network.getNodeById(outputNodeId) ?? undefined
|
||||
if (!outputNode) throw new Error(`Creating MovingRenderLink for link [${link.id}] failed: Output node [${outputNodeId}] not found.`)
|
||||
|
||||
const outputSlot = outputNode.outputs.at(outputIndex)
|
||||
if (!outputSlot) throw new Error(`Creating MovingRenderLink for link [${link.id}] failed: Output slot [${outputIndex}] not found.`)
|
||||
|
||||
this.outputNodeId = outputNodeId
|
||||
this.outputNode = outputNode
|
||||
this.outputSlot = outputSlot
|
||||
this.outputIndex = outputIndex
|
||||
this.outputPos = outputNode.getOutputPos(outputIndex)
|
||||
|
||||
// Store input info
|
||||
const inputNode = network.getNodeById(inputNodeId) ?? undefined
|
||||
if (!inputNode) throw new Error(`Creating DraggingRenderLink for link [${link.id}] failed: Input node [${inputNodeId}] not found.`)
|
||||
|
||||
const inputSlot = inputNode.inputs.at(inputIndex)
|
||||
if (!inputSlot) throw new Error(`Creating DraggingRenderLink for link [${link.id}] failed: Input slot [${inputIndex}] not found.`)
|
||||
|
||||
this.inputNodeId = inputNodeId
|
||||
this.inputNode = inputNode
|
||||
this.inputSlot = inputSlot
|
||||
this.inputIndex = inputIndex
|
||||
this.inputPos = inputNode.getInputPos(inputIndex)
|
||||
|
||||
// RenderLink props
|
||||
this.node = this.toType === "input" ? outputNode : inputNode
|
||||
this.fromSlot = this.toType === "input" ? outputSlot : inputSlot
|
||||
this.fromPos = fromReroute?.pos ?? (this.toType === "input" ? this.outputPos : this.inputPos)
|
||||
this.fromDirection = this.toType === "input" ? LinkDirection.NONE : LinkDirection.LEFT
|
||||
this.fromSlotIndex = this.toType === "input" ? outputIndex : inputIndex
|
||||
}
|
||||
|
||||
canConnectToInput(inputNode: LGraphNode, input: INodeInputSlot): this is this {
|
||||
return this.node.canConnectTo(inputNode, input, this.outputSlot)
|
||||
}
|
||||
|
||||
canConnectToOutput(outputNode: LGraphNode, output: INodeOutputSlot): this is this {
|
||||
return outputNode.canConnectTo(this.node, this.inputSlot, output)
|
||||
}
|
||||
|
||||
canConnectToReroute(reroute: Reroute): boolean {
|
||||
if (this.toType === "input") {
|
||||
if (reroute.origin_id === this.inputNode.id) return false
|
||||
} else {
|
||||
if (reroute.origin_id === this.outputNode.id) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
connectToInput(inputNode: LGraphNode, input: INodeInputSlot, events: LinkConnectorEventTarget): LLink | null | undefined {
|
||||
if (input === this.inputSlot) return
|
||||
|
||||
const link = this.outputNode.connectSlots(this.outputSlot, inputNode, input, this.fromReroute?.id)
|
||||
if (link) events.dispatch("input-moved", this)
|
||||
return link
|
||||
}
|
||||
|
||||
connectToOutput(outputNode: LGraphNode, output: INodeOutputSlot, events: LinkConnectorEventTarget): LLink | null | undefined {
|
||||
if (output === this.outputSlot) return
|
||||
|
||||
const link = outputNode.connectSlots(output, this.inputNode, this.inputSlot, this.link.parentId)
|
||||
if (link) events.dispatch("output-moved", this)
|
||||
return link
|
||||
}
|
||||
|
||||
connectToRerouteInput(
|
||||
reroute: Reroute,
|
||||
{ node: inputNode, input, link: existingLink }: { node: LGraphNode, input: INodeInputSlot, link: LLink },
|
||||
events: LinkConnectorEventTarget,
|
||||
originalReroutes: Reroute[],
|
||||
): void {
|
||||
const { outputNode, outputSlot, fromReroute } = this
|
||||
|
||||
// Clean up reroutes
|
||||
for (const reroute of originalReroutes) {
|
||||
if (reroute.id === this.link.parentId) break
|
||||
|
||||
if (reroute.totalLinks === 1) reroute.remove()
|
||||
}
|
||||
// Set the parentId of the reroute we dropped on, to the reroute we dragged from
|
||||
reroute.parentId = fromReroute?.id
|
||||
|
||||
const newLink = outputNode.connectSlots(outputSlot, inputNode, input, existingLink.parentId)
|
||||
if (newLink) events.dispatch("input-moved", this)
|
||||
}
|
||||
|
||||
connectToRerouteOutput(
|
||||
reroute: Reroute,
|
||||
outputNode: LGraphNode,
|
||||
output: INodeOutputSlot,
|
||||
events: LinkConnectorEventTarget,
|
||||
): void {
|
||||
// Moving output side of links
|
||||
const { inputNode, inputSlot, fromReroute } = this
|
||||
|
||||
// Creating a new link removes floating prop - check before connecting
|
||||
const floatingTerminus = reroute?.floating?.slotType === "output"
|
||||
|
||||
// Connect the first reroute of the link being dragged to the reroute being dropped on
|
||||
if (fromReroute) {
|
||||
fromReroute.parentId = reroute.id
|
||||
} else {
|
||||
// If there are no reroutes, directly connect the link
|
||||
this.link.parentId = reroute.id
|
||||
}
|
||||
// Use the last reroute id on the link to retain all reroutes
|
||||
outputNode.connectSlots(output, inputNode, inputSlot, this.link.parentId)
|
||||
|
||||
// Connecting from the final reroute of a floating reroute chain
|
||||
if (floatingTerminus) reroute.removeAllFloatingLinks()
|
||||
|
||||
events.dispatch("output-moved", this)
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ export class ToInputRenderLink implements RenderLink {
|
||||
: this.node.getOutputPos(outputIndex)
|
||||
}
|
||||
|
||||
canConnectToInput(inputNode: LGraphNode, input: INodeInputSlot): this is this {
|
||||
canConnectToInput(inputNode: LGraphNode, input: INodeInputSlot): boolean {
|
||||
return this.node.canConnectTo(inputNode, input, this.fromSlot)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export class ToOutputRenderLink implements RenderLink {
|
||||
return false
|
||||
}
|
||||
|
||||
canConnectToOutput(outputNode: LGraphNode, output: INodeOutputSlot): this is this {
|
||||
canConnectToOutput(outputNode: LGraphNode, output: INodeOutputSlot): boolean {
|
||||
return this.node.canConnectTo(outputNode, this.fromSlot, output)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { FloatingRenderLink } from "@/canvas/FloatingRenderLink"
|
||||
import type { MovingRenderLink } from "@/canvas/MovingRenderLink"
|
||||
import type { MovingInputLink } from "@/canvas/MovingInputLink"
|
||||
import type { MovingOutputLink } from "@/canvas/MovingOutputLink"
|
||||
import type { RenderLink } from "@/canvas/RenderLink"
|
||||
import type { ToInputRenderLink } from "@/canvas/ToInputRenderLink"
|
||||
import type { LGraphNode } from "@/LGraphNode"
|
||||
@@ -20,11 +21,11 @@ export interface LinkConnectorEventMap {
|
||||
event: CanvasPointerEvent
|
||||
}
|
||||
|
||||
"before-move-input": MovingRenderLink | FloatingRenderLink
|
||||
"before-move-output": MovingRenderLink | FloatingRenderLink
|
||||
"before-move-input": MovingInputLink | FloatingRenderLink
|
||||
"before-move-output": MovingOutputLink | FloatingRenderLink
|
||||
|
||||
"input-moved": MovingRenderLink | FloatingRenderLink
|
||||
"output-moved": MovingRenderLink | FloatingRenderLink
|
||||
"input-moved": MovingInputLink | FloatingRenderLink
|
||||
"output-moved": MovingOutputLink | FloatingRenderLink
|
||||
|
||||
"link-created": LLink | null | undefined
|
||||
|
||||
|
||||
Reference in New Issue
Block a user