Add LGraphNode.strokeStyles API (#868)

This should allow frontend drop the stroke logic in hijack of
`drawNodeShape`. Example usage:

```ts
node.strokeStyles["executionError"] = (this: LGraphNode) => 
  app.lastNodeErrors?.[this.id] ? { colour: 'red', thickness: 2 } : undefined
```
This commit is contained in:
Chenlei Hu
2025-03-30 11:29:37 -04:00
committed by GitHub
parent 27a2b785ac
commit 854ac4350f
6 changed files with 80 additions and 29 deletions

View File

@@ -4390,7 +4390,7 @@ export class LGraphCanvas implements ConnectionColorContext {
* @param size Size of the background to draw, in graph units. Differs from node size if collapsed, etc.
* @param fgcolor Foreground colour - used for text
* @param bgcolor Background colour of the node
* @param selected Whether to render the node as selected. Likely to be removed in future, as current usage is simply the selected property of the node.
* @param _selected Whether to render the node as selected. Likely to be removed in future, as current usage is simply the selected property of the node.
*/
drawNodeShape(
node: LGraphNode,
@@ -4398,7 +4398,7 @@ export class LGraphCanvas implements ConnectionColorContext {
size: Size,
fgcolor: CanvasColour,
bgcolor: CanvasColour,
selected: boolean,
_selected: boolean,
): void {
// Rendering options
ctx.strokeStyle = fgcolor
@@ -4442,18 +4442,6 @@ export class LGraphCanvas implements ConnectionColorContext {
}
ctx.fill()
if (node.has_errors) {
strokeShape(ctx, area, {
shape,
title_mode,
title_height,
padding: 12,
colour: LiteGraph.NODE_ERROR_COLOUR,
collapsed,
thickness: 10,
})
}
// Separator - title bar <-> body
if (!collapsed && render_title) {
ctx.shadowColor = "transparent"
@@ -4491,19 +4479,18 @@ export class LGraphCanvas implements ConnectionColorContext {
node.onDrawTitle?.(ctx)
}
// render selection marker
if (selected) {
node.onBounding?.(area)
const padding = node.has_errors ? 20 : undefined
strokeShape(ctx, area, {
shape,
title_height,
title_mode,
padding,
collapsed: node.flags?.collapsed,
})
// Draw stroke styles
for (const getStyle of Object.values(node.strokeStyles)) {
const strokeStyle = getStyle.call(node)
if (strokeStyle) {
strokeShape(ctx, area, {
shape,
title_height,
title_mode,
collapsed,
...strokeStyle,
})
}
}
// these counter helps in conditioning drawing based on if the node has been executed or an action occurred

View File

@@ -1,4 +1,5 @@
import type { DragAndScale } from "./DragAndScale"
import type { IDrawBoundingOptions } from "./draw"
import type {
CanvasColour,
ColorOption,
@@ -256,6 +257,11 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
) ?? null
}
/**
* The stroke styles that should be applied to the node.
*/
strokeStyles: Record<string, (this: LGraphNode) => IDrawBoundingOptions | undefined>
exec_version?: number
action_call?: string
execute_triggered?: number
@@ -586,12 +592,34 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
overWidget: IWidget,
): boolean | undefined
#getErrorStrokeStyle(this: LGraphNode): IDrawBoundingOptions | undefined {
if (this.has_errors) {
return {
padding: 12,
thickness: 10,
colour: LiteGraph.NODE_ERROR_COLOUR,
}
}
}
#getSelectedStrokeStyle(this: LGraphNode): IDrawBoundingOptions | undefined {
if (this.selected) {
return {
padding: this.has_errors ? 20 : undefined,
}
}
}
constructor(title: string, type?: string) {
this.id = LiteGraph.use_uuids ? LiteGraph.uuidv4() : -1
this.title = title || "Unnamed"
this.type = type ?? ""
this.size = [LiteGraph.NODE_WIDTH, 60]
this.pos = [10, 10]
this.strokeStyles = {
error: this.#getErrorStrokeStyle,
selected: this.#getSelectedStrokeStyle,
}
}
/**

View File

@@ -30,7 +30,7 @@ export enum LabelPosition {
Right = "right",
}
interface IDrawSelectionBoundingOptions {
export interface IDrawBoundingOptions {
/** The shape to render */
shape?: RenderShape
/** The radius of the rounded corners for {@link RenderShape.ROUND} and {@link RenderShape.CARD} */
@@ -67,7 +67,7 @@ export function strokeShape(
padding = 6,
collapsed = false,
thickness = 1,
}: IDrawSelectionBoundingOptions = {},
}: IDrawBoundingOptions = {},
): void {
// These param defaults are not compile-time static, and must be re-evaluated at runtime
round_radius ??= LiteGraph.ROUND_RADIUS

View File

@@ -92,6 +92,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": "LGraphNode",
"type": "mustBeSet",
"widgets": undefined,
@@ -156,6 +160,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": "LGraphNode",
"type": "mustBeSet",
"widgets": undefined,
@@ -221,6 +229,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": "LGraphNode",
"type": "mustBeSet",
"widgets": undefined,

View File

@@ -94,6 +94,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": undefined,
"type": "",
"widgets": undefined,
@@ -160,6 +164,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": undefined,
"type": "",
"widgets": undefined,
@@ -227,6 +235,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": undefined,
"type": "",
"widgets": undefined,

View File

@@ -92,6 +92,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": "LGraphNode",
"type": "mustBeSet",
"widgets": undefined,
@@ -156,6 +160,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": "LGraphNode",
"type": "mustBeSet",
"widgets": undefined,
@@ -221,6 +229,10 @@ LGraph {
"selected": undefined,
"serialize_widgets": undefined,
"showAdvanced": undefined,
"strokeStyles": {
"error": [Function],
"selected": [Function],
},
"title": "LGraphNode",
"type": "mustBeSet",
"widgets": undefined,