144 lines
6.1 KiB
JavaScript
144 lines
6.1 KiB
JavaScript
/**
|
|
* Handles highlighting mapped widgets on the graph canvas.
|
|
*/
|
|
|
|
import { app } from '../../../scripts/app.js';
|
|
import { contextProvider } from '../core/contextProvider.js';
|
|
import { eventBus } from '../core/eventBus.js';
|
|
|
|
// Attempt to get LiteGraph from the global scope or app instance
|
|
const LiteGraph = window.LiteGraph || (app ? app.LiteGraph : null);
|
|
|
|
let original_drawNodeWidgets = null;
|
|
let isHighlightingActive = false;
|
|
|
|
/**
|
|
* Applies the global patch to LGraphCanvas.drawNodeWidgets to enable highlighting.
|
|
*/
|
|
function applyWidgetHighlightPatch() {
|
|
if (!LiteGraph || !LiteGraph.LGraphCanvas || !LiteGraph.LGraphCanvas.prototype?.drawNodeWidgets) {
|
|
console.error("ControlFreak: Cannot apply widget highlight patch. LGraphCanvas.drawNodeWidgets not found.");
|
|
return;
|
|
}
|
|
|
|
if (original_drawNodeWidgets) {
|
|
console.warn("ControlFreak: Widget highlight patch already applied.");
|
|
return; // Already patched
|
|
}
|
|
|
|
original_drawNodeWidgets = LiteGraph.LGraphCanvas.prototype.drawNodeWidgets;
|
|
|
|
LiteGraph.LGraphCanvas.prototype.drawNodeWidgets = function(node) {
|
|
// --- Draw Highlights FIRST (Behind Widgets) ---
|
|
if (node.widgets && node.widgets.length > 0 && isHighlightingActive) {
|
|
const mappingEngine = contextProvider.get('mappingEngine');
|
|
if (mappingEngine) { // Check if mapping engine is available
|
|
const ctx = this.ctx; // Get canvas context from LGraphCanvas instance
|
|
try {
|
|
const brandColor = getComputedStyle(document.documentElement).getPropertyValue('--cf-brand-primary').trim() || '#ff5722';
|
|
const colorParts = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(brandColor);
|
|
// Slightly more transparent for a background glow
|
|
const widgetHighlightColor = colorParts
|
|
? `rgba(${parseInt(colorParts[1], 16)}, ${parseInt(colorParts[2], 16)}, ${parseInt(colorParts[3], 16)}, 0.25)`
|
|
: "rgba(255, 87, 34, 0.25)";
|
|
|
|
node.widgets.forEach(widget => {
|
|
if (mappingEngine.isWidgetMapped(node.id, widget.name)) {
|
|
if (typeof widget.last_y === 'number') {
|
|
const widgetHeight = (widget.size && widget.size[1] > 0) ? widget.size[1] : (LiteGraph.NODE_WIDGET_HEIGHT || 20);
|
|
const nodeWidth = node.size[0];
|
|
const padding = 15;
|
|
const widgetY = widget.last_y;
|
|
const widgetX = padding / 2;
|
|
const widgetWidth = nodeWidth - padding;
|
|
|
|
if (widgetWidth > 0 && widgetHeight > 0) {
|
|
// Save context state
|
|
ctx.save();
|
|
ctx.fillStyle = widgetHighlightColor;
|
|
ctx.beginPath();
|
|
// Draw slightly larger rect behind the widget area
|
|
const margin = 3; // How much larger the highlight is
|
|
ctx.roundRect(widgetX - margin, widgetY - margin, widgetWidth + (margin * 2), widgetHeight + (margin * 2), 5); // Increased radius slightly
|
|
ctx.fill();
|
|
ctx.restore();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
} catch (e) {
|
|
console.error(`ControlFreak: Error drawing highlights for node ${node.id}:`, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- Call the original function AFTER drawing highlights ---
|
|
let result;
|
|
try {
|
|
result = original_drawNodeWidgets.apply(this, arguments);
|
|
} catch (e) {
|
|
console.error(`ControlFreak: Error in original drawNodeWidgets for node ${node.id}:`, e);
|
|
}
|
|
|
|
return result;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Removes the global patch from LGraphCanvas.drawNodeWidgets.
|
|
*/
|
|
function removeWidgetHighlightPatch() {
|
|
if (original_drawNodeWidgets && LiteGraph && LiteGraph.LGraphCanvas && LiteGraph.LGraphCanvas.prototype) {
|
|
LiteGraph.LGraphCanvas.prototype.drawNodeWidgets = original_drawNodeWidgets;
|
|
original_drawNodeWidgets = null;
|
|
// Request redraw to remove highlights
|
|
if(app.graph) app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes the widget highlighter system.
|
|
* Applies the patch and sets up event listeners to trigger redraws.
|
|
*/
|
|
export function initWidgetHighlighter() {
|
|
if (!LiteGraph) {
|
|
console.error("ControlFreak: LiteGraph not available, cannot initialize widget highlighter.");
|
|
return;
|
|
}
|
|
applyWidgetHighlightPatch();
|
|
isHighlightingActive = true; // Activate highlighting
|
|
|
|
// Listen for events that change mappings and trigger redraw
|
|
const redrawCanvas = () => {
|
|
// Check if graph exists and has changed before forcing redraw
|
|
if(app.graph) { // && app.graph.status !== LGraph.STATUS_STOPPED - add if needed
|
|
app.graph.setDirtyCanvas(true, false); // Redraw only, don't recompute paths
|
|
}
|
|
};
|
|
|
|
// Debounce redraw calls slightly to prevent excessive redraws during rapid changes
|
|
let redrawTimeout = null;
|
|
const debouncedRedraw = () => {
|
|
if (redrawTimeout) clearTimeout(redrawTimeout);
|
|
redrawTimeout = setTimeout(redrawCanvas, 50); // 50ms debounce
|
|
};
|
|
|
|
eventBus.on('mapping:created', debouncedRedraw);
|
|
eventBus.on('mapping:deleted', debouncedRedraw);
|
|
eventBus.on('mappings:loaded', debouncedRedraw);
|
|
eventBus.on('mappings:profileChanged', debouncedRedraw);
|
|
// Also redraw if a mapping is updated (e.g., settings changed)
|
|
eventBus.on('mapping:updated', debouncedRedraw);
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Cleans up the widget highlighter system.
|
|
* Removes the patch and potentially event listeners if needed.
|
|
*/
|
|
export function cleanupWidgetHighlighter() {
|
|
removeWidgetHighlightPatch();
|
|
isHighlightingActive = false;
|
|
}
|