Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions browser_tests/tests/vueNodes/nodeStates/bypass.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ test.describe('Vue Node Bypass', () => {

const checkpointNode = comfyPage.vueNodes.getNodeByTitle('Load Checkpoint')
await expect(checkpointNode).toHaveClass(BYPASS_CLASS)
await expect(comfyPage.canvas).toHaveScreenshot(
'vue-node-bypassed-state.png'
)

await comfyPage.page.keyboard.press(BYPASS_HOTKEY)
await expect(checkpointNode).not.toHaveClass(BYPASS_CLASS)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 8 additions & 7 deletions browser_tests/tests/vueNodes/nodeStates/mute.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '../../../fixtures/ComfyPage'

const MUTE_HOTKEY = 'Control+m'
const MUTE_CLASS = /opacity-50/
const MUTE_OPACITY = '0.5'

test.describe('Vue Node Mute', () => {
test.beforeEach(async ({ comfyPage }) => {
Expand All @@ -19,10 +19,11 @@ test.describe('Vue Node Mute', () => {
await comfyPage.page.keyboard.press(MUTE_HOTKEY)

const checkpointNode = comfyPage.vueNodes.getNodeByTitle('Load Checkpoint')
await expect(checkpointNode).toHaveClass(MUTE_CLASS)
await expect(checkpointNode).toHaveCSS('opacity', MUTE_OPACITY)
await expect(comfyPage.canvas).toHaveScreenshot('vue-node-muted-state.png')

await comfyPage.page.keyboard.press(MUTE_HOTKEY)
await expect(checkpointNode).not.toHaveClass(MUTE_CLASS)
await expect(checkpointNode).not.toHaveCSS('opacity', MUTE_OPACITY)
})

test('should allow toggling mute on multiple selected nodes with hotkey', async ({
Expand All @@ -35,11 +36,11 @@ test.describe('Vue Node Mute', () => {
const ksamplerNode = comfyPage.vueNodes.getNodeByTitle('KSampler')

await comfyPage.page.keyboard.press(MUTE_HOTKEY)
await expect(checkpointNode).toHaveClass(MUTE_CLASS)
await expect(ksamplerNode).toHaveClass(MUTE_CLASS)
await expect(checkpointNode).toHaveCSS('opacity', MUTE_OPACITY)
await expect(ksamplerNode).toHaveCSS('opacity', MUTE_OPACITY)

await comfyPage.page.keyboard.press(MUTE_HOTKEY)
await expect(checkpointNode).not.toHaveClass(MUTE_CLASS)
await expect(ksamplerNode).not.toHaveClass(MUTE_CLASS)
await expect(checkpointNode).not.toHaveCSS('opacity', MUTE_OPACITY)
await expect(ksamplerNode).not.toHaveCSS('opacity', MUTE_OPACITY)
})
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 13 additions & 12 deletions src/renderer/extensions/vueNodes/components/LGraphNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
outlineClass,
{
'animate-pulse': executing,
'opacity-50 before:rounded-2xl before:pointer-events-none before:absolute before:bg-bypass/60 before:inset-0':
'before:rounded-2xl before:pointer-events-none before:absolute before:bg-bypass/60 before:inset-0':
bypassed,
'opacity-50 before:rounded-2xl before:pointer-events-none before:absolute before:inset-0':
'before:rounded-2xl before:pointer-events-none before:absolute before:inset-0':
muted,
'will-change-transform': isDragging
},
Expand Down Expand Up @@ -174,26 +174,20 @@ const {

useVueElementTracking(() => nodeData.id, 'node')

const { selectedNodeIds } = storeToRefs(useCanvasStore())

// Inject transform state for coordinate conversion
const transformState = inject(TransformStateKey)
if (!transformState) {
throw new Error(
'TransformState must be provided for node resize functionality'
)
}

// Computed selection state - only this node re-evaluates when its selection changes
const { selectedNodeIds } = storeToRefs(useCanvasStore())
const isSelected = computed(() => {
return selectedNodeIds.value.has(nodeData.id)
})

// Use execution state composable
const nodeLocatorId = computed(() => getLocatorIdFromNodeData(nodeData))
const { executing, progress } = useNodeExecutionState(nodeLocatorId)

// Direct access to execution store for error state
const executionStore = useExecutionStore()
const hasExecutionError = computed(
() => executionStore.lastExecutionErrorNodeId === nodeData.id
Expand Down Expand Up @@ -225,9 +219,16 @@ const nodeBodyBackgroundColor = computed(() => {
)
})

const nodeOpacity = computed(
() => useSettingStore().get('Comfy.Node.Opacity') ?? 1
)
const nodeOpacity = computed(() => {
const globalOpacity = useSettingStore().get('Comfy.Node.Opacity') ?? 1

// For muted/bypassed nodes, apply the 0.5 multiplier on top of global opacity
if (bypassed.value || muted.value) {
return globalOpacity * 0.5
}

return globalOpacity
})

// Use canvas interactions for proper wheel event handling and pointer event capture control
const { handleWheel, shouldHandleNodePointerEvents } = useCanvasInteractions()
Expand Down