diff --git a/browser_tests/interaction.spec.ts b/browser_tests/interaction.spec.ts index 1107e490..c2e7803d 100644 --- a/browser_tests/interaction.spec.ts +++ b/browser_tests/interaction.spec.ts @@ -158,6 +158,16 @@ test.describe('Node Interaction', () => { }) expect(await comfyPage.page.locator('.node-title-editor').count()).toBe(0) }) + + test('Can group selected nodes', async ({ comfyPage }) => { + await comfyPage.setSetting('Comfy.GroupSelectedNodes.Padding', 10) + await comfyPage.select2Nodes() + await comfyPage.page.keyboard.down('Control') + await comfyPage.page.keyboard.press('KeyG') + await comfyPage.page.keyboard.up('Control') + await comfyPage.nextFrame() + await expect(comfyPage.canvas).toHaveScreenshot('group-selected-nodes.png') + }) }) test.describe('Canvas Interaction', () => { diff --git a/browser_tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png new file mode 100644 index 00000000..b97313de Binary files /dev/null and b/browser_tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png differ diff --git a/package-lock.json b/package-lock.json index 630c29be..f5e518d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.2.38", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.2.1", - "@comfyorg/litegraph": "^0.7.52", + "@comfyorg/litegraph": "^0.7.54", "@primevue/themes": "^4.0.0-rc.2", "@vitejs/plugin-vue": "^5.0.5", "@vueuse/core": "^11.0.0", @@ -1881,9 +1881,9 @@ "dev": true }, "node_modules/@comfyorg/litegraph": { - "version": "0.7.52", - "resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.7.52.tgz", - "integrity": "sha512-MtJn4VH3eaP4XYfLQVrc00vJGamOfl5a5xMRJpW8tfPO2iPaetshoB9dkDfNJ6fSolzMt24qvZttkPdh2aNR1Q==", + "version": "0.7.54", + "resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.7.54.tgz", + "integrity": "sha512-nbd68LCFurokYmtq9c/fA9iIRRXAykDqKkAjAle33JlTU6FOr5FrZvg+VmHEk0YbxMTx7WB+4GGHBaaTJdMN9A==", "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { diff --git a/package.json b/package.json index c2085bdf..b008e66d 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ }, "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.2.1", - "@comfyorg/litegraph": "^0.7.52", + "@comfyorg/litegraph": "^0.7.54", "@primevue/themes": "^4.0.0-rc.2", "@vitejs/plugin-vue": "^5.0.5", "@vueuse/core": "^11.0.0", diff --git a/src/extensions/core/keybinds.ts b/src/extensions/core/keybinds.ts index 3177a506..4804819b 100644 --- a/src/extensions/core/keybinds.ts +++ b/src/extensions/core/keybinds.ts @@ -40,7 +40,8 @@ app.registerExtension({ s: '#comfy-save-button', o: '#comfy-file-input', Backspace: '#comfy-clear-button', - d: '#comfy-load-default-button' + d: '#comfy-load-default-button', + g: '#comfy-group-selected-nodes-button' } const modifierKeybindId = modifierKeyIdMap[event.key] diff --git a/src/scripts/app.ts b/src/scripts/app.ts index 84fe08c2..0c91e8fa 100644 --- a/src/scripts/app.ts +++ b/src/scripts/app.ts @@ -53,6 +53,7 @@ import { useSettingStore } from '@/stores/settingStore' import { useToastStore } from '@/stores/toastStore' import type { ToastMessageOptions } from 'primevue/toast' import { useWorkspaceStore } from '@/stores/workspaceStateStore' +import { LGraphGroup } from '@comfyorg/litegraph' export const ANIM_PREVIEW_WIDGET = '$$comfy_animation_preview' diff --git a/src/scripts/ui.ts b/src/scripts/ui.ts index dfb3d694..18f5e07b 100644 --- a/src/scripts/ui.ts +++ b/src/scripts/ui.ts @@ -5,6 +5,9 @@ import { ComfySettingsDialog } from './ui/settings' import { ComfyApp, app } from './app' import { TaskItem } from '@/types/apiTypes' import { showSettingsDialog } from '@/services/dialogService' +import { useToastStore } from '@/stores/toastStore' +import { LGraphGroup } from '@comfyorg/litegraph' +import { useSettingStore } from '@/stores/settingStore' export const ComfyDialog = _ComfyDialog @@ -756,6 +759,31 @@ export class ComfyUI { onclick: async () => { app.resetView() } + }), + $el('button', { + id: 'comfy-group-selected-nodes-button', + textContent: 'Group', + hidden: true, + onclick: () => { + if ( + !app.canvas.selected_nodes || + Object.keys(app.canvas.selected_nodes).length === 0 + ) { + useToastStore().add({ + severity: 'error', + summary: 'No nodes selected', + detail: 'Please select nodes to group', + life: 3000 + }) + return + } + const group = new LGraphGroup() + const padding = useSettingStore().get( + 'Comfy.GroupSelectedNodes.Padding' + ) + group.addNodes(Object.values(app.canvas.selected_nodes), padding) + app.canvas.graph.add(group) + } }) ]) as HTMLDivElement diff --git a/src/scripts/ui/menu/index.ts b/src/scripts/ui/menu/index.ts index ebc66666..a9f3b774 100644 --- a/src/scripts/ui/menu/index.ts +++ b/src/scripts/ui/menu/index.ts @@ -88,6 +88,7 @@ export class ComfyAppMenu { app }) ) + this.actionsGroup = new ComfyButtonGroup( new ComfyButton({ icon: 'refresh', diff --git a/src/stores/settingStore.ts b/src/stores/settingStore.ts index a3cc70a4..83fcd0da 100644 --- a/src/stores/settingStore.ts +++ b/src/stores/settingStore.ts @@ -241,6 +241,17 @@ export const useSettingStore = defineStore('setting', { type: 'hidden', defaultValue: ['.safetensors', '.sft'] }) + + app.ui.settings.addSetting({ + id: 'Comfy.GroupSelectedNodes.Padding', + name: 'Group selected nodes padding', + type: 'slider', + defaultValue: 10, + attrs: { + min: 0, + max: 100 + } + }) }, set(key: K, value: Settings[K]) {