mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-22 13:32:11 +00:00
Compare commits
10 Commits
rizumu/scr
...
litegraph/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0821f4b443 | ||
|
|
1af4b8efc6 | ||
|
|
6ba54935ce | ||
|
|
b0947ee834 | ||
|
|
74c09f31ef | ||
|
|
173293b919 | ||
|
|
fc6a0c8491 | ||
|
|
699824f1e4 | ||
|
|
1f8e2c71d3 | ||
|
|
2dadcde05d |
@@ -59,9 +59,10 @@ test.describe('Canvas settings', { tag: '@canvas' }, () => {
|
||||
await test.step('Capture HUD region with setting on', async () => {
|
||||
await comfyPage.settings.setSetting('Comfy.Graph.CanvasInfo', true)
|
||||
await comfyPage.canvasOps.moveMouseToEmptyArea()
|
||||
// FPS value varies per run; allow ~1% pixel variance in the 180×160 clip
|
||||
await expect(comfyPage.page).toHaveScreenshot(
|
||||
'canvas-info-hud-on.png',
|
||||
{ clip: hudClip, maxDiffPixels: 50 }
|
||||
{ clip: hudClip, maxDiffPixels: 350 }
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -212,9 +212,6 @@ describe('useCoreCommands', () => {
|
||||
clear: vi.fn(),
|
||||
serialize: vi.fn(),
|
||||
configure: vi.fn(),
|
||||
start: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
runStep: vi.fn(),
|
||||
findNodeByTitle: vi.fn(),
|
||||
findNodesByTitle: vi.fn(),
|
||||
findNodesByType: vi.fn(),
|
||||
|
||||
@@ -104,8 +104,6 @@ const secondNode = LiteGraph.createNode('basic/sum')
|
||||
graph.add(secondNode)
|
||||
|
||||
firstNode.connect(0, secondNode, 1)
|
||||
|
||||
graph.start()
|
||||
```
|
||||
|
||||
## Projects using it
|
||||
|
||||
@@ -73,7 +73,7 @@ import {
|
||||
multiClone,
|
||||
splitPositionables
|
||||
} from './subgraph/subgraphUtils'
|
||||
import { Alignment, LGraphEventMode } from './types/globalEnums'
|
||||
import { Alignment } from './types/globalEnums'
|
||||
import type {
|
||||
LGraphTriggerAction,
|
||||
LGraphTriggerEvent,
|
||||
@@ -173,8 +173,10 @@ export interface BaseLGraph {
|
||||
}
|
||||
|
||||
/**
|
||||
* LGraph is the class that contain a full graph. We instantiate one and add nodes to it, and then we can run the execution loop.
|
||||
* supported callbacks:
|
||||
* LGraph contains a full graph. Instantiate it, add nodes/groups, and use it
|
||||
* for editing, traversal, and serialisation.
|
||||
*
|
||||
* Supported callbacks:
|
||||
* + onNodeAdded: when a new node is added to the graph
|
||||
* + onNodeRemoved: when a node inside this graph is removed
|
||||
*/
|
||||
@@ -183,9 +185,6 @@ export class LGraph
|
||||
{
|
||||
static serialisedSchemaVersion = 1 as const
|
||||
|
||||
static STATUS_STOPPED = 1
|
||||
static STATUS_RUNNING = 2
|
||||
|
||||
/** List of LGraph properties that are manually handled by {@link LGraph.configure}. */
|
||||
static readonly ConfigureProperties = new Set([
|
||||
'nodes',
|
||||
@@ -224,7 +223,6 @@ export class LGraph
|
||||
*/
|
||||
links: Map<LinkId, LLink> & Record<LinkId, LLink>
|
||||
list_of_graphcanvas: LGraphCanvas[] | null
|
||||
status: number = LGraph.STATUS_STOPPED
|
||||
|
||||
private _state: LGraphState = {
|
||||
lastGroupId: 0,
|
||||
@@ -249,20 +247,6 @@ export class LGraph
|
||||
_nodes_in_order: LGraphNode[] = []
|
||||
_nodes_executable: LGraphNode[] | null = null
|
||||
_groups: LGraphGroup[] = []
|
||||
iteration: number = 0
|
||||
globaltime: number = 0
|
||||
/** @deprecated Unused */
|
||||
runningtime: number = 0
|
||||
fixedtime: number = 0
|
||||
fixedtime_lapse: number = 0.01
|
||||
elapsed_time: number = 0.01
|
||||
last_update_time: number = 0
|
||||
starttime: number = 0
|
||||
catch_errors: boolean = true
|
||||
execution_timer_id?: number | null
|
||||
errors_in_execution?: boolean
|
||||
/** @deprecated Unused */
|
||||
execution_time!: number
|
||||
_last_trigger_time?: number
|
||||
filter?: string
|
||||
/** Must contain serialisable values, e.g. primitive types */
|
||||
@@ -368,9 +352,6 @@ export class LGraph
|
||||
* Removes all nodes from this graph
|
||||
*/
|
||||
clear(): void {
|
||||
this.stop()
|
||||
this.status = LGraph.STATUS_STOPPED
|
||||
|
||||
const graphId = this.id
|
||||
if (this.isRootGraph && graphId !== zeroUuid) {
|
||||
usePromotionStore().clearGraph(graphId)
|
||||
@@ -416,26 +397,12 @@ export class LGraph
|
||||
// other scene stuff
|
||||
this._groups = []
|
||||
|
||||
// iterations
|
||||
this.iteration = 0
|
||||
|
||||
// custom data
|
||||
this.config = {}
|
||||
this.vars = {}
|
||||
// to store custom data
|
||||
this.extra = {}
|
||||
|
||||
// timing
|
||||
this.globaltime = 0
|
||||
this.runningtime = 0
|
||||
this.fixedtime = 0
|
||||
this.fixedtime_lapse = 0.01
|
||||
this.elapsed_time = 0.01
|
||||
this.last_update_time = 0
|
||||
this.starttime = 0
|
||||
|
||||
this.catch_errors = true
|
||||
|
||||
this.nodes_executing = []
|
||||
this.nodes_actioning = []
|
||||
this.nodes_executedAction = []
|
||||
@@ -492,131 +459,6 @@ export class LGraph
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in 0.9
|
||||
* Starts running this graph every interval milliseconds.
|
||||
* @param interval amount of milliseconds between executions, if 0 then it renders to the monitor refresh rate
|
||||
*/
|
||||
start(interval?: number): void {
|
||||
if (this.status == LGraph.STATUS_RUNNING) return
|
||||
this.status = LGraph.STATUS_RUNNING
|
||||
this.sendEventToAllNodes('onStart')
|
||||
|
||||
// launch
|
||||
this.starttime = LiteGraph.getTime()
|
||||
this.last_update_time = this.starttime
|
||||
interval ||= 0
|
||||
|
||||
// execute once per frame
|
||||
if (
|
||||
interval == 0 &&
|
||||
typeof window != 'undefined' &&
|
||||
window.requestAnimationFrame
|
||||
) {
|
||||
const on_frame = () => {
|
||||
if (this.execution_timer_id != -1) return
|
||||
|
||||
window.requestAnimationFrame(on_frame)
|
||||
this.runStep(1, !this.catch_errors)
|
||||
}
|
||||
this.execution_timer_id = -1
|
||||
on_frame()
|
||||
} else {
|
||||
// execute every 'interval' ms
|
||||
// @ts-expect-error - Timer ID type mismatch needs fixing
|
||||
this.execution_timer_id = setInterval(() => {
|
||||
// execute
|
||||
this.runStep(1, !this.catch_errors)
|
||||
}, interval)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in 0.9
|
||||
* Stops the execution loop of the graph
|
||||
*/
|
||||
stop(): void {
|
||||
if (this.status == LGraph.STATUS_STOPPED) return
|
||||
|
||||
this.status = LGraph.STATUS_STOPPED
|
||||
if (this.execution_timer_id != null) {
|
||||
if (this.execution_timer_id != -1) {
|
||||
clearInterval(this.execution_timer_id)
|
||||
}
|
||||
this.execution_timer_id = null
|
||||
}
|
||||
|
||||
this.sendEventToAllNodes('onStop')
|
||||
}
|
||||
|
||||
/**
|
||||
* Run N steps (cycles) of the graph
|
||||
* @param num number of steps to run, default is 1
|
||||
* @param do_not_catch_errors [optional] if you want to try/catch errors
|
||||
* @param limit max number of nodes to execute (used to execute from start to a node)
|
||||
*/
|
||||
runStep(num: number, do_not_catch_errors: boolean, limit?: number): void {
|
||||
num = num || 1
|
||||
|
||||
const start = LiteGraph.getTime()
|
||||
this.globaltime = 0.001 * (start - this.starttime)
|
||||
|
||||
const nodes = this._nodes_executable || this._nodes
|
||||
if (!nodes) return
|
||||
|
||||
limit = limit || nodes.length
|
||||
|
||||
if (do_not_catch_errors) {
|
||||
// iterations
|
||||
for (let i = 0; i < num; i++) {
|
||||
for (let j = 0; j < limit; ++j) {
|
||||
const node = nodes[j]
|
||||
// FIXME: Looks like copy/paste broken logic - checks for "on", executes "do"
|
||||
if (node.mode == LGraphEventMode.ALWAYS && node.onExecute) {
|
||||
// wrap node.onExecute();
|
||||
node.doExecute?.()
|
||||
}
|
||||
}
|
||||
|
||||
this.fixedtime += this.fixedtime_lapse
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
// iterations
|
||||
for (let i = 0; i < num; i++) {
|
||||
for (let j = 0; j < limit; ++j) {
|
||||
const node = nodes[j]
|
||||
if (node.mode == LGraphEventMode.ALWAYS) {
|
||||
node.onExecute?.()
|
||||
}
|
||||
}
|
||||
|
||||
this.fixedtime += this.fixedtime_lapse
|
||||
}
|
||||
this.errors_in_execution = false
|
||||
} catch (error) {
|
||||
this.errors_in_execution = true
|
||||
if (LiteGraph.throw_errors) throw error
|
||||
|
||||
if (LiteGraph.debug) console.error('Error during execution:', error)
|
||||
this.stop()
|
||||
}
|
||||
}
|
||||
|
||||
const now = LiteGraph.getTime()
|
||||
let elapsed = now - start
|
||||
if (elapsed == 0) elapsed = 1
|
||||
|
||||
this.execution_time = 0.001 * elapsed
|
||||
this.globaltime += 0.001 * elapsed
|
||||
this.iteration += 1
|
||||
this.elapsed_time = (now - this.last_update_time) * 0.001
|
||||
this.last_update_time = now
|
||||
this.nodes_executing = []
|
||||
this.nodes_actioning = []
|
||||
this.nodes_executedAction = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the graph execution order according to relevance of the nodes (nodes with only outputs have more relevance than
|
||||
* nodes with only inputs.
|
||||
@@ -803,33 +645,6 @@ export class LGraph
|
||||
this.setDirtyCanvas(true, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of time the graph has been running in milliseconds
|
||||
* @returns number of milliseconds the graph has been running
|
||||
*/
|
||||
getTime(): number {
|
||||
return this.globaltime
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of time accumulated using the fixedtime_lapse var.
|
||||
* This is used in context where the time increments should be constant
|
||||
* @returns number of milliseconds the graph has been running
|
||||
*/
|
||||
getFixedTime(): number {
|
||||
return this.fixedtime
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of time it took to compute the latest iteration.
|
||||
* Take into account that this number could be not correct
|
||||
* if the nodes are using graphical actions
|
||||
* @returns number of milliseconds it took the last cycle
|
||||
*/
|
||||
getElapsedTime(): number {
|
||||
return this.elapsed_time
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the internal version counter.
|
||||
* Currently only read for debug display in {@link LGraphCanvas.renderInfo}.
|
||||
@@ -839,39 +654,6 @@ export class LGraph
|
||||
this._version++
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in 0.9
|
||||
* Sends an event to all the nodes, useful to trigger stuff
|
||||
* @param eventname the name of the event (function to be called)
|
||||
* @param params parameters in array format
|
||||
*/
|
||||
sendEventToAllNodes(
|
||||
eventname: string,
|
||||
params?: object | object[],
|
||||
mode?: LGraphEventMode
|
||||
): void {
|
||||
mode = mode || LGraphEventMode.ALWAYS
|
||||
|
||||
const nodes = this._nodes_in_order || this._nodes
|
||||
if (!nodes) return
|
||||
|
||||
for (const node of nodes) {
|
||||
// @ts-expect-error deprecated
|
||||
if (!node[eventname] || node.mode != mode) continue
|
||||
if (params === undefined) {
|
||||
// @ts-expect-error deprecated
|
||||
node[eventname]()
|
||||
} else if (params && params.constructor === Array) {
|
||||
// @ts-expect-error deprecated
|
||||
// eslint-disable-next-line prefer-spread
|
||||
node[eventname].apply(node, params)
|
||||
} else {
|
||||
// @ts-expect-error deprecated
|
||||
node[eventname](params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an action on every canvas registered to this graph.
|
||||
* @param action Action to run for every canvas
|
||||
|
||||
@@ -48,9 +48,9 @@ describe('LGraphCanvas.renderInfo', () => {
|
||||
try {
|
||||
lgCanvas.renderInfo(ctx, 10, 0)
|
||||
|
||||
// lineCount = 5 (graph present, no info_text), lineHeight = 13
|
||||
// lineCount = 3 (graph present, no info_text), lineHeight = 13
|
||||
// y = canvas.height / DPR - (lineCount + 1) * lineHeight
|
||||
expect(ctx.translate).toHaveBeenCalledWith(10, 2160 / 2 - 6 * 13)
|
||||
expect(ctx.translate).toHaveBeenCalledWith(10, 2160 / 2 - 4 * 13)
|
||||
} finally {
|
||||
Object.defineProperty(window, 'devicePixelRatio', {
|
||||
value: originalDPR,
|
||||
|
||||
@@ -5404,7 +5404,7 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>
|
||||
*/
|
||||
renderInfo(ctx: CanvasRenderingContext2D, x: number, y: number): void {
|
||||
const lineHeight = 13
|
||||
const lineCount = (this.graph ? 5 : 1) + (this.info_text ? 1 : 0)
|
||||
const lineCount = (this.graph ? 3 : 1) + (this.info_text ? 1 : 0)
|
||||
x = x || 10
|
||||
y =
|
||||
y ||
|
||||
@@ -5421,12 +5421,6 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>
|
||||
ctx.textAlign = 'left'
|
||||
let line = 1
|
||||
if (this.graph) {
|
||||
ctx.fillText(
|
||||
`T: ${this.graph.globaltime.toFixed(2)}s`,
|
||||
5,
|
||||
lineHeight * line++
|
||||
)
|
||||
ctx.fillText(`I: ${this.graph.iteration}`, 5, lineHeight * line++)
|
||||
ctx.fillText(
|
||||
`N: ${this.graph._nodes.length} [${this.visible_nodes.length}]`,
|
||||
5,
|
||||
|
||||
@@ -1422,8 +1422,6 @@ export class LGraphNode
|
||||
// @ts-expect-error deprecated
|
||||
this.graph.nodes_executing[this.id] = false
|
||||
|
||||
// save execution/action ref
|
||||
this.exec_version = this.graph.iteration
|
||||
if (options?.action_call) {
|
||||
this.action_call = options.action_call
|
||||
// @ts-expect-error deprecated
|
||||
|
||||
@@ -947,8 +947,6 @@ export class ComfyApp {
|
||||
}
|
||||
)
|
||||
|
||||
this.rootGraph.start()
|
||||
|
||||
// Ensure the canvas fills the window
|
||||
useResizeObserver(this.canvasElRef, ([canvasEl]) => {
|
||||
if (canvasEl.target instanceof HTMLCanvasElement) {
|
||||
|
||||
Reference in New Issue
Block a user