Manage app.ts litegraph keybindings (#1151)

* Manage app.ts litegraph keybindings

* nit
This commit is contained in:
Chenlei Hu
2024-10-07 16:50:58 -04:00
committed by GitHub
parent ff1ca268a4
commit cc17bee945
6 changed files with 159 additions and 77 deletions

View File

@@ -30,7 +30,7 @@ app.registerExtension({
const keybindingStore = useKeybindingStore()
const commandStore = useCommandStore()
const keybinding = keybindingStore.getKeybinding(keyCombo)
if (keybinding) {
if (keybinding && keybinding.targetSelector !== '#graph-canvas') {
await commandStore.execute(keybinding.commandId)
event.preventDefault()
return

View File

@@ -53,6 +53,8 @@ import { useWorkspaceStore } from '@/stores/workspaceStateStore'
import { useExecutionStore } from '@/stores/executionStore'
import { IWidget } from '@comfyorg/litegraph'
import { useExtensionStore } from '@/stores/extensionStore'
import { KeyComboImpl, useKeybindingStore } from '@/stores/keybindingStore'
import { useCommandStore } from '@/stores/commandStore'
export const ANIM_PREVIEW_WIDGET = '$$comfy_animation_preview'
@@ -1278,13 +1280,10 @@ export class ComfyApp {
/**
* Handle keypress
*
* Ctrl + M mute/unmute selected nodes
*/
#addProcessKeyHandler() {
const self = this
const origProcessKey = LGraphCanvas.prototype.processKey
LGraphCanvas.prototype.processKey = function (e) {
LGraphCanvas.prototype.processKey = function (e: KeyboardEvent) {
if (!this.graph) {
return
}
@@ -1296,54 +1295,11 @@ export class ComfyApp {
}
if (e.type == 'keydown' && !e.repeat) {
// Ctrl + M mute/unmute
if (e.key === 'm' && (e.metaKey || e.ctrlKey)) {
if (this.selected_nodes) {
for (var i in this.selected_nodes) {
if (this.selected_nodes[i].mode === 2) {
// never
this.selected_nodes[i].mode = 0 // always
} else {
this.selected_nodes[i].mode = 2 // never
}
}
}
block_default = true
}
// Ctrl + B bypass
if (e.key === 'b' && (e.metaKey || e.ctrlKey)) {
if (this.selected_nodes) {
for (var i in this.selected_nodes) {
if (this.selected_nodes[i].mode === 4) {
// never
this.selected_nodes[i].mode = 0 // always
} else {
this.selected_nodes[i].mode = 4 // never
}
}
}
block_default = true
}
// p pin/unpin
if (e.key === 'p') {
if (this.selected_nodes) {
for (const i in this.selected_nodes) {
const node = this.selected_nodes[i]
node.pin()
}
}
block_default = true
}
// Alt + C collapse/uncollapse
if (e.key === 'c' && e.altKey) {
if (this.selected_nodes) {
for (var i in this.selected_nodes) {
this.selected_nodes[i].collapse()
}
}
const keyCombo = KeyComboImpl.fromEvent(e)
const keybindingStore = useKeybindingStore()
const keybinding = keybindingStore.getKeybinding(keyCombo)
if (keybinding && keybinding.targetSelector === '#graph-canvas') {
useCommandStore().execute(keybinding.commandId)
block_default = true
}
@@ -1362,26 +1318,6 @@ export class ComfyApp {
// Trigger onPaste
return true
}
if (e.key === '+' && e.altKey) {
block_default = true
let scale = this.ds.scale * 1.1
this.ds.changeScale(scale, [
this.ds.element.width / 2,
this.ds.element.height / 2
])
this.graph.change()
}
if (e.key === '-' && e.altKey) {
block_default = true
let scale = (this.ds.scale * 1) / 1.1
this.ds.changeScale(scale, [
this.ds.element.width / 2,
this.ds.element.height / 2
])
this.graph.change()
}
}
this.graph.change()

View File

@@ -17,6 +17,7 @@ import { useTitleEditorStore } from './graphStore'
import { useErrorHandling } from '@/hooks/errorHooks'
import { useWorkflowStore } from './workflowStore'
import { type KeybindingImpl, useKeybindingStore } from './keybindingStore'
import { LGraphNode } from '@comfyorg/litegraph'
export interface ComfyCommand {
id: string
@@ -75,6 +76,28 @@ export class ComfyCommandImpl implements ComfyCommand {
const getTracker = () =>
app.workflowManager.activeWorkflow?.changeTracker ?? globalTracker
const getSelectedNodes = (): LGraphNode[] => {
const selectedNodes = app.canvas.selected_nodes
const result: LGraphNode[] = []
if (selectedNodes) {
for (const i in selectedNodes) {
const node = selectedNodes[i]
result.push(node)
}
}
return result
}
const toggleSelectedNodesMode = (mode: number) => {
getSelectedNodes().forEach((node) => {
if (node.mode === mode) {
node.mode = 0 // always
} else {
node.mode = mode
}
})
}
export const useCommandStore = defineStore('command', () => {
const settingStore = useSettingStore()
@@ -248,7 +271,11 @@ export const useCommandStore = defineStore('command', () => {
icon: 'pi pi-plus',
label: 'Zoom In',
function: () => {
app.canvas.ds.changeScale(app.canvas.ds.scale + 0.1)
const ds = app.canvas.ds
ds.changeScale(ds.scale * 1.1, [
ds.element.width / 2,
ds.element.height / 2
])
app.canvas.setDirty(true, true)
}
},
@@ -257,7 +284,11 @@ export const useCommandStore = defineStore('command', () => {
icon: 'pi pi-minus',
label: 'Zoom Out',
function: () => {
app.canvas.ds.changeScale(app.canvas.ds.scale - 0.1)
const ds = app.canvas.ds
ds.changeScale(ds.scale / 1.1, [
ds.element.width / 2,
ds.element.height / 2
])
app.canvas.setDirty(true, true)
}
},
@@ -365,6 +396,46 @@ export const useCommandStore = defineStore('command', () => {
function: () => {
useWorkflowStore().loadPreviousOpenedWorkflow()
}
},
{
id: 'Comfy.Canvas.ToggleSelectedNodes.Mute',
icon: 'pi pi-volume-off',
label: 'Mute/Unmute Selected Nodes',
versionAdded: '1.3.11',
function: () => {
toggleSelectedNodesMode(2) // muted
}
},
{
id: 'Comfy.Canvas.ToggleSelectedNodes.Bypass',
icon: 'pi pi-shield',
label: 'Bypass/Unbypass Selected Nodes',
versionAdded: '1.3.11',
function: () => {
toggleSelectedNodesMode(4) // bypassed
}
},
{
id: 'Comfy.Canvas.ToggleSelectedNodes.Pin',
icon: 'pi pi-pin',
label: 'Pin/Unpin Selected Nodes',
versionAdded: '1.3.11',
function: () => {
getSelectedNodes().forEach((node) => {
node.pin(!node.pinned)
})
}
},
{
id: 'Comfy.Canvas.ToggleSelectedNodes.Collapse',
icon: 'pi pi-minus',
label: 'Collapse/Expand Selected Nodes',
versionAdded: '1.3.11',
function: () => {
getSelectedNodes().forEach((node) => {
node.collapse()
})
}
}
]

View File

@@ -94,5 +94,71 @@ export const CORE_KEYBINDINGS: Keybinding[] = [
ctrl: true
},
commandId: 'Comfy.ShowSettingsDialog'
},
// For '=' both holding shift and not holding shift
{
combo: {
key: '=',
alt: true
},
commandId: 'Comfy.Canvas.ZoomIn',
targetSelector: '#graph-canvas'
},
{
combo: {
key: '+',
alt: true,
shift: true
},
commandId: 'Comfy.Canvas.ZoomIn',
targetSelector: '#graph-canvas'
},
// For number pad '+'
{
combo: {
key: '+',
alt: true
},
commandId: 'Comfy.Canvas.ZoomIn',
targetSelector: '#graph-canvas'
},
{
combo: {
key: '-',
alt: true
},
commandId: 'Comfy.Canvas.ZoomOut',
targetSelector: '#graph-canvas'
},
{
combo: {
key: 'p'
},
commandId: 'Comfy.Canvas.ToggleSelectedNodes.Pin',
targetSelector: '#graph-canvas'
},
{
combo: {
key: 'c',
alt: true
},
commandId: 'Comfy.Canvas.ToggleSelectedNodes.Collapse',
targetSelector: '#graph-canvas'
},
{
combo: {
key: 'b',
ctrl: true
},
commandId: 'Comfy.Canvas.ToggleSelectedNodes.Bypass',
targetSelector: '#graph-canvas'
},
{
combo: {
key: 'm',
ctrl: true
},
commandId: 'Comfy.Canvas.ToggleSelectedNodes.Mute',
targetSelector: '#graph-canvas'
}
]

View File

@@ -8,16 +8,20 @@ import type { ComfyExtension } from '@/types/comfy'
export class KeybindingImpl implements Keybinding {
commandId: string
combo: KeyComboImpl
targetSelector?: string
constructor(obj: Keybinding) {
this.commandId = obj.commandId
this.combo = new KeyComboImpl(obj.combo)
this.targetSelector = obj.targetSelector
}
equals(other: any): boolean {
if (toRaw(other) instanceof KeybindingImpl) {
return (
this.commandId === other.commandId && this.combo.equals(other.combo)
this.commandId === other.commandId &&
this.combo.equals(other.combo) &&
this.targetSelector === other.targetSelector
)
}
return false

View File

@@ -12,7 +12,12 @@ export const zKeyCombo = z.object({
// Keybinding schema
export const zKeybinding = z.object({
commandId: z.string(),
combo: zKeyCombo
combo: zKeyCombo,
// Optional target element CSS selector to limit keybinding to.
// Note: Currently only used to distinguish between global keybindings
// and litegraph canvas keybindings.
// Do NOT use this field in extensions as it has no effect.
targetSelector: z.string().optional()
})
// Infer types from schemas