Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CanvasPointer API #308

Merged
merged 41 commits into from
Nov 16, 2024
Merged

Add CanvasPointer API #308

merged 41 commits into from
Nov 16, 2024

Conversation

webfiltered
Copy link
Contributor

@webfiltered webfiltered commented Nov 15, 2024

Default behaviour changes

This is a fundamental change to the way Litegraph handles pointer interaction. Each pointer event is now tracked and managed by a CanvasPointer, created by the canvas as LGraphCanvas.pointer.

  • Dragging multiple items no longer requires that the shift key be held down
    • Clicking an item when multiple nodes / etc are selected will still deselect everything else
  • Clicking a connected link on an input no longer disconnects and reconnects it
  • Double-clicking requires that both clicks occur nearby
  • Makes adding an option (later) to customise what modifier keys do actually feasible

Bug fixes

  • Intermittent issue where clicking a node slightly displaces it
  • Alt-clicking to add a reroute creates two undo steps

For users, a lot of the change will be subtle, but it should "feel" more like a stable, native app. It should also result in fewer unexpected changes in the future.

For devs, the process to add / change click & drag actions has been drastically simplified.

Selecting multiple items

  • Ctrl + drag - Begin multi-select
  • Ctrl + Shift + drag - Add to selection
    • Ctrl + drag, Shift - Alternate add to selection
  • Ctrl + drag, Alt - Remove from selection

Click "drift"

A small amount of buffering is performed between down/up events to prevent accidental micro-drag events. If either of the two controls are exceeded, the event will be considered a drag event, not a click.

  • buffterTime is the maximum time that tiny movements can be ignored (Default: 150ms)
  • maxClickDrift controls how far a click can drift from its down event before it is considered a drag (Default: 6)

Double-click

When double clicking, the double click callback is executed shortly after one normal click callback (if present). At present, dragging from the second click simply invalidates the event - nothing will happen.

  • doubleClickTime is the maximum time between two down events for them to be considered a double click (Default: 300ms)
  • Distance between the two events must be less than 3 * maxClickDrift

Configuration

All above configuration is via class static. Could be converted to instance-based.

Implementing

Clicking, double-clicking, and dragging can now all be configured during the initial pointerdown event, and the correct callback(s) will be executed.

A click event can be as simple as:

if (node.isClickedInSpot(e.canvasX, e.canvasY)) this.pointer.onClick = () => node.gotClickInSpot()

Full usage can be seen in the old processMouseDown handler, which is still in place (several monkey patches in the wild).

Registering a click or drag event

Example usage:

const { pointer } = this
// Click / double click - executed on pointerup
pointer.onClick = (e) => node.executeClick(e)
pointer.onDoubleClick = node.gotDoubleClick

// Drag events - executed on pointermove
pointer.onDragStart = (e) => {
  node.isBeingDragged = true
  canvas.startedDragging(e)
}
pointer.onDrag = () => {}
// finally() is preferred where possible, as it is guaranteed to run
pointer.onDragEnd = () => {}

// Always run, regardless of outcome
pointer.finally = () => node.isBeingDragged = false

Hovering over

Adds API for downstream consumers to handle custom cursors. A bitwise enum of items,

type LGraphCanvasState = {
  /** If `true`, pointer move events will set the canvas cursor style. */
  shouldSetCursor: boolean,
  /** Bit flags indicating what is currently below the pointer. */
  hoveringOver: CanvasItem,
  ...
}

// Disable litegraph cursors
canvas.state.shouldSetCursor = false

// Checking state - bit operators
if (canvas.state.hoveringOver & CanvasItem.ResizeSe) element.style.cursor = 'se-resize'

Removed public interfaces

All are unused and incomplete. Have bugs beyond just typescript typing, and are (currently) not worth maintaining. If any of these features are desired down the track, they can be reimplemented.

  • Live mode
  • Subgraph
  • dragged_node

Replaces previous impls. which only worked on some items, and were triggered when unexpected e.g. clicking a node that hadn't been moved.

Update test expectations
Marks as deprecated
Add TS strict types
Add final click drag distance math
Add option to retain events
Unused, not maintained.
Remove live_mode reference
Incomplete impl. - unused.
Superceded by selectedItems
LGraphNode.getWidgetOnPos
- Rewrites most pointer handling to use CanvasPointer callbacks
- All callbacks are declared ahead of time during the initial pointerdown event, logically grouped together
- Drastically simplifies the alteration or creation of new click / drag interactions
- Click events are all clicks, rather than some processed on mouse down, others on mouse up

- Functions return instead of setting and repeatedly checking multiple state vars
- Removes all lines that needed THIRTEEN tab indents
Replaces original workarounds with final types
- Centralises cursor set behaviour
- Provides simple downstream override
@webfiltered webfiltered marked this pull request as ready for review November 16, 2024 15:39
@huchenlei
Copy link
Member

huchenlei commented Nov 16, 2024

Do note that dragged_node is being referenced in the snapToGrid code in the frontend, we need to get rid of that on merging the corresponding frontend PR.

@huchenlei huchenlei merged commit b29a32c into master Nov 16, 2024
2 checks passed
@huchenlei huchenlei deleted the canvas-pointer branch November 16, 2024 22:35
@webfiltered webfiltered added this to the Pointer API milestone Nov 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants