diff --git a/src/lib/litegraph/src/LGraphBadge.ts b/src/lib/litegraph/src/LGraphBadge.ts index 76f916fec..6fad0a09c 100644 --- a/src/lib/litegraph/src/LGraphBadge.ts +++ b/src/lib/litegraph/src/LGraphBadge.ts @@ -1,3 +1,4 @@ +import type { ReadOnlyRect } from '@/lib/litegraph/src/interfaces' import { LGraphIcon } from './LGraphIcon' import type { LGraphIconOptions } from './LGraphIcon' @@ -15,6 +16,7 @@ export interface LGraphBadgeOptions { height?: number cornerRadius?: number iconOptions?: LGraphIconOptions + onClick?: (e: MouseEvent) => void xOffset?: number yOffset?: number } @@ -28,9 +30,15 @@ export class LGraphBadge { height: number cornerRadius: number icon?: LGraphIcon + onClick?: (e: MouseEvent) => void xOffset: number yOffset: number + readonly _boundingRect: [number, number, number, number] = [0, 0, 0, 0] + get boundingRect(): ReadOnlyRect { + return this._boundingRect + } + constructor({ text, fgColor = 'white', @@ -40,6 +48,7 @@ export class LGraphBadge { height = 20, cornerRadius = 5, iconOptions, + onClick, xOffset = 0, yOffset = 0 }: LGraphBadgeOptions) { @@ -53,6 +62,7 @@ export class LGraphBadge { if (iconOptions) { this.icon = new LGraphIcon(iconOptions) } + this.onClick = onClick this.xOffset = xOffset this.yOffset = yOffset } @@ -91,6 +101,8 @@ export class LGraphBadge { const badgeWidth = this.getWidth(ctx) const badgeX = 0 + this._boundingRect.splice(0, 4, x, y, badgeWidth, this.height) + // Draw badge background ctx.fillStyle = this.bgColor ctx.beginPath() diff --git a/src/lib/litegraph/src/LGraphCanvas.ts b/src/lib/litegraph/src/LGraphCanvas.ts index 37c0950a2..541165102 100644 --- a/src/lib/litegraph/src/LGraphCanvas.ts +++ b/src/lib/litegraph/src/LGraphCanvas.ts @@ -1,4 +1,5 @@ import { toString } from 'es-toolkit/compat' +import { toValue } from 'vue' import { PREFIX, SEPARATOR } from '@/constants/groupNodeConstants' import { LitegraphLinkAdapter } from '@/renderer/core/canvas/litegraph/litegraphLinkAdapter' @@ -2801,6 +2802,12 @@ export class LGraphCanvas implements CustomEventDispatcher } } } + for (const badge of node.badges.map(toValue).filter((b) => b.onClick)) { + if (isInRect(pos[0], pos[1], badge.boundingRect)) { + pointer.onClick = badge.onClick + return + } + } // Mousedown callback - can block drag if (node.onMouseDown?.(e, pos, this)) { diff --git a/src/lib/litegraph/src/LGraphGroup.ts b/src/lib/litegraph/src/LGraphGroup.ts index ee3197d43..9fcd4985f 100644 --- a/src/lib/litegraph/src/LGraphGroup.ts +++ b/src/lib/litegraph/src/LGraphGroup.ts @@ -18,6 +18,7 @@ import { containsCentre, containsRect, createBounds, + isInRect, isInRectangle, isPointInRect, snapPoint @@ -370,6 +371,8 @@ export class LGraphGroup implements Positionable, IPinnable, IColorable { ) } - isPointInside = LGraphNode.prototype.isPointInside + isPointInside(x: number, y: number): boolean { + return isInRect(x, y, this.boundingRect) + } setDirtyCanvas = LGraphNode.prototype.setDirtyCanvas } diff --git a/src/lib/litegraph/src/LGraphNode.ts b/src/lib/litegraph/src/LGraphNode.ts index a9dc95ccb..1bdbbf867 100644 --- a/src/lib/litegraph/src/LGraphNode.ts +++ b/src/lib/litegraph/src/LGraphNode.ts @@ -1,3 +1,5 @@ +import { toValue } from 'vue' + import { LGraphNodeProperties } from '@/lib/litegraph/src/LGraphNodeProperties' import { calculateInputSlotPosFromSlot, @@ -2084,7 +2086,13 @@ export class LGraphNode * checks if a point is inside the shape of a node */ isPointInside(x: number, y: number): boolean { - return isInRect(x, y, this.boundingRect) + if (isInRect(x, y, this.boundingRect)) return true + + for (const badge of this.badges.map(toValue).filter((b) => b.onClick)) { + if (isInRect(x - this.pos[0], y - this.pos[1], badge.boundingRect)) + return true + } + return false } /** diff --git a/src/lib/litegraph/src/__snapshots__/LGraph.test.ts.snap b/src/lib/litegraph/src/__snapshots__/LGraph.test.ts.snap index 1a92319bb..0841fc96c 100644 --- a/src/lib/litegraph/src/__snapshots__/LGraph.test.ts.snap +++ b/src/lib/litegraph/src/__snapshots__/LGraph.test.ts.snap @@ -26,7 +26,6 @@ LGraph { "font_size": 14, "graph": [Circular], "id": 123, - "isPointInside": [Function], "selected": undefined, "setDirtyCanvas": [Function], "title": "A group to test with", diff --git a/src/renderer/extensions/vueNodes/components/NodeBadge.vue b/src/renderer/extensions/vueNodes/components/NodeBadge.vue index 064eac26d..52bada611 100644 --- a/src/renderer/extensions/vueNodes/components/NodeBadge.vue +++ b/src/renderer/extensions/vueNodes/components/NodeBadge.vue @@ -6,6 +6,7 @@ color: fgColor, backgroundColor: bgColor }" + @click="(e) => onClick?.(e)" > {{ text }} @@ -20,6 +21,7 @@ export interface NodeBadgeProps { fgColor?: LGraphBadge['fgColor'] bgColor?: LGraphBadge['bgColor'] cssIcon?: string + onClick?: (e: MouseEvent) => void } const {