diff --git a/src/store/utils/dimmingUtils.ts b/src/store/utils/dimmingUtils.ts index b1a834bc..d1e3229b 100644 --- a/src/store/utils/dimmingUtils.ts +++ b/src/store/utils/dimmingUtils.ts @@ -32,32 +32,46 @@ export function computeDimmedNodes( }); }); - // Step 2: Smart cascade — remove nodes that have at least one active input - // A node stays active if any incoming edge comes from a source NOT in potentiallyDimmed - // AND that source is not a Switch with a disabled output pointing to this node + // Step 2: Type-aware smart cascade — only un-dim if an active input replaces + // the SAME data type that was blocked by the disabled Switch output. + // e.g. a Prompt (text) does NOT rescue a node whose image input is disabled. const finalDimmed = new Set(); potentiallyDimmed.forEach(nodeId => { const incomingEdges = edges.filter(e => e.target === nodeId); - // Check if any incoming edge provides an active path - const hasActiveInput = incomingEdges.some(edge => { - // Source is not potentially dimmed — it's an active source - if (!potentiallyDimmed.has(edge.source)) { - // But also check: is this edge coming from a disabled Switch output? - const sourceNode = nodes.find(n => n.id === edge.source); - if (sourceNode?.type === "switch") { - const switchData = sourceNode.data as SwitchNodeData; - const switchEntry = switchData.switches?.find(s => s.id === edge.sourceHandle); - // If this specific switch output is disabled, it's not an active path - if (switchEntry && !switchEntry.enabled) return false; + // Collect which handle types are blocked on this node + // (from disabled Switch outputs or from transitively dimmed sources) + const blockedTypes = new Set(); + incomingEdges.forEach(edge => { + const sourceNode = nodes.find(n => n.id === edge.source); + if (sourceNode?.type === "switch") { + const switchData = sourceNode.data as SwitchNodeData; + const switchEntry = switchData.switches?.find(s => s.id === edge.sourceHandle); + if (switchEntry && !switchEntry.enabled && edge.targetHandle) { + blockedTypes.add(edge.targetHandle); } - return true; // Active source, not dimmed + } else if (potentiallyDimmed.has(edge.source) && edge.targetHandle) { + blockedTypes.add(edge.targetHandle); } - return false; // Source is also dimmed }); - if (!hasActiveInput) { + // Check if any active input provides the same type as a blocked type + const hasReplacementInput = incomingEdges.some(edge => { + // Skip dimmed sources + if (potentiallyDimmed.has(edge.source)) return false; + // Skip disabled Switch outputs + const sourceNode = nodes.find(n => n.id === edge.source); + if (sourceNode?.type === "switch") { + const switchData = sourceNode.data as SwitchNodeData; + const switchEntry = switchData.switches?.find(s => s.id === edge.sourceHandle); + if (switchEntry && !switchEntry.enabled) return false; + } + // Active input — only counts if it provides a blocked type + return edge.targetHandle ? blockedTypes.has(edge.targetHandle) : false; + }); + + if (!hasReplacementInput) { finalDimmed.add(nodeId); } });