[Refactor] Move strokeShape from LGraphCanvas to draw (#435)

* [Refactor] Move strokeShape from LGraphCanvas to draw

* Fix round radius

* nit

* nit

* nit
This commit is contained in:
Chenlei Hu
2025-02-02 19:29:26 -08:00
committed by GitHub
parent a4791f6e6b
commit 817214e6da
6 changed files with 131 additions and 113 deletions

View File

@@ -56,7 +56,7 @@ import {
isInRect,
snapPoint,
} from "./measure"
import { drawSlot, LabelPosition } from "./draw"
import { drawSlot, LabelPosition, strokeShape } from "./draw"
import { DragAndScale } from "./DragAndScale"
import { LinkReleaseContextExtended, LiteGraph, clamp } from "./litegraph"
import { stringOrEmpty, stringOrNull } from "./strings"
@@ -132,16 +132,6 @@ interface IDialogOptions {
onclose?(): void
}
interface IDrawSelectionBoundingOptions {
shape?: RenderShape
title_height?: number
title_mode?: TitleMode
colour?: CanvasColour
padding?: number
collapsed?: boolean
thickness?: number
}
/** @inheritdoc {@link LGraphCanvas.state} */
export interface LGraphCanvasState {
/** {@link Positionable} items are being dragged on the canvas. */
@@ -313,6 +303,20 @@ export class LGraphCanvas {
this.#maximumFrameGap = value > Number.EPSILON ? 1000 / value : 0
}
/**
* @deprecated Use {@link LiteGraphGlobal.ROUND_RADIUS} instead.
*/
get round_radius() {
return LiteGraph.ROUND_RADIUS
}
/**
* @deprecated Use {@link LiteGraphGlobal.ROUND_RADIUS} instead.
*/
set round_radius(value: number) {
LiteGraph.ROUND_RADIUS = value
}
options: {
skip_events?: any
viewport?: any
@@ -388,7 +392,6 @@ export class LGraphCanvas {
/** to render foreground objects (above nodes and connections) in the canvas affected by transform */
onDrawForeground?: (arg0: CanvasRenderingContext2D, arg1: any) => void
connections_width: number
round_radius: number
/** The current node being drawn by {@link drawNode}. This should NOT be used to determine the currently selected node. See {@link selectedItems} */
current_node: LGraphNode | null
/** used for widgets */
@@ -628,7 +631,6 @@ export class LGraphCanvas {
this.onAfterChange = null
this.connections_width = 3
this.round_radius = 8
this.current_node = null
this.node_widget = null
@@ -4534,7 +4536,7 @@ export class LGraphCanvas {
const area = node.boundingRect
const gap = 3
const radius = this.round_radius + gap
const radius = LiteGraph.ROUND_RADIUS + gap
const x = area[0] - gap
const y = area[1] - gap
@@ -5191,8 +5193,8 @@ export class LGraphCanvas {
area[2],
area[3],
shape == RenderShape.CARD
? [this.round_radius, this.round_radius, 0, 0]
: [this.round_radius],
? [LiteGraph.ROUND_RADIUS, LiteGraph.ROUND_RADIUS, 0, 0]
: [LiteGraph.ROUND_RADIUS],
)
} else if (shape == RenderShape.CIRCLE) {
ctx.arc(size[0] * 0.5, size[1] * 0.5, size[0] * 0.5, 0, Math.PI * 2)
@@ -5200,7 +5202,7 @@ export class LGraphCanvas {
ctx.fill()
if (node.has_errors && !LiteGraph.use_legacy_node_error_indicator) {
this.strokeShape(ctx, area, {
strokeShape(ctx, area, {
shape,
title_mode,
title_height,
@@ -5247,8 +5249,8 @@ export class LGraphCanvas {
size[0],
title_height,
collapsed
? [this.round_radius]
: [this.round_radius, this.round_radius, 0, 0],
? [LiteGraph.ROUND_RADIUS]
: [LiteGraph.ROUND_RADIUS, LiteGraph.ROUND_RADIUS, 0, 0],
)
}
ctx.fill()
@@ -5411,7 +5413,7 @@ export class LGraphCanvas {
const padding = node.has_errors && !LiteGraph.use_legacy_node_error_indicator ? 20 : undefined
this.strokeShape(ctx, area, {
strokeShape(ctx, area, {
shape,
title_height,
title_mode,
@@ -5425,94 +5427,6 @@ export class LGraphCanvas {
if (node.action_triggered > 0) node.action_triggered--
}
/**
* Draws only the path of a shape on the canvas, without filling.
* Used to draw indicators for node status, e.g. "selected".
* @param ctx The 2D context to draw on
* @param area The position and size of the shape to render
*/
strokeShape(
ctx: CanvasRenderingContext2D,
area: Rect,
{
/** The shape to render */
shape = RenderShape.BOX,
/** Shape will extend above the Y-axis 0 by this amount */
title_height = LiteGraph.NODE_TITLE_HEIGHT,
/** @deprecated This is node-specific: it should be removed entirely, and behaviour defined by the caller more explicitly */
title_mode = TitleMode.NORMAL_TITLE,
/** The colour that should be drawn */
colour = LiteGraph.NODE_BOX_OUTLINE_COLOR,
/** The distance between the edge of the {@link area} and the middle of the line */
padding = 6,
/** @deprecated This is node-specific: it should be removed entirely, and behaviour defined by the caller more explicitly */
collapsed = false,
/** Thickness of the line drawn (`lineWidth`) */
thickness = 1,
}: IDrawSelectionBoundingOptions = {},
): void {
// Adjust area if title is transparent
if (title_mode === TitleMode.TRANSPARENT_TITLE) {
area[1] -= title_height
area[3] += title_height
}
// Set up context
const { lineWidth, strokeStyle } = ctx
ctx.lineWidth = thickness
ctx.globalAlpha = 0.8
ctx.strokeStyle = colour
ctx.beginPath()
// Draw shape based on type
const [x, y, width, height] = area
switch (shape) {
case RenderShape.BOX: {
ctx.rect(
x - padding,
y - padding,
width + 2 * padding,
height + 2 * padding,
)
break
}
case RenderShape.ROUND:
case RenderShape.CARD: {
const radius = this.round_radius + padding
const isCollapsed = shape === RenderShape.CARD && collapsed
const cornerRadii =
isCollapsed || shape === RenderShape.ROUND
? [radius]
: [radius, 2, radius, 2]
ctx.roundRect(
x - padding,
y - padding,
width + 2 * padding,
height + 2 * padding,
cornerRadii,
)
break
}
case RenderShape.CIRCLE: {
const centerX = x + width / 2
const centerY = y + height / 2
const radius = Math.max(width, height) / 2 + padding
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2)
break
}
}
// Stroke the shape
ctx.stroke()
// Reset context
ctx.lineWidth = lineWidth
ctx.strokeStyle = strokeStyle
// TODO: Store and reset value properly. Callers currently expect this behaviour (e.g. muted nodes).
ctx.globalAlpha = 1
}
/**
* Draws a snap guide for a {@link Positionable} item.
*

View File

@@ -18,7 +18,7 @@ import {
snapPoint,
} from "./measure"
import { LGraphNode } from "./LGraphNode"
import { RenderShape, TitleMode } from "./types/globalEnums"
import { strokeShape } from "./draw"
export interface IGraphGroupFlags extends Record<string, unknown> {
pinned?: true
@@ -183,7 +183,7 @@ export class LGraphGroup implements Positionable, IPinnable {
ctx.fillText(this.title + (this.pinned ? "📌" : ""), x + padding, y + font_size)
if (LiteGraph.highlight_selected_group && this.selected) {
graphCanvas.strokeShape(ctx, this._bounding, {
strokeShape(ctx, this._bounding, {
title_height: this.titleHeight,
padding,
})

View File

@@ -76,6 +76,7 @@ export class LiteGraphGlobal {
DEFAULT_POSITION = [100, 100]
/** ,"circle" */
VALID_SHAPES = ["default", "box", "round", "card"]
ROUND_RADIUS = 8
// shapes are used for nodes but also for slots
BOX_SHAPE = RenderShape.BOX

View File

@@ -1,6 +1,6 @@
import type { Vector2 } from "./litegraph"
import type { INodeSlot } from "./interfaces"
import { LinkDirection, RenderShape } from "./types/globalEnums"
import { LiteGraph, type Vector2 } from "./litegraph"
import type { CanvasColour, INodeSlot, Rect } from "./interfaces"
import { LinkDirection, RenderShape, TitleMode } from "./types/globalEnums"
export enum SlotType {
Array = "array",
@@ -143,3 +143,104 @@ export function drawSlot(
ctx.strokeStyle = originalStrokeStyle
ctx.lineWidth = originalLineWidth
}
interface IDrawSelectionBoundingOptions {
shape?: RenderShape
round_radius?: number
title_height?: number
title_mode?: TitleMode
colour?: CanvasColour
padding?: number
collapsed?: boolean
thickness?: number
}
/**
* Draws only the path of a shape on the canvas, without filling.
* Used to draw indicators for node status, e.g. "selected".
* @param ctx The 2D context to draw on
* @param area The position and size of the shape to render
*/
export function strokeShape(
ctx: CanvasRenderingContext2D,
area: Rect,
{
/** The shape to render */
shape = RenderShape.BOX,
/** The radius of the rounded corners for {@link RenderShape.ROUND} and {@link RenderShape.CARD} */
round_radius = LiteGraph.ROUND_RADIUS,
/** Shape will extend above the Y-axis 0 by this amount */
title_height = LiteGraph.NODE_TITLE_HEIGHT,
/** @deprecated This is node-specific: it should be removed entirely, and behaviour defined by the caller more explicitly */
title_mode = TitleMode.NORMAL_TITLE,
/** The colour that should be drawn */
colour = LiteGraph.NODE_BOX_OUTLINE_COLOR,
/** The distance between the edge of the {@link area} and the middle of the line */
padding = 6,
/** @deprecated This is node-specific: it should be removed entirely, and behaviour defined by the caller more explicitly */
collapsed = false,
/** Thickness of the line drawn (`lineWidth`) */
thickness = 1,
}: IDrawSelectionBoundingOptions = {},
): void {
// Adjust area if title is transparent
if (title_mode === TitleMode.TRANSPARENT_TITLE) {
area[1] -= title_height
area[3] += title_height
}
// Set up context
const { lineWidth, strokeStyle } = ctx
ctx.lineWidth = thickness
ctx.globalAlpha = 0.8
ctx.strokeStyle = colour
ctx.beginPath()
// Draw shape based on type
const [x, y, width, height] = area
switch (shape) {
case RenderShape.BOX: {
ctx.rect(
x - padding,
y - padding,
width + 2 * padding,
height + 2 * padding,
)
break
}
case RenderShape.ROUND:
case RenderShape.CARD: {
const radius = round_radius + padding
const isCollapsed = shape === RenderShape.CARD && collapsed
const cornerRadii =
isCollapsed || shape === RenderShape.ROUND
? [radius]
: [radius, 2, radius, 2]
ctx.roundRect(
x - padding,
y - padding,
width + 2 * padding,
height + 2 * padding,
cornerRadii,
)
break
}
case RenderShape.CIRCLE: {
const centerX = x + width / 2
const centerY = y + height / 2
const radius = Math.max(width, height) / 2 + padding
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2)
break
}
}
// Stroke the shape
ctx.stroke()
// Reset context
ctx.lineWidth = lineWidth
ctx.strokeStyle = strokeStyle
// TODO: Store and reset value properly. Callers currently expect this behaviour (e.g. muted nodes).
ctx.globalAlpha = 1
}

View File

@@ -83,6 +83,7 @@ export type {
export { CanvasPointer } from "./CanvasPointer"
export { Reroute } from "./Reroute"
export { createBounds } from "./measure"
export { strokeShape } from "./draw"
export function clamp(v: number, a: number, b: number): number {
return a > v ? a : b < v ? b : v

View File

@@ -88,6 +88,7 @@ LiteGraphGlobal {
"ON_TRIGGER": 3,
"OUTPUT": 2,
"RIGHT": 4,
"ROUND_RADIUS": 8,
"ROUND_SHAPE": 2,
"Reroute": [Function],
"SPLINE_LINK": 2,