mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 03:01:54 +00:00
Litegraph Reroute Beta (#1421)
* Add Reroute support - ConnectingLinkImpl Bonus: TS strict * Add Reroute support * Remove unused TS expect error * Add reroute beta opt-in option * Add settings option: Middle-click reroute node * Add settings: Link Markers * Move settings * Update litegraph --------- Co-authored-by: huchenlei <huchenlei@proton.me>
This commit is contained in:
8
package-lock.json
generated
8
package-lock.json
generated
@@ -10,7 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
|
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
|
||||||
"@comfyorg/comfyui-electron-types": "^0.2.10",
|
"@comfyorg/comfyui-electron-types": "^0.2.10",
|
||||||
"@comfyorg/litegraph": "^0.8.25",
|
"@comfyorg/litegraph": "^0.8.26",
|
||||||
"@primevue/themes": "^4.0.5",
|
"@primevue/themes": "^4.0.5",
|
||||||
"@vueuse/core": "^11.0.0",
|
"@vueuse/core": "^11.0.0",
|
||||||
"@xterm/addon-fit": "^0.10.0",
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
@@ -1922,9 +1922,9 @@
|
|||||||
"license": "GPL-3.0-only"
|
"license": "GPL-3.0-only"
|
||||||
},
|
},
|
||||||
"node_modules/@comfyorg/litegraph": {
|
"node_modules/@comfyorg/litegraph": {
|
||||||
"version": "0.8.25",
|
"version": "0.8.26",
|
||||||
"resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.8.25.tgz",
|
"resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.8.26.tgz",
|
||||||
"integrity": "sha512-VYMpxNLAwLgmT1mFX77RNA3O5KavhWBmYJpb3+BLW6BwmnDCd0QHX9gy5IFsGSpQP28k2lWgANIcGZF2Ev2eqg==",
|
"integrity": "sha512-q0Vcd5usphR5nghfyFksVx+VM+eSB1MyX8Ne304KFDnr214KQMA6DAjrEQJlGBUUCybLiOtPCvd3dxPecEQiSQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@cspotcode/source-map-support": {
|
"node_modules/@cspotcode/source-map-support": {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
|
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
|
||||||
"@comfyorg/comfyui-electron-types": "^0.2.10",
|
"@comfyorg/comfyui-electron-types": "^0.2.10",
|
||||||
"@comfyorg/litegraph": "^0.8.25",
|
"@comfyorg/litegraph": "^0.8.26",
|
||||||
"@primevue/themes": "^4.0.5",
|
"@primevue/themes": "^4.0.5",
|
||||||
"@vueuse/core": "^11.0.0",
|
"@vueuse/core": "^11.0.0",
|
||||||
"@xterm/addon-fit": "^0.10.0",
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
|
|||||||
@@ -104,6 +104,12 @@ watchEffect(() => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
LiteGraph.middle_click_slot_add_default_node = settingStore.get(
|
||||||
|
'Comfy.Node.MiddleClickRerouteNode'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
nodeDefStore.showDeprecated = settingStore.get('Comfy.Node.ShowDeprecated')
|
nodeDefStore.showDeprecated = settingStore.get('Comfy.Node.ShowDeprecated')
|
||||||
})
|
})
|
||||||
@@ -134,6 +140,24 @@ watchEffect(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
const linkMarkerShape = settingStore.get('Comfy.Graph.LinkMarkers')
|
||||||
|
const { canvas } = canvasStore
|
||||||
|
if (canvas) {
|
||||||
|
canvas.linkMarkerShape = linkMarkerShape
|
||||||
|
canvas.setDirty(false, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
const reroutesEnabled = settingStore.get('Comfy.RerouteBeta')
|
||||||
|
const { canvas } = canvasStore
|
||||||
|
if (canvas) {
|
||||||
|
canvas.reroutesEnabled = reroutesEnabled
|
||||||
|
canvas.setDirty(false, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (!canvasStore.canvas) return
|
if (!canvasStore.canvas) return
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ const getNewNodeLocation = (): [number, number] => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const originalEvent = triggerEvent.value.detail.originalEvent
|
const originalEvent = triggerEvent.value.detail.originalEvent
|
||||||
// @ts-expect-error LiteGraph types are not typed
|
|
||||||
return [originalEvent.canvasX, originalEvent.canvasY]
|
return [originalEvent.canvasX, originalEvent.canvasY]
|
||||||
}
|
}
|
||||||
const nodeFilters = ref<FilterAndValue[]>([])
|
const nodeFilters = ref<FilterAndValue[]>([])
|
||||||
@@ -153,8 +152,16 @@ const showContextMenu = (e: LiteGraphCanvasEvent) => {
|
|||||||
showSearchBox: () => showSearchBox(e)
|
showSearchBox: () => showSearchBox(e)
|
||||||
}
|
}
|
||||||
const connectionOptions = firstLink.output
|
const connectionOptions = firstLink.output
|
||||||
? { nodeFrom: firstLink.node, slotFrom: firstLink.output }
|
? {
|
||||||
: { nodeTo: firstLink.node, slotTo: firstLink.input }
|
nodeFrom: firstLink.node,
|
||||||
|
slotFrom: firstLink.output,
|
||||||
|
afterRerouteId: firstLink.afterRerouteId
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
nodeTo: firstLink.node,
|
||||||
|
slotTo: firstLink.input,
|
||||||
|
afterRerouteId: firstLink.afterRerouteId
|
||||||
|
}
|
||||||
canvasStore.canvas.showConnectionMenu({
|
canvasStore.canvas.showConnectionMenu({
|
||||||
...connectionOptions,
|
...connectionOptions,
|
||||||
...commonOptions
|
...commonOptions
|
||||||
@@ -178,7 +185,6 @@ const canvasEventHandler = (e: LiteGraphCanvasEvent) => {
|
|||||||
} else if (e.detail.subType === 'group-double-click') {
|
} else if (e.detail.subType === 'group-double-click') {
|
||||||
const group = e.detail.group
|
const group = e.detail.group
|
||||||
const [x, y] = group.pos
|
const [x, y] = group.pos
|
||||||
// @ts-expect-error LiteGraphCanvasEvent is not typed
|
|
||||||
const relativeY = e.detail.originalEvent.canvasY - y
|
const relativeY = e.detail.originalEvent.canvasY - y
|
||||||
// Show search box if the click is NOT on the title bar
|
// Show search box if the click is NOT on the title bar
|
||||||
if (relativeY > group.titleHeight) {
|
if (relativeY > group.titleHeight) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
LinkReleaseTriggerMode
|
LinkReleaseTriggerMode
|
||||||
} from '@/types/searchBoxTypes'
|
} from '@/types/searchBoxTypes'
|
||||||
import type { SettingParams } from '@/types/settingTypes'
|
import type { SettingParams } from '@/types/settingTypes'
|
||||||
|
import { LinkMarkerShape } from '@comfyorg/litegraph'
|
||||||
import { LiteGraph } from '@comfyorg/litegraph'
|
import { LiteGraph } from '@comfyorg/litegraph'
|
||||||
|
|
||||||
export const CORE_SETTINGS: SettingParams[] = [
|
export const CORE_SETTINGS: SettingParams[] = [
|
||||||
@@ -484,5 +485,34 @@ export const CORE_SETTINGS: SettingParams[] = [
|
|||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
versionAdded: '1.3.40'
|
versionAdded: '1.3.40'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Comfy.Node.MiddleClickRerouteNode',
|
||||||
|
name: 'Middle-click creates a new Reroute node',
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: true,
|
||||||
|
versionAdded: '1.3.42'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Comfy.RerouteBeta',
|
||||||
|
name: 'Opt-in to the reroute beta test',
|
||||||
|
tooltip:
|
||||||
|
'Enables the new native reroutes.\n\nReroutes can be added by holding alt and dragging from a link line, or on the link menu.\n\nDisabling this option is non-destructive - reroutes are hidden.',
|
||||||
|
experimental: true,
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: false,
|
||||||
|
versionAdded: '1.3.42'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Comfy.Graph.LinkMarkers',
|
||||||
|
name: 'Link midpoint markers',
|
||||||
|
defaultValue: LinkMarkerShape.Circle,
|
||||||
|
type: 'combo',
|
||||||
|
options: [
|
||||||
|
{ value: LinkMarkerShape.None, text: 'None' },
|
||||||
|
{ value: LinkMarkerShape.Circle, text: 'Circle' },
|
||||||
|
{ value: LinkMarkerShape.Arrow, text: 'Arrow' }
|
||||||
|
],
|
||||||
|
versionAdded: '1.3.42'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,35 +1,24 @@
|
|||||||
// @ts-strict-ignore
|
|
||||||
import type {
|
import type {
|
||||||
ConnectingLink,
|
ConnectingLink,
|
||||||
LGraphNode,
|
LGraphNode,
|
||||||
Vector2,
|
Vector2,
|
||||||
INodeInputSlot,
|
INodeInputSlot,
|
||||||
INodeOutputSlot,
|
INodeOutputSlot,
|
||||||
INodeSlot
|
INodeSlot,
|
||||||
|
ISlotType
|
||||||
} from '@comfyorg/litegraph'
|
} from '@comfyorg/litegraph'
|
||||||
import type { ISlotType } from '@comfyorg/litegraph'
|
|
||||||
import { LiteGraph } from '@comfyorg/litegraph'
|
import { LiteGraph } from '@comfyorg/litegraph'
|
||||||
|
import { RerouteId } from '@comfyorg/litegraph/dist/Reroute'
|
||||||
|
|
||||||
export class ConnectingLinkImpl implements ConnectingLink {
|
export class ConnectingLinkImpl implements ConnectingLink {
|
||||||
node: LGraphNode
|
|
||||||
slot: number
|
|
||||||
input: INodeInputSlot | null
|
|
||||||
output: INodeOutputSlot | null
|
|
||||||
pos: Vector2
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
node: LGraphNode,
|
public node: LGraphNode,
|
||||||
slot: number,
|
public slot: number,
|
||||||
input: INodeInputSlot | null,
|
public input: INodeInputSlot | undefined,
|
||||||
output: INodeOutputSlot | null,
|
public output: INodeOutputSlot | undefined,
|
||||||
pos: Vector2
|
public pos: Vector2,
|
||||||
) {
|
public afterRerouteId?: RerouteId
|
||||||
this.node = node
|
) {}
|
||||||
this.slot = slot
|
|
||||||
this.input = input
|
|
||||||
this.output = output
|
|
||||||
this.pos = pos
|
|
||||||
}
|
|
||||||
|
|
||||||
static createFromPlainObject(obj: ConnectingLink) {
|
static createFromPlainObject(obj: ConnectingLink) {
|
||||||
return new ConnectingLinkImpl(
|
return new ConnectingLinkImpl(
|
||||||
@@ -37,12 +26,13 @@ export class ConnectingLinkImpl implements ConnectingLink {
|
|||||||
obj.slot,
|
obj.slot,
|
||||||
obj.input,
|
obj.input,
|
||||||
obj.output,
|
obj.output,
|
||||||
obj.pos
|
obj.pos,
|
||||||
|
obj.afterRerouteId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
get type(): ISlotType | null {
|
get type(): ISlotType | null {
|
||||||
const result = this.input ? this.input.type : this.output.type
|
const result = this.input ? this.input.type : this.output?.type ?? null
|
||||||
return result === -1 ? null : result
|
return result === -1 ? null : result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,9 +61,9 @@ export class ConnectingLinkImpl implements ConnectingLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.releaseSlotType === 'input') {
|
if (this.releaseSlotType === 'input') {
|
||||||
this.node.connect(this.slot, newNode, newNodeSlot)
|
this.node.connect(this.slot, newNode, newNodeSlot, this.afterRerouteId)
|
||||||
} else {
|
} else {
|
||||||
newNode.connect(newNodeSlot, this.node, this.slot)
|
newNode.connect(newNodeSlot, this.node, this.slot, this.afterRerouteId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user