fix: DO NOT MERGE: Try to fix the types, behavior is not correct

This commit is contained in:
DrJKL
2025-09-30 16:11:00 -07:00
parent 9a3545b42b
commit 78cbfd2a7a
10 changed files with 130 additions and 98 deletions

View File

@@ -220,7 +220,7 @@ export class DragAndScale {
* @param bounds The bounds to animate the view to, defined by a rectangle.
*/
animateToBounds(
bounds: Rect | Rectangle,
bounds: Readonly<Rect | Rectangle>,
setDirty: () => void,
{
duration = 350,

View File

@@ -4733,32 +4733,47 @@ export class LGraphCanvas
for (const renderLink of renderLinks) {
const {
fromSlot,
fromPos: pos,
fromDirection,
dragDirection
fromPos: pos
// fromDirection,
// dragDirection
} = renderLink
const connShape = fromSlot.shape
const connType = fromSlot.type
const colour = resolveConnectingLinkColor(connType)
const color = resolveConnectingLinkColor(connType)
// the connection being dragged by the mouse
if (this.linkRenderer) {
this.linkRenderer.renderDraggingLink(
ctx,
pos,
highlightPos,
colour,
fromDirection,
dragDirection,
{
...this.buildLinkRenderContext(),
linkMarkerShape: LinkMarkerShape.None
}
)
if (
this.linkRenderer &&
renderLink.fromSlotIndex !== undefined &&
renderLink.node !== undefined
) {
const { fromSlotIndex, node } = renderLink
if (
node instanceof LGraphNode &&
('link' in fromSlot || 'links' in fromSlot)
) {
this.linkRenderer.renderDraggingLink(
ctx,
node,
fromSlot,
fromSlotIndex,
highlightPos,
this.buildLinkRenderContext(),
{ fromInput: 'link' in fromSlot, color }
// pos,
// colour,
// fromDirection,
// dragDirection,
// {
// ...this.buildLinkRenderContext(),
// linkMarkerShape: LinkMarkerShape.None
// }
)
}
}
ctx.fillStyle = colour
ctx.fillStyle = color
ctx.beginPath()
if (connType === LiteGraph.EVENT || connShape === RenderShape.BOX) {
ctx.rect(pos[0] - 6 + 0.5, pos[1] - 5 + 0.5, 14, 10)

View File

@@ -1,4 +1,4 @@
import { Rectangle } from '@/lib/litegraph/src/infrastructure/Rectangle'
import type { Rectangle } from '@/lib/litegraph/src/infrastructure/Rectangle'
import type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'
import type { ContextMenu } from './ContextMenu'

View File

@@ -1,13 +1,15 @@
import type { LGraphCanvas } from '@/lib/litegraph/src/LGraphCanvas'
import type { RenderLink } from '@/lib/litegraph/src/canvas/RenderLink'
import type { ReadOnlyPoint } from '@/lib/litegraph/src/interfaces'
import { LinkDirection } from '@/lib/litegraph/src/types/globalEnums'
import { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
// import type { RenderLink } from '@/lib/litegraph/src/canvas/RenderLink'
import type { Point } from '@/lib/litegraph/src/interfaces'
// import { LinkDirection } from '@/lib/litegraph/src/types/globalEnums'
import { resolveConnectingLinkColor } from '@/lib/litegraph/src/utils/linkColors'
import { createLinkConnectorAdapter } from '@/renderer/core/canvas/links/linkConnectorAdapter'
import { useSlotLinkDragState } from '@/renderer/core/canvas/links/slotLinkDragState'
import type { LinkRenderContext } from '@/renderer/core/canvas/litegraph/litegraphLinkAdapter'
import { getSlotKey } from '@/renderer/core/layout/slots/slotIdentifier'
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
// import { getSlotKey } from '@/renderer/core/layout/slots/slotIdentifier'
// import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
function buildContext(canvas: LGraphCanvas): LinkRenderContext {
return {
@@ -49,24 +51,32 @@ export function attachSlotLinkPreviewRenderer(canvas: LGraphCanvas) {
const renderLinks = createLinkConnectorAdapter()?.renderLinks
if (!renderLinks || renderLinks.length === 0) return
const to: ReadOnlyPoint = [pointer.canvas.x, pointer.canvas.y]
const to: Point = [pointer.canvas.x, pointer.canvas.y]
ctx.save()
for (const link of renderLinks) {
const startDir = link.fromDirection ?? LinkDirection.RIGHT
const endDir = link.dragDirection ?? LinkDirection.CENTER
const colour = resolveConnectingLinkColor(link.fromSlot.type)
// const startDir = link.fromDirection ?? LinkDirection.RIGHT
// const endDir = link.dragDirection ?? LinkDirection.CENTER
const color = resolveConnectingLinkColor(link.fromSlot.type)
const fromPoint = resolveRenderLinkOrigin(link)
linkRenderer.renderDraggingLink(
ctx,
fromPoint,
to,
colour,
startDir,
endDir,
context
)
// const fromPoint = resolveRenderLinkOrigin(link)
const { node, fromSlot, fromSlotIndex } = link
if (node instanceof LGraphNode && 'link' in fromSlot) {
linkRenderer.renderDraggingLink(
ctx,
node,
fromSlot,
fromSlotIndex,
to,
context,
{
color
}
// colour,
// startDir,
// endDir,
// context
)
}
}
ctx.restore()
}
@@ -74,35 +84,35 @@ export function attachSlotLinkPreviewRenderer(canvas: LGraphCanvas) {
canvas.onDrawForeground = patched
}
function resolveRenderLinkOrigin(link: RenderLink): ReadOnlyPoint {
if (link.fromReroute) {
const rerouteLayout = layoutStore.getRerouteLayout(link.fromReroute.id)
if (rerouteLayout) {
return [rerouteLayout.position.x, rerouteLayout.position.y]
}
// function resolveRenderLinkOrigin(link: RenderLink): Point {
// if (link.fromReroute) {
// const rerouteLayout = layoutStore.getRerouteLayout(link.fromReroute.id)
// if (rerouteLayout) {
// return [rerouteLayout.position.x, rerouteLayout.position.y]
// }
const [x, y] = link.fromReroute.pos
return [x, y]
}
// const [x, y] = link.fromReroute.pos
// return [x, y]
// }
const nodeId = getRenderLinkNodeId(link)
if (nodeId != null) {
const isInputFrom = link.toType === 'output'
const key = getSlotKey(String(nodeId), link.fromSlotIndex, isInputFrom)
const layout = layoutStore.getSlotLayout(key)
if (layout) {
return [layout.position.x, layout.position.y]
}
}
// const nodeId = getRenderLinkNodeId(link)
// if (nodeId != null) {
// const isInputFrom = link.toType === 'output'
// const key = getSlotKey(String(nodeId), link.fromSlotIndex, isInputFrom)
// const layout = layoutStore.getSlotLayout(key)
// if (layout) {
// return [layout.position.x, layout.position.y]
// }
// }
return link.fromPos
}
// return link.fromPos
// }
function getRenderLinkNodeId(link: RenderLink): number | null {
const node = link.node
if (typeof node === 'object' && node !== null && 'id' in node) {
const maybeId = node.id
if (typeof maybeId === 'number') return maybeId
}
return null
}
// function getRenderLinkNodeId(link: RenderLink): number | null {
// const node = link.node
// if (typeof node === 'object' && node !== null && 'id' in node) {
// const maybeId = node.id
// if (typeof maybeId === 'number') return maybeId
// }
// return null
// }

View File

@@ -7,7 +7,7 @@
* Maintains backward compatibility with existing litegraph integration.
*/
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { LLink } from '@/lib/litegraph/src/LLink'
import type { LLink } from '@/lib/litegraph/src/LLink'
import type { Reroute } from '@/lib/litegraph/src/Reroute'
import type {
CanvasColour,
@@ -21,6 +21,7 @@ import {
LinkMarkerShape,
LinkRenderType
} from '@/lib/litegraph/src/types/globalEnums'
import { getSlotPosition } from '@/renderer/core/canvas/litegraph/slotCalculations'
import {
type ArrowShape,
CanvasPathRenderer,
@@ -411,7 +412,6 @@ export class LitegraphLinkAdapter {
const slotDir =
fromSlot.dir ||
(options.fromInput ? LinkDirection.LEFT : LinkDirection.RIGHT)
// Create drag data
const dragData: DragLinkData = {
fixedPoint: { x: slotPos[0], y: slotPos[1] },

View File

@@ -70,7 +70,7 @@ export interface RenderContext {
highlightedIds?: Set<string>
}
interface DragLinkData {
export interface DragLinkData {
/** Fixed end - the slot being dragged from */
fixedPoint: Point
fixedDirection: Direction
@@ -605,6 +605,7 @@ export class CanvasPathRenderer {
type: dragData.type,
disabled: dragData.disabled
}
console.log({ linkData })
// Use standard link drawing
return this.drawLink(ctx, linkData, context)

View File

@@ -42,7 +42,7 @@ import type {
INodeInputSlot,
INodeOutputSlot
} from '@/lib/litegraph/src/interfaces'
import { RenderShape } from '@/lib/litegraph/src/litegraph'
import { Rectangle, RenderShape } from '@/lib/litegraph/src/litegraph'
import NodeContent from '@/renderer/extensions/vueNodes/components/NodeContent.vue'
import NodeHeader from '@/renderer/extensions/vueNodes/components/NodeHeader.vue'
import NodeSlots from '@/renderer/extensions/vueNodes/components/NodeSlots.vue'
@@ -85,7 +85,7 @@ const nodeData = computed<VueNodeData>(() => {
name,
type: input.type,
shape: input.isOptional ? RenderShape.HollowCircle : undefined,
boundingRect: [0, 0, 0, 0],
boundingRect: new Rectangle(0, 0, 0, 0),
link: null
}))
@@ -94,13 +94,13 @@ const nodeData = computed<VueNodeData>(() => {
return {
name: output,
type: output,
boundingRect: [0, 0, 0, 0],
boundingRect: new Rectangle(0, 0, 0, 0),
links: []
}
}
return {
...output,
boundingRect: [0, 0, 0, 0],
boundingRect: new Rectangle(0, 0, 0, 0),
links: []
}
})

View File

@@ -7,6 +7,7 @@ import { createI18n } from 'vue-i18n'
import type { VueNodeData } from '@/composables/graph/useGraphNodeManager'
import type { INodeOutputSlot } from '@/lib/litegraph/src/interfaces'
import type { INodeInputSlot } from '@/lib/litegraph/src/interfaces'
import { Rectangle } from '@/lib/litegraph/src/litegraph'
import enMessages from '@/locales/en/main.json' with { type: 'json' }
import NodeSlots from './NodeSlots.vue'
@@ -29,7 +30,7 @@ const makeNodeData = (overrides: Partial<VueNodeData> = {}): VueNodeData => ({
interface StubSlotData {
name?: string
type?: string
boundingRect?: [number, number, number, number]
boundingRect?: Rectangle
}
const InputSlotStub = defineComponent({
@@ -96,13 +97,13 @@ describe('NodeSlots.vue', () => {
const inputObjNoWidget = {
name: 'objNoWidget',
type: 'number',
boundingRect: new Float32Array([0, 0, 0, 0]),
boundingRect: new Rectangle(0, 0, 0, 0),
link: null
}
const inputObjWithWidget = {
name: 'objWithWidget',
type: 'number',
boundingRect: new Float32Array([0, 0, 0, 0]),
boundingRect: new Rectangle(0, 0, 0, 0),
widget: { name: 'objWithWidget' },
link: null
}
@@ -150,13 +151,13 @@ describe('NodeSlots.vue', () => {
const outputObj = {
name: 'outA',
type: 'any',
boundingRect: new Float32Array([0, 0, 0, 0]),
boundingRect: new Rectangle(0, 0, 0, 0),
links: []
}
const outputObjB = {
name: 'outB',
type: 'any',
boundingRect: new Float32Array([0, 0, 0, 0]),
boundingRect: new Rectangle(0, 0, 0, 0),
links: []
}
const outputs: INodeOutputSlot[] = [outputObj, outputObjB]

View File

@@ -34,7 +34,7 @@ import { computed, onErrorCaptured, ref } from 'vue'
import type { VueNodeData } from '@/composables/graph/useGraphNodeManager'
import { useErrorHandling } from '@/composables/useErrorHandling'
import type { INodeSlot } from '@/lib/litegraph/src/litegraph'
import { type INodeSlot, Rectangle } from '@/lib/litegraph/src/litegraph'
import { isSlotObject } from '@/utils/typeGuardUtil'
import InputSlot from './InputSlot.vue'
@@ -60,28 +60,30 @@ const filteredInputs = computed(() => {
}
return true
})
.map((input) =>
isSlotObject(input)
? input
: ({
name: typeof input === 'string' ? input : '',
type: 'any',
boundingRect: [0, 0, 0, 0] as [number, number, number, number]
} as INodeSlot)
.map(
(input): INodeSlot =>
isSlotObject(input)
? input
: {
name: typeof input === 'string' ? input : '',
type: 'any',
boundingRect: new Rectangle(0, 0, 0, 0)
}
)
})
// Outputs don't have widgets, so we don't need to filter them
const filteredOutputs = computed(() => {
const outputs = nodeData?.outputs || []
return outputs.map((output) =>
isSlotObject(output)
? output
: ({
name: typeof output === 'string' ? output : '',
type: 'any',
boundingRect: [0, 0, 0, 0] as [number, number, number, number]
} as INodeSlot)
return outputs.map(
(output): INodeSlot =>
isSlotObject(output)
? output
: {
name: typeof output === 'string' ? output : '',
type: 'any',
boundingRect: new Rectangle(0, 0, 0, 0)
}
)
})

View File

@@ -30,7 +30,7 @@
:slot-data="{
name: widget.name,
type: widget.type,
boundingRect: [0, 0, 0, 0]
boundingRect
}"
:node-id="nodeData?.id != null ? String(nodeData.id) : ''"
:index="getWidgetInputIndex(widget)"
@@ -60,6 +60,7 @@ import type {
VueNodeData
} from '@/composables/graph/useGraphNodeManager'
import { useErrorHandling } from '@/composables/useErrorHandling'
import { Rectangle } from '@/lib/litegraph/src/litegraph'
import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions'
import { useNodeTooltips } from '@/renderer/extensions/vueNodes/composables/useNodeTooltips'
// Import widget components directly
@@ -164,6 +165,8 @@ const processedWidgets = computed((): ProcessedWidget[] => {
return result
})
const boundingRect = new Rectangle(0, 0, 0, 0)
// TODO: Refactor to avoid O(n) lookup - consider storing input index on widget creation
// or restructuring data model to unify widgets and inputs
// Map a widget to its corresponding input slot index