Update Litegraph: Canvas Pointer (#1556)

* Litegraph: canvas.pointer

Clear @ts-expect-error

Fix exception thrown on slot double-click

Long-standing bug but has no real impact in prod - just logs an error.
Required for new connecting_link features.

Add settings: CanvasPointer options

Update litegraph 0.8.28

Fix regression in snap to grid render

Fix snap to grid marker always on

Update snap to grid to use Positionable API

Fix test clicks registering as double-click

Improve test precision

Current test proves it has changed to something smaller.
New test proves it is exactly what was specified.
Will need refinement when a limit is put on latent width.

Fix test expects collapse node to select node

Remove redundant code

Resolved by CanvasPointer

Fix flaky test - ContextMenu

Fix settings group

* Update litegraph

* Remove snapToGrid extension

* Update test expectations [skip ci]

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
filtered
2024-11-19 02:50:51 +11:00
committed by GitHub
parent 2a93f873b4
commit 7e245ba1cf
29 changed files with 125 additions and 64 deletions

View File

@@ -62,6 +62,7 @@ test.describe('Change Tracker', () => {
expect(await getRedoQueueSize()).toBe(0)
const node = (await comfyPage.getFirstNodeRef())!
await node.click('title')
await node.click('collapse')
await expect(node).toBeCollapsed()
expect(await isModified()).toBe(true)
@@ -98,6 +99,7 @@ test.describe('Change Tracker', () => {
// Make changes outside set
// Bypass + collapse node
await node.click('title')
await node.click('collapse')
await comfyPage.ctrlB()
await expect(node).toBeCollapsed()
@@ -111,6 +113,10 @@ test.describe('Change Tracker', () => {
await expect(node).not.toBeBypassed()
await expect(node).not.toBeCollapsed()
// Prevent clicks registering a double-click
await comfyPage.clickEmptySpace()
await node.click('title')
// Run again, but within a change transaction
await beforeChange(comfyPage)
@@ -152,6 +158,7 @@ test.describe('Change Tracker', () => {
const multipleChanges = async () => {
await beforeChange(comfyPage)
// Call other actions that uses begin/endChange
await node.click('title')
await collapse()
await bypassAndPin()
await afterChange(comfyPage)

View File

@@ -24,14 +24,6 @@ test.describe('Copy Paste', () => {
test('Can copy and paste widget value', async ({ comfyPage }) => {
// Copy width value (512) from empty latent node to KSampler's seed.
// Empty latent node's width
await comfyPage.canvas.click({
position: {
x: 718,
y: 643
}
})
await comfyPage.ctrlC(null)
// KSampler's seed
await comfyPage.canvas.click({
position: {
@@ -39,6 +31,14 @@ test.describe('Copy Paste', () => {
y: 281
}
})
await comfyPage.ctrlC(null)
// Empty latent node's width
await comfyPage.canvas.click({
position: {
x: 718,
y: 643
}
})
await comfyPage.ctrlV(null)
await comfyPage.page.keyboard.press('Enter')
await expect(comfyPage.canvas).toHaveScreenshot('copied-widget-value.png')

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

@@ -526,9 +526,6 @@ export class ComfyPage {
safeSpot = safeSpot || { x: 10, y: 10 }
await this.page.mouse.move(safeSpot.x, safeSpot.y)
await this.page.mouse.down()
// TEMPORARY HACK: Multiple pans open the search menu, so cheat and keep it closed.
// TODO: Fix that (double-click at not-the-same-coordinations should not open the menu)
await this.page.keyboard.press('Escape')
await this.page.mouse.move(offset.x + safeSpot.x, offset.y + safeSpot.y)
await this.page.mouse.up()
await this.nextFrame()
@@ -557,6 +554,11 @@ export class ComfyPage {
await this.nextFrame()
}
async clickContextMenuItem(name: string): Promise<void> {
await this.page.getByRole('menuitem', { name }).click()
await this.nextFrame()
}
async doubleClickCanvas() {
await this.page.mouse.dblclick(10, 10, { delay: 5 })
await this.nextFrame()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View File

@@ -36,7 +36,7 @@ test.describe('Canvas Right Click Menu', () => {
await dialog.accept('GroupNode2CLIP')
})
await comfyPage.rightClickCanvas()
await comfyPage.page.getByText('Convert to Group Node').click()
await comfyPage.clickContextMenuItem('Convert to Group Node')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot(
'right-click-node-group-node.png'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 98 KiB

8
package-lock.json generated
View File

@@ -10,7 +10,7 @@
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
"@comfyorg/comfyui-electron-types": "^0.2.16",
"@comfyorg/litegraph": "^0.8.27",
"@comfyorg/litegraph": "^0.8.29",
"@primevue/themes": "^4.0.5",
"@vueuse/core": "^11.0.0",
"@xterm/addon-fit": "^0.10.0",
@@ -1923,9 +1923,9 @@
"license": "GPL-3.0-only"
},
"node_modules/@comfyorg/litegraph": {
"version": "0.8.27",
"resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.8.27.tgz",
"integrity": "sha512-EMQ3jsny+3gUQL4+vSVwJAFxrLq4IpuyjCvAiErLY4wLZZu2Mi+7cELmhrNS0MajhZqfN1M0GPmdcBRwSWbarw==",
"version": "0.8.29",
"resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.8.29.tgz",
"integrity": "sha512-h7c+sW/BEAPfWSDYATNk2YtB1kduQ0v85z2Rq8q11UoLHRkTa0A1zosDFSwIdCul/prdG51wbXr99EHq3Dsfnw==",
"license": "MIT"
},
"node_modules/@cspotcode/source-map-support": {

View File

@@ -73,7 +73,7 @@
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
"@comfyorg/comfyui-electron-types": "^0.2.16",
"@comfyorg/litegraph": "^0.8.27",
"@comfyorg/litegraph": "^0.8.29",
"@primevue/themes": "^4.0.5",
"@vueuse/core": "^11.0.0",
"@xterm/addon-fit": "^0.10.0",

View File

@@ -47,7 +47,8 @@ import {
DragAndScale,
LGraphCanvas,
ContextMenu,
LGraphBadge
LGraphBadge,
CanvasPointer
} from '@comfyorg/litegraph'
import type { RenderedTreeExplorerNode } from '@/types/treeExplorerTypes'
import { useCanvasStore } from '@/stores/graphStore'
@@ -162,6 +163,29 @@ watchEffect(() => {
}
})
watchEffect(() => {
CanvasPointer.doubleClickTime = settingStore.get(
'Comfy.Pointer.DoubleClickTime'
)
})
watchEffect(() => {
CanvasPointer.bufferTime = settingStore.get('Comfy.Pointer.ClickBufferTime')
})
watchEffect(() => {
CanvasPointer.maxClickDrift = settingStore.get('Comfy.Pointer.ClickDrift')
})
watchEffect(() => {
LiteGraph.CANVAS_GRID_SIZE = settingStore.get('Comfy.SnapToGrid.GridSize')
})
watchEffect(() => {
comfyApp.graph.config.alwaysSnapToGrid =
settingStore.get('pysssss.SnapToGrid')
})
watchEffect(() => {
if (!canvasStore.canvas) return

View File

@@ -15,7 +15,6 @@ import './rerouteNode'
import './saveImageExtraOutput'
import './simpleTouchSupport'
import './slotDefaults'
import './snapToGrid'
import './uploadImage'
import './webcamCapture'
import './widgetInputs'

View File

@@ -44,7 +44,7 @@ app.registerExtension({
lastTouch = getMultiTouchCenter(e)
touchDist = getMultiTouchPos(e)
app.canvas.pointer_is_down = false
app.canvas.pointer.isDown = false
}
}
},
@@ -78,7 +78,7 @@ app.registerExtension({
touchTime = null
if (e.touches?.length === 2 && lastTouch && !e.ctrlKey && !e.shiftKey) {
e.preventDefault() // Prevent browser from zooming when two textareas are touched
app.canvas.pointer_is_down = false
app.canvas.pointer.isDown = false
touchZooming = true
LiteGraph.closeAllContextMenus(window)
@@ -137,7 +137,7 @@ LGraphCanvas.prototype.processMouseDown = function (e) {
if (touchZooming || touchCount) {
return
}
app.canvas.pointer_is_down = false // Prevent context menu from opening on second tap
app.canvas.pointer.isDown = false // Prevent context menu from opening on second tap
return processMouseDown.apply(this, arguments)
}

View File

@@ -1,40 +0,0 @@
import { app } from '../../scripts/app'
import { LiteGraph } from '@comfyorg/litegraph'
app.registerExtension({
name: 'Comfy.SnapToGrid',
init() {
// Add setting to control grid size
app.ui.settings.addSetting({
id: 'Comfy.SnapToGrid.GridSize',
category: ['LiteGraph', 'Canvas', 'GridSize'],
name: 'Snap to grid size',
type: 'slider',
attrs: {
min: 1,
max: 500
},
tooltip:
'When dragging and resizing nodes while holding shift they will be aligned to the grid, this controls the size of that grid.',
defaultValue: LiteGraph.CANVAS_GRID_SIZE,
onChange(value) {
LiteGraph.CANVAS_GRID_SIZE = +value || 10
}
})
// Keep the 'pysssss.SnapToGrid' setting id so we don't need to migrate setting values.
// Using a new setting id can cause existing users to lose their existing settings.
app.ui.settings.addSetting({
id: 'pysssss.SnapToGrid',
category: ['LiteGraph', 'Canvas', 'AlwaysSnapToGrid'],
name: 'Always snap to grid',
type: 'boolean',
defaultValue: false,
versionAdded: '1.3.13',
versionModified: '1.3.42',
onChange(value) {
app.graph.config.alwaysSnapToGrid = !!value
}
})
}
})

View File

@@ -894,7 +894,7 @@ app.registerExtension({
// Not a widget input or already handled input
if (
!(input.type in ComfyWidgets) &&
!(input.widget[GET_CONFIG]?.()?.[0] instanceof Array)
!(input.widget?.[GET_CONFIG]?.()?.[0] instanceof Array)
) {
return r //also Not a ComfyWidgets input or combo (do nothing)
}

View File

@@ -1089,7 +1089,6 @@ export class ComfyApp {
'dragover',
(e) => {
this.canvas.adjustMouseEvent(e)
// @ts-expect-error: canvasX and canvasY are added by adjustMouseEvent in litegraph
const node = this.graph.getNodeOnPos(e.canvasX, e.canvasY)
if (node) {
// @ts-expect-error This is not a standard event. TODO fix it.

View File

@@ -535,5 +535,75 @@ export const CORE_SETTINGS: SettingParams[] = [
type: 'boolean',
defaultValue: true,
versionAdded: '1.4.0'
},
{
id: 'Comfy.Pointer.ClickDrift',
category: ['LiteGraph', 'Pointer', 'ClickDrift'],
name: 'Pointer click drift (maximum distance)',
tooltip:
'If the pointer moves more than this distance while holding a button down, it is considered dragging (rather than clicking).\n\nHelps prevent objects from being unintentionally nudged if the pointer is moved whilst clicking.',
experimental: true,
type: 'slider',
attrs: {
min: 0,
max: 20,
step: 1
},
defaultValue: 6,
versionAdded: '1.4.3'
},
{
id: 'Comfy.Pointer.ClickBufferTime',
category: ['LiteGraph', 'Pointer', 'ClickBufferTime'],
name: 'Pointer click drift delay',
tooltip:
'After pressing a pointer button down, this is the maximum time (in milliseconds) that pointer movement can be ignored for.\n\nHelps prevent objects from being unintentionally nudged if the pointer is moved whilst clicking.',
experimental: true,
type: 'slider',
attrs: {
min: 0,
max: 1000,
step: 25
},
defaultValue: 150,
versionAdded: '1.4.3'
},
{
id: 'Comfy.Pointer.DoubleClickTime',
category: ['LiteGraph', 'Pointer', 'DoubleClickTime'],
name: 'Double click interval (maximum)',
tooltip:
'The maximum time in milliseconds between the two clicks of a double-click. Increasing this value may assist if double-clicks are sometimes not registered.',
type: 'slider',
attrs: {
min: 100,
max: 1000,
step: 50
},
defaultValue: 300,
versionAdded: '1.4.3'
},
{
id: 'Comfy.SnapToGrid.GridSize',
category: ['LiteGraph', 'Canvas', 'GridSize'],
name: 'Snap to grid size',
type: 'slider',
attrs: {
min: 1,
max: 500
},
tooltip:
'When dragging and resizing nodes while holding shift they will be aligned to the grid, this controls the size of that grid.',
defaultValue: LiteGraph.CANVAS_GRID_SIZE
},
// Keep the 'pysssss.SnapToGrid' setting id so we don't need to migrate setting values.
// Using a new setting id can cause existing users to lose their existing settings.
{
id: 'pysssss.SnapToGrid',
category: ['LiteGraph', 'Canvas', 'AlwaysSnapToGrid'],
name: 'Always snap to grid',
type: 'boolean',
defaultValue: false,
versionAdded: '1.3.13'
}
]