Skip to content

Commit a8c3cda

Browse files
ampagentDrJKL
authored andcommitted
refactor: remove redundant geometry comments
1 parent 8da4bc9 commit a8c3cda

7 files changed

Lines changed: 67 additions & 94 deletions

File tree

src/lib/litegraph/src/LGraph.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import type { UUID } from '@/utils/uuid'
1010
import { createUuidv4, zeroUuid } from '@/utils/uuid'
1111
import {
1212
registerGroupLayout,
13+
registerNodeLayout,
1314
unregisterAllGraphLayout,
1415
unregisterGroupLayout,
16+
unregisterNodeLayout,
1517
unregisterRerouteLayout
1618
} from '@/renderer/core/layout/operations/graphLayoutRegistration'
1719
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
@@ -46,10 +48,8 @@ import { LGraphGroup } from './LGraphGroup'
4648
import type { GroupId } from './LGraphGroup'
4749
import {
4850
LGraphNode,
49-
registerNodeLayout,
5051
registerNodeState,
5152
unregisterAllNodeStates,
52-
unregisterNodeLayout,
5353
unregisterNodeState
5454
} from './LGraphNode'
5555
import {

src/lib/litegraph/src/LGraphNode.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,41 @@ describe('snapToGrid', () => {
863863
})
864864
})
865865

