Start of the rewrite to a modular system
This commit is contained in:
parent
2bfdc30caa
commit
4ac45367e5
29 changed files with 4414 additions and 588 deletions
170
static/js/button-generator/effects/hologram.js
Normal file
170
static/js/button-generator/effects/hologram.js
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
import { ButtonEffect } from '../effect-base.js';
|
||||
|
||||
/**
|
||||
* Hologram effect
|
||||
* Creates a futuristic holographic appearance with glitches and scan lines
|
||||
*/
|
||||
export class HologramEffect extends ButtonEffect {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'hologram',
|
||||
name: 'Hologram',
|
||||
type: 'general',
|
||||
category: 'Visual Effects',
|
||||
renderOrder: 88 // Near the end, after most other effects
|
||||
});
|
||||
}
|
||||
|
||||
defineControls() {
|
||||
return [
|
||||
{
|
||||
id: 'animate-hologram',
|
||||
type: 'checkbox',
|
||||
label: 'Hologram Effect',
|
||||
defaultValue: false,
|
||||
description: 'Futuristic holographic appearance'
|
||||
},
|
||||
{
|
||||
id: 'hologram-intensity',
|
||||
type: 'range',
|
||||
label: 'Effect Intensity',
|
||||
defaultValue: 50,
|
||||
min: 10,
|
||||
max: 100,
|
||||
step: 5,
|
||||
showWhen: 'animate-hologram',
|
||||
description: 'Strength of hologram effect'
|
||||
},
|
||||
{
|
||||
id: 'hologram-glitch-freq',
|
||||
type: 'range',
|
||||
label: 'Glitch Frequency',
|
||||
defaultValue: 30,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 10,
|
||||
showWhen: 'animate-hologram',
|
||||
description: 'How often glitches occur'
|
||||
},
|
||||
{
|
||||
id: 'hologram-color',
|
||||
type: 'color',
|
||||
label: 'Hologram Tint',
|
||||
defaultValue: '#00ffff',
|
||||
showWhen: 'animate-hologram',
|
||||
description: 'Color tint for hologram effect'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
isEnabled(controlValues) {
|
||||
return controlValues['animate-hologram'] === true;
|
||||
}
|
||||
|
||||
apply(context, controlValues, animState, renderData) {
|
||||
if (!animState) return;
|
||||
|
||||
const intensity = (controlValues['hologram-intensity'] || 50) / 100;
|
||||
const glitchFreq = (controlValues['hologram-glitch-freq'] || 30) / 100;
|
||||
const color = controlValues['hologram-color'] || '#00ffff';
|
||||
|
||||
// Get current canvas content
|
||||
const imageData = context.getImageData(0, 0, renderData.width, renderData.height);
|
||||
const data = imageData.data;
|
||||
|
||||
// Parse hologram color for tinting
|
||||
const hexColor = color.replace('#', '');
|
||||
const r = parseInt(hexColor.substr(0, 2), 16);
|
||||
const g = parseInt(hexColor.substr(2, 2), 16);
|
||||
const b = parseInt(hexColor.substr(4, 2), 16);
|
||||
|
||||
// Apply holographic tint
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
// Mix with hologram color
|
||||
data[i] = data[i] * (1 - intensity * 0.3) + r * intensity * 0.3; // Red
|
||||
data[i + 1] = data[i + 1] * (1 - intensity * 0.5) + g * intensity * 0.5; // Green (more cyan)
|
||||
data[i + 2] = data[i + 2] * (1 - intensity * 0.5) + b * intensity * 0.5; // Blue (more cyan)
|
||||
}
|
||||
|
||||
context.putImageData(imageData, 0, 0);
|
||||
|
||||
// Add horizontal scan lines
|
||||
context.globalAlpha = 0.05 * intensity;
|
||||
context.fillStyle = '#000000';
|
||||
for (let y = 0; y < renderData.height; y += 2) {
|
||||
context.fillRect(0, y, renderData.width, 1);
|
||||
}
|
||||
context.globalAlpha = 1.0;
|
||||
|
||||
// Add moving highlight scan line
|
||||
const scanY = (animState.progress * renderData.height) % renderData.height;
|
||||
const gradient = context.createLinearGradient(0, scanY - 3, 0, scanY + 3);
|
||||
gradient.addColorStop(0, 'rgba(0, 255, 255, 0)');
|
||||
gradient.addColorStop(0.5, `rgba(${r}, ${g}, ${b}, ${0.3 * intensity})`);
|
||||
gradient.addColorStop(1, 'rgba(0, 255, 255, 0)');
|
||||
context.fillStyle = gradient;
|
||||
context.fillRect(0, scanY - 3, renderData.width, 6);
|
||||
|
||||
// Random glitches
|
||||
if (Math.random() < glitchFreq * 0.1) {
|
||||
const glitchY = Math.floor(Math.random() * renderData.height);
|
||||
const glitchHeight = Math.floor(2 + Math.random() * 4);
|
||||
const offset = (Math.random() - 0.5) * 6 * intensity;
|
||||
|
||||
const sliceData = context.getImageData(0, glitchY, renderData.width, glitchHeight);
|
||||
context.putImageData(sliceData, offset, glitchY);
|
||||
}
|
||||
|
||||
// Add chromatic aberration on edges
|
||||
if (intensity > 0.3) {
|
||||
const originalImage = context.getImageData(0, 0, renderData.width, renderData.height);
|
||||
const aberration = 2 * intensity;
|
||||
|
||||
// Slight red shift right
|
||||
const redShift = context.getImageData(0, 0, renderData.width, renderData.height);
|
||||
for (let i = 0; i < redShift.data.length; i += 4) {
|
||||
const pixelIndex = i / 4;
|
||||
const x = pixelIndex % renderData.width;
|
||||
if (x < 3 || x > renderData.width - 3) {
|
||||
const sourceIndex = ((pixelIndex + Math.floor(aberration)) * 4);
|
||||
if (sourceIndex < originalImage.data.length) {
|
||||
redShift.data[i] = originalImage.data[sourceIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Slight blue shift left
|
||||
const blueShift = context.getImageData(0, 0, renderData.width, renderData.height);
|
||||
for (let i = 0; i < blueShift.data.length; i += 4) {
|
||||
const pixelIndex = i / 4;
|
||||
const x = pixelIndex % renderData.width;
|
||||
if (x < 3 || x > renderData.width - 3) {
|
||||
const sourceIndex = ((pixelIndex - Math.floor(aberration)) * 4);
|
||||
if (sourceIndex >= 0 && sourceIndex < originalImage.data.length) {
|
||||
blueShift.data[i + 2] = originalImage.data[sourceIndex + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.putImageData(redShift, 0, 0);
|
||||
context.globalCompositeOperation = 'screen';
|
||||
context.globalAlpha = 0.3;
|
||||
context.putImageData(blueShift, 0, 0);
|
||||
context.globalCompositeOperation = 'source-over';
|
||||
context.globalAlpha = 1.0;
|
||||
}
|
||||
|
||||
// Add flickering effect
|
||||
if (Math.random() < 0.05) {
|
||||
context.globalAlpha = 0.9 + Math.random() * 0.1;
|
||||
context.fillStyle = 'rgba(255, 255, 255, 0.05)';
|
||||
context.fillRect(0, 0, renderData.width, renderData.height);
|
||||
context.globalAlpha = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-register effect
|
||||
export function register(generator) {
|
||||
generator.registerEffect(new HologramEffect());
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue