feat: improve canvas highlight hook robustness and update node highlight style to a thicker blue border.

This commit is contained in:
AEmotionStudio
2026-01-05 17:34:42 -08:00
parent 444614f574
commit c8ac92e7d3
3 changed files with 90 additions and 40 deletions
+51 -22
View File
@@ -37,21 +37,18 @@ export class CanvasHighlighter {
this.originalOnDrawForeground = canvas.onDrawForeground;
// Override
canvas.onDrawForeground = (ctx: CanvasRenderingContext2D, visible_nodes: any) => {
// Call original first
if (this.originalOnDrawForeground) {
this.originalOnDrawForeground.call(canvas, ctx, visible_nodes);
}
// Draw our highlight
this.drawHighlight(ctx, canvas.ds.scale);
};
canvas.onDrawForeground = this.boundOnDrawForeground;
}
/**
* Set the node ID to highlight.
*/
/**
* Set the node ID to highlight.
*/
setHighlightedNode(nodeId: number | null): void {
this.ensureHook(); // Ensure we are still hooked
if (this.highlightedNodeId === nodeId) return;
this.highlightedNodeId = nodeId;
// Force redraw to update highlight immediately
@@ -61,6 +58,35 @@ export class CanvasHighlighter {
}
}
/**
* Ensure the canvas hook is active.
*/
private ensureHook(): void {
const app = (window as any).app;
if (!app || !app.canvas) return;
// If our hook was overwritten (e.g. by another extension), re-hook
if (app.canvas.onDrawForeground !== this.boundOnDrawForeground) {
// console.log('[MagnifyGlass] Re-hooking CanvasHighlighter');
this.originalOnDrawForeground = app.canvas.onDrawForeground;
app.canvas.onDrawForeground = this.boundOnDrawForeground;
}
}
// Bound method to preserve 'this' and allow equality check
private boundOnDrawForeground = (ctx: CanvasRenderingContext2D, visible_nodes: any) => {
// Call original first
if (this.originalOnDrawForeground) {
this.originalOnDrawForeground.call((window as any).app.canvas, ctx, visible_nodes);
}
// Draw our highlight
const app = (window as any).app;
if (app && app.canvas) {
this.drawHighlight(ctx, app.canvas.ds.scale);
}
};
/**
* Draw the highlight rectangle around the target node.
*/
@@ -78,23 +104,24 @@ export class CanvasHighlighter {
// Note: ctx passed to onDrawForeground is already transformed by LiteGraph to graph coordinates
// so we can draw using node.pos directly.
const x = node.pos[0] - this.HIGHLIGHT_PADDING;
const y = node.pos[1] - this.HIGHLIGHT_PADDING;
const w = node.size[0] + (this.HIGHLIGHT_PADDING * 2);
const h = node.size[1] + (this.HIGHLIGHT_PADDING * 2);
const padding = 10;
const x = node.pos[0] - padding;
const y = node.pos[1] - padding;
const w = node.size[0] + (padding * 2);
const h = node.size[1] + (padding * 2);
// Draw glow/outline
ctx.lineWidth = this.HIGHLIGHT_WIDTH;
ctx.strokeStyle = this.HIGHLIGHT_COLOR;
ctx.shadowColor = this.HIGHLIGHT_COLOR;
ctx.shadowBlur = 10 * scale; // Scale shadow with zoom
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
// Draw large blue bar/border
ctx.lineWidth = 10; // Thicker border
ctx.strokeStyle = '#007bff'; // Blue
// ctx.shadowColor = '#007bff'; // Optional glow
// ctx.shadowBlur = 0;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
// Use roundRect if available (modern browsers), else rect
ctx.beginPath();
if (typeof ctx.roundRect === 'function') {
const radius = 10; // LiteGraph nodes usually have round corners
const radius = 10;
ctx.roundRect(x, y, w, h, radius);
} else {
ctx.rect(x, y, w, h);
@@ -111,7 +138,9 @@ export class CanvasHighlighter {
cleanup(): void {
const app = (window as any).app;
if (app && app.canvas && this.originalOnDrawForeground) {
app.canvas.onDrawForeground = this.originalOnDrawForeground;
if (app.canvas.onDrawForeground === this.boundOnDrawForeground) {
app.canvas.onDrawForeground = this.originalOnDrawForeground;
}
}
}
}
+38 -17
View File
@@ -12,6 +12,16 @@ class CanvasHighlighter {
__publicField(this, "HIGHLIGHT_WIDTH", 2);
// px
__publicField(this, "HIGHLIGHT_PADDING", 0);
// Bound method to preserve 'this' and allow equality check
__publicField(this, "boundOnDrawForeground", (ctx, visible_nodes) => {
if (this.originalOnDrawForeground) {
this.originalOnDrawForeground.call(window.app.canvas, ctx, visible_nodes);
}
const app = window.app;
if (app && app.canvas) {
this.drawHighlight(ctx, app.canvas.ds.scale);
}
});
this.hookCanvas();
}
/**
@@ -25,17 +35,16 @@ class CanvasHighlighter {
}
const canvas = app.canvas;
this.originalOnDrawForeground = canvas.onDrawForeground;
canvas.onDrawForeground = (ctx, visible_nodes) => {
if (this.originalOnDrawForeground) {
this.originalOnDrawForeground.call(canvas, ctx, visible_nodes);
}
this.drawHighlight(ctx, canvas.ds.scale);
};
canvas.onDrawForeground = this.boundOnDrawForeground;
}
/**
* Set the node ID to highlight.
*/
/**
* Set the node ID to highlight.
*/
setHighlightedNode(nodeId) {
this.ensureHook();
if (this.highlightedNodeId === nodeId) return;
this.highlightedNodeId = nodeId;
const app = window.app;
@@ -43,6 +52,17 @@ class CanvasHighlighter {
app.canvas.setDirty(true, true);
}
}
/**
* Ensure the canvas hook is active.
*/
ensureHook() {
const app = window.app;
if (!app || !app.canvas) return;
if (app.canvas.onDrawForeground !== this.boundOnDrawForeground) {
this.originalOnDrawForeground = app.canvas.onDrawForeground;
app.canvas.onDrawForeground = this.boundOnDrawForeground;
}
}
/**
* Draw the highlight rectangle around the target node.
*/
@@ -53,16 +73,15 @@ class CanvasHighlighter {
const node = app.graph.getNodeById(this.highlightedNodeId);
if (!node) return;
ctx.save();
const x = node.pos[0] - this.HIGHLIGHT_PADDING;
const y = node.pos[1] - this.HIGHLIGHT_PADDING;
const w = node.size[0] + this.HIGHLIGHT_PADDING * 2;
const h = node.size[1] + this.HIGHLIGHT_PADDING * 2;
ctx.lineWidth = this.HIGHLIGHT_WIDTH;
ctx.strokeStyle = this.HIGHLIGHT_COLOR;
ctx.shadowColor = this.HIGHLIGHT_COLOR;
ctx.shadowBlur = 10 * scale;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
const padding = 10;
const x = node.pos[0] - padding;
const y = node.pos[1] - padding;
const w = node.size[0] + padding * 2;
const h = node.size[1] + padding * 2;
ctx.lineWidth = 10;
ctx.strokeStyle = "#007bff";
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.beginPath();
if (typeof ctx.roundRect === "function") {
const radius = 10;
@@ -79,7 +98,9 @@ class CanvasHighlighter {
cleanup() {
const app = window.app;
if (app && app.canvas && this.originalOnDrawForeground) {
app.canvas.onDrawForeground = this.originalOnDrawForeground;
if (app.canvas.onDrawForeground === this.boundOnDrawForeground) {
app.canvas.onDrawForeground = this.originalOnDrawForeground;
}
}
}
}
File diff suppressed because one or more lines are too long