Files
AEmotionStudio-ComfyUI-Shad…/web/gradient_title.js
T

176 lines
8.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { shouldUpdateFrame, resetShadowContext, createTitleGradient, calculateShimmerPosition, TITLE_CORNER_RADIUS, } from './golden_eyeball.js';
// Cache for rendering optimization (uses shared AnimationCache interface)
const CACHE = {
lastTime: 0,
frameCount: 0,
frameSkip: 2, // Only update animation every X frames
};
// Import app from ComfyUI at runtime (this import is resolved by the browser)
// @ts-ignore - ComfyUI provides this at runtime
import { app } from '../../scripts/app.js';
// Define the extension
const extension = {
name: 'ShaderNoiseKSampler.GradientTitle',
async beforeRegisterNodeDef(nodeType, nodeData, _app) {
// Apply to both shader noise ksampler nodes
if (nodeData.name === 'ShaderNoiseKSampler' ||
nodeData.name === 'ShaderNoiseKSamplerDirect') {
// Store the original onDrawForeground function if it exists
const origOnDrawForeground = nodeType.prototype.onDrawForeground;
// Add our own onDrawForeground function
nodeType.prototype.onDrawForeground = function (ctx) {
// Draw gradient title FIRST so it acts as background layer
drawGradientTitle(this, ctx);
// Call the original onDrawForeground after, so shader renders on top
if (origOnDrawForeground) {
origOnDrawForeground.call(this, ctx);
}
};
// Clean up resources when node is removed
const origOnRemoved = nodeType.prototype.onRemoved;
nodeType.prototype.onRemoved = function () {
if (origOnRemoved) {
origOnRemoved.call(this);
}
// Note: CACHE only holds animation timing state, no cleanup needed
};
}
},
};
// Register the extension
app.registerExtension(extension);
/**
* Draws a gradient title directly on the canvas
* @param node - The node to apply the gradient to
* @param ctx - The canvas context
*/
function drawGradientTitle(node, ctx) {
// Get title area dimensions
const titleHeight = node.flags.collapsed ? 20 : 30; // Smaller height when collapsed
const width = node.flags.collapsed ? 190 : node.size[0]; // Smaller width when collapsed
const fullHeight = node.size[1]; // Get actual node height
const equationY = 45; // Y position for the equation, moved lower
// Choose appropriate equation based on node type
let equation;
let collapsedEquation;
if (node.type === 'ShaderNoiseKSamplerDirect') {
equation = 'Lt = Sα(N) ∘ Kβ(t) ⟿';
collapsedEquation = 'Lt = Sα(N) ∘ Kβ(t) ⟿';
}
else {
equation = 'Lt = Sα(N) ∘ Kβ(t)';
collapsedEquation = 'Lt = Sα(N) ∘ Kβ(t)';
}
// Update animation frame counter using shared utility
const shouldUpdateAnimation = shouldUpdateFrame(CACHE);
// Save current state
ctx.save();
// Reset shadow properties using shared utility
resetShadowContext(ctx);
// Create vertical background gradient using shared utility
const gradient = createTitleGradient(ctx, fullHeight);
// Calculate shimmer position (always compute for smooth animation)
const shimmerPosition = calculateShimmerPosition(1.0);
if (shouldUpdateAnimation) {
CACHE.lastTime = Date.now() / 3000;
}
// Add collapse button handler
if (node.flags.collapsed) {
// If node is collapsed, adjust the title rendering
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, titleHeight);
// Draw etched shadow for collapsed version
ctx.fillStyle = 'rgba(0,0,0,0.3)';
ctx.font = 'italic 11px Arial'; // Smaller font for collapsed state
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(collapsedEquation, width / 2 + 1, titleHeight / 2 + 1);
// Create base golden gradient for collapsed version
const baseGradient = ctx.createLinearGradient(0, titleHeight / 2 - 5, 0, titleHeight / 2 + 5);
baseGradient.addColorStop(0, '#B8860B'); // Darker gold
baseGradient.addColorStop(0.5, '#FFD700'); // Bright gold
baseGradient.addColorStop(1, '#B8860B'); // Darker gold
// Draw base golden text
ctx.fillStyle = baseGradient;
ctx.font = 'italic 11px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(collapsedEquation, width / 2, titleHeight / 2);
// Create moving highlight effect for collapsed version
const highlightWidth = width * 0.4; // Width of the highlight
const highlightX = -highlightWidth + (width + highlightWidth) * shimmerPosition; // Adjusted range
const shimmerGradient = ctx.createLinearGradient(highlightX - highlightWidth / 2, 0, highlightX + highlightWidth / 2, 0);
// Create smooth highlight transition
shimmerGradient.addColorStop(0, 'rgba(255, 255, 200, 0)');
shimmerGradient.addColorStop(0.1, 'rgba(255, 255, 200, 0)');
shimmerGradient.addColorStop(0.5, 'rgba(255, 255, 200, 0.3)');
shimmerGradient.addColorStop(0.9, 'rgba(255, 255, 200, 0)');
shimmerGradient.addColorStop(1, 'rgba(255, 255, 200, 0)');
// Apply highlight
ctx.fillStyle = shimmerGradient;
ctx.fillText(collapsedEquation, width / 2, titleHeight / 2);
// Add outline glow that follows the highlight
const glowIntensity = Math.max(0, 1 - Math.abs(width / 2 - highlightX) / (width / 4));
ctx.shadowColor = `rgba(255, 255, 200, ${glowIntensity * 0.3})`;
ctx.shadowBlur = 4; // Less blur for collapsed version
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.fillText(collapsedEquation, width / 2, titleHeight / 2);
// Skip the rest of the rendering when collapsed
ctx.restore();
return;
}
// Draw background that fills the entire node (non-collapsed state, reached after early return above)
ctx.fillStyle = gradient;
// Use rounded rectangle for the background with rounded corners at the bottom
ctx.beginPath();
ctx.moveTo(0, 0); // Start at top-left
ctx.lineTo(width, 0); // Top edge
ctx.lineTo(width, fullHeight - TITLE_CORNER_RADIUS); // Right edge before bottom-right corner
ctx.arcTo(width, fullHeight, width - TITLE_CORNER_RADIUS, fullHeight, TITLE_CORNER_RADIUS); // Bottom-right rounded corner
ctx.lineTo(TITLE_CORNER_RADIUS, fullHeight); // Bottom edge before bottom-left corner
ctx.arcTo(0, fullHeight, 0, fullHeight - TITLE_CORNER_RADIUS, TITLE_CORNER_RADIUS); // Bottom-left rounded corner
ctx.lineTo(0, 0); // Left edge back to top
ctx.closePath();
ctx.fill();
// Draw etched shadow
ctx.fillStyle = 'rgba(0,0,0,0.3)';
ctx.font = 'italic 14px Arial'; // Smaller font for equation
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(equation, width / 2 + 2, equationY + 2);
// Create base golden gradient
const baseGradient = ctx.createLinearGradient(0, equationY - 7, 0, equationY + 7);
baseGradient.addColorStop(0, '#B8860B'); // Darker gold
baseGradient.addColorStop(0.5, '#FFD700'); // Bright gold
baseGradient.addColorStop(1, '#B8860B'); // Darker gold
// Draw base golden text
ctx.fillStyle = baseGradient;
ctx.font = 'italic 14px Arial'; // Smaller font for equation
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(equation, width / 2, equationY);
// Create moving highlight effect
const highlightWidth = width * 0.4; // Width of the highlight
const highlightX = -highlightWidth + (width + highlightWidth) * shimmerPosition; // Adjusted range
const shimmerGradient = ctx.createLinearGradient(highlightX - highlightWidth / 2, 0, highlightX + highlightWidth / 2, 0);
// Create smooth highlight transition
shimmerGradient.addColorStop(0, 'rgba(255, 255, 200, 0)');
shimmerGradient.addColorStop(0.1, 'rgba(255, 255, 200, 0)');
shimmerGradient.addColorStop(0.5, 'rgba(255, 255, 200, 0.3)');
shimmerGradient.addColorStop(0.9, 'rgba(255, 255, 200, 0)');
shimmerGradient.addColorStop(1, 'rgba(255, 255, 200, 0)');
// Apply highlight
ctx.fillStyle = shimmerGradient;
ctx.fillText(equation, width / 2, equationY);
// Add outline glow that follows the highlight
const glowIntensity = Math.max(0, 1 - Math.abs(width / 2 - highlightX) / (width / 4));
ctx.shadowColor = `rgba(255, 255, 200, ${glowIntensity * 0.3})`;
ctx.shadowBlur = 8;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.fillText(equation, width / 2, equationY);
// Restore context state
ctx.restore();
}
//# sourceMappingURL=gradient_title.js.map