79 lines
1.9 KiB
JavaScript
79 lines
1.9 KiB
JavaScript
import { ButtonEffect } from '../effect-base.js';
|
|
|
|
/**
|
|
* Scanline effect
|
|
* Creates CRT-style horizontal lines
|
|
*/
|
|
export class ScanlineEffect extends ButtonEffect {
|
|
constructor() {
|
|
super({
|
|
id: 'scanline',
|
|
name: 'Scanline',
|
|
type: 'general',
|
|
category: 'Visual Effects',
|
|
renderOrder: 75
|
|
});
|
|
}
|
|
|
|
defineControls() {
|
|
return [
|
|
{
|
|
id: 'animate-scanline',
|
|
type: 'checkbox',
|
|
label: 'Scanline Effect',
|
|
defaultValue: false
|
|
},
|
|
{
|
|
id: 'scanline-intensity',
|
|
type: 'range',
|
|
label: 'Scanline Intensity',
|
|
defaultValue: 0.3,
|
|
min: 0.1,
|
|
max: 0.8,
|
|
step: 0.05,
|
|
showWhen: 'animate-scanline',
|
|
description: 'Darkness of scanlines'
|
|
},
|
|
{
|
|
id: 'scanline-speed',
|
|
type: 'range',
|
|
label: 'Scanline Speed',
|
|
defaultValue: 1,
|
|
min: 0.1,
|
|
max: 3,
|
|
step: 0.1,
|
|
showWhen: 'animate-scanline',
|
|
description: 'Movement speed of scanlines'
|
|
}
|
|
];
|
|
}
|
|
|
|
isEnabled(controlValues) {
|
|
return controlValues['animate-scanline'] === true;
|
|
}
|
|
|
|
apply(context, controlValues, animState, renderData) {
|
|
if (!animState) return;
|
|
|
|
const intensity = controlValues['scanline-intensity'] || 0.3;
|
|
const speed = controlValues['scanline-speed'] || 1;
|
|
|
|
// Create overlay with scanlines
|
|
context.globalCompositeOperation = 'multiply';
|
|
context.fillStyle = `rgba(0, 0, 0, ${intensity})`;
|
|
|
|
// Animate scanline position
|
|
const offset = (animState.progress * speed * renderData.height) % 2;
|
|
|
|
for (let y = offset; y < renderData.height; y += 2) {
|
|
context.fillRect(0, Math.floor(y), renderData.width, 1);
|
|
}
|
|
|
|
context.globalCompositeOperation = 'source-over';
|
|
}
|
|
}
|
|
|
|
// Auto-register effect
|
|
export function register(generator) {
|
|
generator.registerEffect(new ScanlineEffect());
|
|
}
|