diff --git a/src/app/utilities/rete-editor.ts b/src/app/utilities/rete-editor.ts index b5b255b..ede9e3a 100644 --- a/src/app/utilities/rete-editor.ts +++ b/src/app/utilities/rete-editor.ts @@ -184,10 +184,12 @@ export async function createEditor( area.addPipe((context: any) => { if (context?.type === 'nodetranslated') { - const nodeId = String(context.data?.id ?? ''); + // Any node moved can be one the way back has to clear, not only one of its two ends. for (const connection of editor.getConnections() as LoopAwareConnection[]) { - if (!connection.__loopBack || (connection.source !== nodeId && connection.target !== nodeId)) continue; - connection.__loopTop = loopTop(area, connection); + if (!connection.__loopBack) continue; + const top = loopTop(area, connection); + if (top === connection.__loopTop) continue; + connection.__loopTop = top; void area.update('connection', connection.id); } } @@ -813,10 +815,18 @@ export async function refreshLoopMarkers( * as it is expanded or edited, its position only when it is moved. */ function loopTop(area: AreaPlugin, connection: LoopAwareConnection): number | undefined { - const tops = [connection.source, connection.target] - .map((id) => area.nodeViews.get(id)?.position.y) - .filter((y): y is number => typeof y === 'number'); - return tops.length ? Math.min(...tops) - 48 : undefined; + const ends = [connection.source, connection.target] + .map((id) => area.nodeViews.get(id)) + .filter((view): view is NonNullable => view != null); + if (!ends.length) return undefined; + // The way back runs across everything between its two ends, so it has to clear the tallest of + // those nodes too - the loop's own steps usually sit there - not only the two it connects. + const left = Math.min(...ends.map((view) => view.position.x)); + const right = Math.max(...ends.map((view) => view.position.x + view.element.offsetWidth)); + const tops = [...area.nodeViews.values()] + .filter((view) => view.position.x + view.element.offsetWidth >= left && view.position.x <= right) + .map((view) => view.position.y); + return Math.min(...tops, ...ends.map((view) => view.position.y)) - 48; } /**