mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-21 15:24:09 +00:00
This pull request refactors the minimap rendering system to use a unified, extensible data source abstraction for all minimap operations. By introducing a data source interface and factory, the minimap can now seamlessly support multiple sources of node layout (such as the `LayoutStore` or the underlying `LiteGraph`), improving maintainability and future extensibility. Rendering logic and change detection throughout the minimap have been updated to use this new abstraction, resulting in cleaner code and easier support for new data models. **Core architecture improvements:** * Introduced a new `IMinimapDataSource` interface and related data types (`MinimapNodeData`, `MinimapLinkData`, `MinimapGroupData`) to standardize node, link, and group data for minimap rendering. * Added an abstract base class `AbstractMinimapDataSource` that provides shared logic for bounds and group/link extraction, and implemented two concrete data sources: `LiteGraphDataSource` (for classic graph data) and `LayoutStoreDataSource` (for layout store data). [[1]](diffhunk://#diff-ea46218fc9ffced84168a5ff975e4a30e43f7bf134ee8f02ed2eae66efbb729dR1-R95) [[2]](diffhunk://#diff-9a6b7c6be25b4dbeb358fea18f3a21e78797058ccc86c818ed1e5f69c7355273R1-R30) [[3]](diffhunk://#diff-f200ba9495a03157198abff808ed6c3761746071404a52adbad98f6a9d01249bR1-R42) * Created a `MinimapDataSourceFactory` that selects the appropriate data source based on the presence of layout store data, enabling seamless switching between data models. **Minimap rendering and logic refactoring:** * Updated all minimap rendering functions (`renderGroups`, `renderNodes`, `renderConnections`) and the main `renderMinimapToCanvas` entry point to use the unified data source interface, significantly simplifying the rendering code and decoupling it from the underlying graph structure. [[1]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L1-R11) [[2]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121R33-R75) [[3]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L66-R124) [[4]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L134-R161) [[5]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L153-R187) [[6]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L187-L188) [[7]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121R227-R231) [[8]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L230-R248) * Refactored minimap viewport and graph change detection logic to use the data source abstraction for bounds, node, and link change detection, and to respond to layout store version changes. [[1]](diffhunk://#diff-d92e448dee5e30782a66b9e66d8c8b05626dffd0b2ff1032f2612b9a9b9c51f6L2-R10) [[2]](diffhunk://#diff-d92e448dee5e30782a66b9e66d8c8b05626dffd0b2ff1032f2612b9a9b9c51f6R33-R35) [[3]](diffhunk://#diff-d92e448dee5e30782a66b9e66d8c8b05626dffd0b2ff1032f2612b9a9b9c51f6L99-R141) [[4]](diffhunk://#diff-d92e448dee5e30782a66b9e66d8c8b05626dffd0b2ff1032f2612b9a9b9c51f6R157-R160) [[5]](diffhunk://#diff-338d14c67dabffaf6f68fbf09b16e8d67bead2b9df340e46601b2fbd57331521L8-R11) [[6]](diffhunk://#diff-338d14c67dabffaf6f68fbf09b16e8d67bead2b9df340e46601b2fbd57331521L56-R64) These changes make the minimap codebase more modular and robust, and lay the groundwork for supporting additional node layout strategies in the future. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5547-Layoutstore-Minimap-calculation-26e6d73d3650813e9457c051dff41ca1) by [Unito](https://www.unito.io)
96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
import type { LGraph } from '@/lib/litegraph/src/litegraph'
|
|
import { calculateNodeBounds } from '@/renderer/core/spatial/boundsCalculator'
|
|
|
|
import type {
|
|
IMinimapDataSource,
|
|
MinimapBounds,
|
|
MinimapGroupData,
|
|
MinimapLinkData,
|
|
MinimapNodeData
|
|
} from '../types'
|
|
|
|
/**
|
|
* Abstract base class for minimap data sources
|
|
* Provides common functionality and shared implementation
|
|
*/
|
|
export abstract class AbstractMinimapDataSource implements IMinimapDataSource {
|
|
constructor(protected graph: LGraph | null) {}
|
|
|
|
// Abstract methods that must be implemented by subclasses
|
|
abstract getNodes(): MinimapNodeData[]
|
|
abstract getNodeCount(): number
|
|
abstract hasData(): boolean
|
|
|
|
// Shared implementation using calculateNodeBounds
|
|
getBounds(): MinimapBounds {
|
|
const nodes = this.getNodes()
|
|
if (nodes.length === 0) {
|
|
return { minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }
|
|
}
|
|
|
|
// Convert MinimapNodeData to the format expected by calculateNodeBounds
|
|
const compatibleNodes = nodes.map((node) => ({
|
|
pos: [node.x, node.y],
|
|
size: [node.width, node.height]
|
|
}))
|
|
|
|
const bounds = calculateNodeBounds(compatibleNodes)
|
|
if (!bounds) {
|
|
return { minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }
|
|
}
|
|
|
|
return bounds
|
|
}
|
|
|
|
// Shared implementation for groups
|
|
getGroups(): MinimapGroupData[] {
|
|
if (!this.graph?._groups) return []
|
|
return this.graph._groups.map((group) => ({
|
|
x: group.pos[0],
|
|
y: group.pos[1],
|
|
width: group.size[0],
|
|
height: group.size[1],
|
|
color: group.color
|
|
}))
|
|
}
|
|
|
|
// TODO: update when Layoutstore supports links
|
|
getLinks(): MinimapLinkData[] {
|
|
if (!this.graph) return []
|
|
return this.extractLinksFromGraph(this.graph)
|
|
}
|
|
|
|
protected extractLinksFromGraph(graph: LGraph): MinimapLinkData[] {
|
|
const links: MinimapLinkData[] = []
|
|
const nodeMap = new Map(this.getNodes().map((n) => [n.id, n]))
|
|
|
|
for (const node of graph._nodes) {
|
|
if (!node.outputs) continue
|
|
|
|
const sourceNodeData = nodeMap.get(String(node.id))
|
|
if (!sourceNodeData) continue
|
|
|
|
for (const output of node.outputs) {
|
|
if (!output.links) continue
|
|
|
|
for (const linkId of output.links) {
|
|
const link = graph.links[linkId]
|
|
if (!link) continue
|
|
|
|
const targetNodeData = nodeMap.get(String(link.target_id))
|
|
if (!targetNodeData) continue
|
|
|
|
links.push({
|
|
sourceNode: sourceNodeData,
|
|
targetNode: targetNodeData,
|
|
sourceSlot: link.origin_slot,
|
|
targetSlot: link.target_slot
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return links
|
|
}
|
|
}
|