866+
describe('layout geometry projection', () => {
867+
beforeEach(() => {
868+
setActivePinia(createTestingPinia({ stubActions: false }))
869+
layoutStore.reset()
870+
})
871+
872+
test('refreshes stable views before indexed mutations', () => {
873+
const graph = new LGraph()
874+
const node = new LGraphNode('test')
875+
node.pos = [10, 20]
876+
node.size = [100, 50]
877+
graph.add(node)
878+
const pos = node.pos
879+
const size = node.size
880+
881+
layoutStore.batchUpdateNodeBounds([
882+
{
883+
nodeId: node.id,
884+
bounds: { x: 30, y: 40, width: 200, height: 80 }
885+
}
886+
])
887+
pos[0] = 50
888+
size[1] = 90
889+
890+
expect(node.pos).toBe(pos)
891+
expect(node.size).toBe(size)
892+
expect([...pos]).toEqual([50, 40])
893+
expect([...size]).toEqual([200, 90])
894+
expect(layoutStore.getNodeLayoutRef(node.id).value).toMatchObject({
895+
position: { x: 50, y: 40 },
896+
size: { width: 200, height: 90 }
897+
})
898+
})
899+
})
900+
866901
describe('_setConcreteSlots', () => {
867902
beforeEach(() => {
868903
setActivePinia(createTestingPinia({ stubActions: false }))

src/lib/litegraph/src/LGraphNode.ts

Lines changed: 7 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ export type NodeProperty = string | number | boolean | object | null
126126
/** Captures only the {@link layoutStore} singleton, so shared across nodes. */
127127
const layoutMutations = useLayoutMutations()
128128

129-
/** Scratch for store rect reads that must not allocate. */
130-
const storedRect = new Float64Array(4)
129+
const storedRectScratch = new Float64Array(4)
131130

132131
interface INodePropertyInfo {
133132
name?: string
@@ -622,19 +621,6 @@ export class LGraphNode
622621
return [posX - bX, posY - bY]
623622
}
624623

625-
/**
626-
* A frame-scoped projection of the node's geometry, which `layoutStore` owns.
627-
*
628-
* Reading straight from the store on every access costs ~57ns against a
629-
* realistic document, and the legacy canvas reads a node's geometry dozens of
630-
* times per frame. The rect is refreshed once per dirty signal and read
631-
* locally after that - ADR 0008's first render-loop mitigation, pre-collecting
632-
* a query rather than probing the store per draw call.
633-
*
634-
* It is a projection, never a source: nothing reads it back into the store,
635-
* and it cannot go stale because every store write bumps the version that
636-
* invalidates it.
637-
*/
638624
_posSize = new Rectangle()
639625
_pos: Point = this._posSize.pos
640626
_size: Size = this._posSize.size
@@ -647,17 +633,10 @@ export class LGraphNode
647633
synchronize: () => this.refreshGeometry()
648634
})
649635

650-
/** The `layoutStore.geometryVersion` this projection was built from. */
651636
_geometryVersion = -1
652637

653-
/**
654-
* Whether the store holds this node's geometry. Until it does — before the
655-
* node is attached — {@link _posSize} is the geometry, not a projection of
656-
* it, and must not be overwritten by whatever entry happens to share the id.
657-
*/
658638
_layoutRegistered = false
659639

660-
/** Rebuilds {@link _posSize} if the store has changed since it was read. */
661640
private refreshGeometry(): void {
662641
if (!this._layoutRegistered) return
663642

@@ -686,9 +665,9 @@ export class LGraphNode
686665

687666
const position = { x: this._pos[0], y: this._pos[1] }
688667
if (
689-
layoutStore.readNodeRect(this.id, storedRect) &&
690-
storedRect[0] === position.x &&
691-
storedRect[1] === position.y
668+
layoutStore.readNodeRect(this.id, storedRectScratch) &&
669+
storedRectScratch[0] === position.x &&
670+
storedRectScratch[1] === position.y
692671
) {
693672
return
694673
}
@@ -721,12 +700,10 @@ export class LGraphNode
721700
private _sizeUpdated(): void {
722701
if (this.id === UNASSIGNED_NODE_ID || !this.graph) return
723702

724-
// An equal write would bump the store version, which invalidates every
725-
// node's geometry projection, so it is worth a read to avoid.
726703
if (
727-
layoutStore.readNodeRect(this.id, storedRect) &&
728-
storedRect[2] === this._size[0] &&
729-
storedRect[3] === this._size[1]
704+
layoutStore.readNodeRect(this.id, storedRectScratch) &&
705+
storedRectScratch[2] === this._size[0] &&
706+
storedRectScratch[3] === this._size[1]
730707
) {
731708
return
732709
}
@@ -4413,36 +4390,6 @@ export function registerNodeState(
44134390
* node. No-op for nodes that were never registered.
44144391
* @param node The node to unregister
44154392
*/
4416-
/**
4417-
* Hands the node's geometry to {@link layoutStore} and switches it to reading
4418-
* from there. Called from `LGraph.add`, after the node has an id.
4419-
* @param node The node to register
4420-
*/
4421-
export function registerNodeLayout(node: LGraphNode, zIndex: number): void {
4422-
layoutMutations.setSource(LayoutSource.Canvas)
4423-
layoutMutations.createNode(node.id, {
4424-
position: { x: node._pos[0], y: node._pos[1] },
4425-
size: { width: node._size[0], height: node._size[1] },
4426-
zIndex,
4427-
visible: true
4428-
})
4429-
node._layoutRegistered = true
4430-
node._geometryVersion = layoutStore.geometryVersion
4431-
}
4432-
4433-
/**
4434-
* Drops the node's layout entry. The node keeps its last known geometry
4435-
* locally, so a detached node still reports where it was.
4436-
* @param node The node to unregister
4437-
*/
4438-
export function unregisterNodeLayout(node: LGraphNode): void {
4439-
if (!node._layoutRegistered) return
4440-
4441-
node._layoutRegistered = false
4442-
layoutMutations.setSource(LayoutSource.Canvas)
4443-
layoutMutations.deleteNode(node.id)
4444-
}
4445-
44464393
export function unregisterNodeState(node: LGraphNode): void {
44474394
if (!node._graphId) return
44484395
useNodeDataStore().deleteNode(node._graphId, node._state)

src/renderer/core/canvas/litegraph/notifyLayoutChanges.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,6 @@
11
import type { LGraphCanvas } from '@/lib/litegraph/src/litegraph'
22
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
33

4-
/**
5-
* Tells the legacy canvas about geometry the store changed on its own — a Vue
6-
* drag, a DOM size measurement — which it would otherwise never repaint for.
7-
*
8-
* Node geometry itself needs no forwarding: `pos` and `size` project from the
9-
* store, so they are already current. What does not carry across is
10-
* `onResize`, which extensions such as `useLoad3d` and DOM widgets chain onto.
11-
* `LGraphNode.setSize` fires it for resizes the class initiates; this covers
12-
* the ones the store initiates.
13-
*
14-
* It fires on the operation rather than on a class/store size difference:
15-
* there is no longer any difference to detect, so a diff-based check would sit
16-
* silently inert.
17-
*
18-
* @param canvas The canvas to repaint and whose nodes should be notified
19-
* @returns A function that stops the notifications
20-
*/
214
export function notifyLayoutChanges(canvas: LGraphCanvas): () => void {
225
return layoutStore.onChange((change) => {
236
if (change.nodeIds.length === 0) return

src/renderer/core/layout/operations/graphLayoutRegistration.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
*/
88
import type { LGraph } from '@/lib/litegraph/src/LGraph'
99
import type { LGraphGroup } from '@/lib/litegraph/src/LGraphGroup'
10-
import { unregisterNodeLayout } from '@/lib/litegraph/src/LGraphNode'
10+
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
1111
import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations'
12+
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
1213
import { LayoutSource } from '@/renderer/core/layout/types'
1314
import type { RerouteId } from '@/renderer/core/layout/types'
1415

@@ -23,6 +24,24 @@ function canvasMutations() {
2324
return mutations
2425
}
2526

27+
export function registerNodeLayout(node: LGraphNode, zIndex: number): void {
28+
canvasMutations().createNode(node.id, {
29+
position: { x: node._pos[0], y: node._pos[1] },
30+
size: { width: node._size[0], height: node._size[1] },
31+
zIndex,
32+
visible: true
33+
})
34+
node._layoutRegistered = true
35+
node._geometryVersion = layoutStore.geometryVersion
36+
}
37+
38+
export function unregisterNodeLayout(node: LGraphNode): void {
39+
if (!node._layoutRegistered) return
40+
41+
node._layoutRegistered = false
42+
canvasMutations().deleteNode(node.id)
43+
}
44+
2645
export function registerGroupLayout(
2746
graph: Pick<LGraph, 'rootGraph'>,
2847
group: Pick<LGraphGroup, 'id' | 'pos' | 'size'>

src/renderer/core/layout/operations/layoutMutations.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const NODE_2 = toNodeId('2')
1313
const MISSING_NODE = toNodeId('999')
1414
const NEW_NODE = toNodeId('99')
1515

16-
/** Production registers nodes from `LGraph.add`; these tests need only the entry. */
1716
function seedNode(
1817
nodeId: NodeId,
1918
[x, y]: [number, number],

src/renderer/core/layout/store/layoutStore.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -369,23 +369,10 @@ class LayoutStoreImpl implements LayoutStore {
369369
return ygroup ? yGroupToLayout(ygroup, groupId) : null
370370
}
371371

372-
/**
373-
* Get current version for change detection
374-
*/
375-
/**
376-
* Bumped by every layout change. Read as a dirty signal by consumers that
377-
* hold a frame-scoped projection of geometry and need to know when to refresh
378-
* it — a plain number, so it stays cheap enough for a per-read check.
379-
*/
380372
get geometryVersion(): number {
381373
return this.version.value
382374
}
383375

384-
/**
385-
* Copies a node's stored rect into `out` without allocating. The one read a
386-
* frame's worth of geometry access should cost; see ADR 0008 on pre-collected
387-
* render queries.
388-
*/
389376
readNodeRect(nodeId: NodeId, out: Float64Array): boolean {
390377
const rect = this.ynodes.get(String(nodeId))?.get('rect') as
391378
| number[]
@@ -399,6 +386,9 @@ class LayoutStoreImpl implements LayoutStore {
399386
return true
400387
}
401388

389+
/**
390+
* Get current version for change detection
391+
*/
402392
getVersion(): ComputedRef<number> {
403393
return computed(() => this.version.value)
404394
}

0 commit comments

Comments
 (0)