Drawaria Layer Animation System

Adds a layer-based animation system to Drawaria, create and manage multiple drawing layers with PokeAPI integration

// ==UserScript==
// @name         Drawaria Layer Animation System
// @namespace    http://tampermonkey.net/
// @version      3.6
// @description  Adds a layer-based animation system to Drawaria, create and manage multiple drawing layers with PokeAPI integration
// @author       YouTubeDrawaria
// @match        *://drawaria.online/*
// @match        *://*.drawaria.online/*
// @grant        none
// @run-at       document-idle
// @license MIT
// @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// ==/UserScript==

(function() {
    'use strict';

    class RealLayerAnimationSystem {
        constructor() {
            this.layers = [{ commands: [], visible: true, name: 'Layer 1' }];
            this.currentLayer = 0;
            this.isDrawing = false;
            this.lastX = 0;
            this.lastY = 0;
            this.isAnimating = false;
            this.animationSpeed = 50;

            this.isLoopEnabled = false;

            // Nueva variable para controlar la calidad de importación
            this.highQualityImport = false;
            this.pixelProcessingStep = 2;
            this.targetImageResolution = 100;

            this.gameCanvas = null;
            this.gameCtx = null;
            this.previewCanvas = null;
            this.previewCtx = null;

            this.gameSocket = null;
            this.onionOpacity = 0.3;
            this.menuVisible = false;

            this.init();
        }

        init() {
            this.captureGameWebSocket();
            this.waitForGameCanvas();
            this.createCompactInterface();
            this.setupEventListeners();
        }

        // ... [mantengo todos los métodos existentes sin cambios hasta setupEventListeners]

        captureGameWebSocket() {
            const originalSend = WebSocket.prototype.send;
            WebSocket.prototype.send = function (...args) {
                if (!this.url || !this.url.includes('drawaria')) {
                    return originalSend.apply(this, args);
                }

                if (!window.layerAnimationSocket) {
                    window.layerAnimationSocket = this;
                    console.log('✅ WebSocket capturado para Layer Animation');
                }

                return originalSend.apply(this, args);
            };

            const checkExisting = () => {
                if (window.layerAnimationSocket && window.layerAnimationSocket.readyState === 1) {
                    this.gameSocket = window.layerAnimationSocket;
                    this.updateSocketStatus();
                    return;
                }
                setTimeout(checkExisting, 1000);
            };
            checkExisting();
        }

        sendRealDrawCommand(x1, y1, x2, y2, color, thickness) {
            if (!this.gameSocket || this.gameSocket.readyState !== 1) return false;

            const normX1 = (x1 / this.gameCanvas.width).toFixed(4);
            const normY1 = (y1 / this.gameCanvas.height).toFixed(4);
            const normX2 = (x2 / this.gameCanvas.width).toFixed(4);
            const normY2 = (y2 / this.gameCanvas.height).toFixed(4);

            const command = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${0 - thickness},"${color}",0,0,{}]]`;

            try {
                this.gameSocket.send(command);
                return true;
            } catch (error) {
                console.error('Error enviando comando:', error);
                return false;
            }
        }

        waitForGameCanvas() {
            const checkCanvas = () => {
                this.gameCanvas = document.getElementById('canvas');
                if (this.gameCanvas) {
                    this.gameCtx = this.gameCanvas.getContext('2d');
                    this.setupPreviewCanvas();
                } else {
                    setTimeout(checkCanvas, 100);
                }
            };
            checkCanvas();
        }

        setupPreviewCanvas() {
            this.previewCanvas = document.createElement('canvas');
            this.previewCtx = this.previewCanvas.getContext('2d');
            this.previewCanvas.width = 220;
            this.previewCanvas.height = 160;
            this.previewCanvas.id = 'layerPreviewCanvas';

            this.previewCtx.lineCap = 'round';
            this.previewCtx.lineJoin = 'round';
        }

        createCompactInterface() {
            const html = `
                <!-- Toggle Button -->
                <div id="layerToggleBtn" class="layer-toggle">🎬</div>

                <!-- Compact Panel -->
                <div id="layerCompactPanel" class="layer-compact-panel">
                    <div class="compact-header">
                        Layer Animator <span id="socketIndicator">⚫</span>
                    </div>

                    <div class="compact-canvas">
                        <div id="previewContainer"></div>
                    </div>

                    <div class="compact-controls">
                        <div class="layer-nav-compact">
                            <button id="prevLayer">◀</button>
                            <span id="layerInfo">1/1</span>
                            <button id="nextLayer">▶</button>
                        </div>

                        <div class="layer-actions-compact">
                            <button id="addLayer" title="Add Layer">➕</button>
                            <button id="removeLayer" title="Remove Layer">➖</button>
                            <button id="clearLayer" title="Clear Layer">🗑️</button>
                            <button id="duplicateLayer" title="Duplicate Layer">📋</button>
                            <button id="toggleLoopBtn" title="Toggle Loop Animation">🔄</button>
                            <button id="toggleQualityBtn" title="Toggle High Quality Image Import">⭐</button>
                            <button id="importImageBtn" title="Import Image(s)">🏞️</button>
                            <button id="loadPokemonBtn" title="Load Random Pokemon Pixel Art">🎮</button>
                            <input type="file" id="imageFileInput" multiple accept="image/*" style="display: none;">
                        </div>
                    </div>

                    <div class="onion-compact">
                        <label><input type="checkbox" id="onionToggle" checked> Onion</label>
                        <input type="range" id="onionRange" min="10" max="100" value="30">
                    </div>

                    <div class="animation-compact">
                        <button id="playBtn" class="play-btn-compact">▶️ PLAY</button>
                        <button id="stopBtn" class="stop-btn-compact" disabled>⏹️ STOP</button>

                        <div class="speed-compact">
                            <label class="speed-label">Speed: <span id="speedValue">18</span>ms</label>
                            <input type="range" id="speedRange" min="3" max="500" value="18" class="speed-slider">
                        </div>
                    </div>

                    <div class="layer-list-compact" id="layerListCompact"></div>
                </div>
            `;

            document.body.insertAdjacentHTML('beforeend', html);

            const container = document.getElementById('previewContainer');
            if (container && this.previewCanvas) {
                container.appendChild(this.previewCanvas);
            }

            this.addCompactStyles();
            this.updateLayerList();
            this.updateOnionSkin();
            this.updateSocketStatus();
            this.updateLoopButtonState();
            this.updateQualityButtonState();
        }

        addCompactStyles() {
            const css = `
                .layer-toggle {
                    position: fixed;
                    top: 10px;
                    right: 10px;
                    width: 40px;
                    height: 40px;
                    background: linear-gradient(45deg, #4CAF50, #45a049);
                    color: white;
                    border: none;
                    border-radius: 50%;
                    cursor: pointer;
                    z-index: 10000;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    font-size: 18px;
                    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                    transition: all 0.3s ease;
                }

                .layer-toggle:hover {
                    transform: scale(1.1);
                }

                .layer-compact-panel {
                    position: fixed;
                    top: 60px;
                    right: 10px;
                    width: 260px;
                    background: linear-gradient(145deg, #2a2a2a, #1e1e1e);
                    border: 2px solid #4CAF50;
                    border-radius: 10px;
                    padding: 12px;
                    z-index: 9999;
                    font-family: 'Arial', sans-serif;
                    color: #fff;
                    font-size: 12px;
                    box-shadow: 0 8px 32px rgba(0,0,0,0.4);
                    display: none;
                }

                .compact-header {
                    text-align: center;
                    font-weight: bold;
                    margin-bottom: 10px;
                    color: #4CAF50;
                    border-bottom: 1px solid #444;
                    padding-bottom: 5px;
                }

                .compact-canvas {
                    margin-bottom: 10px;
                }

                #layerPreviewCanvas {
                    width: 100%;
                    height: 120px;
                    border: 2px solid #555;
                    border-radius: 5px;
                    background: white;
                    cursor: crosshair;
                    display: block;
                }

                .compact-controls {
                    display: flex;
                    flex-direction: column;
                    gap: 8px;
                    margin-bottom: 10px;
                }

                .layer-nav-compact {
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    gap: 12px;
                }

                .layer-nav-compact button {
                    background: #4CAF50;
                    border: none;
                    color: white;
                    padding: 6px 10px;
                    border-radius: 4px;
                    cursor: pointer;
                    font-size: 12px;
                    transition: background 0.3s;
                }

                .layer-nav-compact button:hover:not(:disabled) {
                    background: #45a049;
                }

                .layer-nav-compact button:disabled {
                    background: #666;
                    cursor: not-allowed;
                }

                #layerInfo {
                    background: #333;
                    padding: 6px 12px;
                    border-radius: 4px;
                    min-width: 50px;
                    text-align: center;
                    font-size: 11px;
                    font-weight: bold;
                }

                .layer-actions-compact {
                    display: flex;
                    flex-wrap: wrap;
                    justify-content: center;
                    gap: 6px;
                }

                .layer-actions-compact button {
                    background: #555;
                    border: none;
                    color: white;
                    padding: 6px 8px;
                    border-radius: 4px;
                    cursor: pointer;
                    font-size: 12px;
                    transition: all 0.2s;
                    min-width: 30px;
                    text-align: center;
                }

                .layer-actions-compact button:hover:not(:disabled) {
                    background: #777;
                    transform: scale(1.05);
                }

                .layer-actions-compact button:disabled {
                    opacity: 0.5;
                    cursor: not-allowed;
                }

                #toggleLoopBtn.active, #toggleQualityBtn.active {
                    background: linear-gradient(45deg, #FFD700, #DAA520);
                    color: #333;
                }

                #loadPokemonBtn {
                    background: linear-gradient(45deg, #FF6B35, #F7931E);
                    color: white;
                    animation: pokemonGlow 2s infinite alternate;
                }

                #loadPokemonBtn:hover:not(:disabled) {
                    background: linear-gradient(45deg, #F7931E, #FF6B35);
                    transform: scale(1.1);
                }

                @keyframes pokemonGlow {
                    0% { box-shadow: 0 0 5px rgba(255,107,53,0.5); }
                    100% { box-shadow: 0 0 15px rgba(255,107,53,0.8); }
                }

                .onion-compact {
                    background: #333;
                    padding: 8px;
                    border-radius: 5px;
                    margin-bottom: 10px;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                }

                .onion-compact label {
                    font-size: 11px;
                }

                .onion-compact input[type="range"] {
                    width: 70px;
                }

                .animation-compact {
                    margin-bottom: 10px;
                }

                .play-btn-compact, .stop-btn-compact {
                    width: 100%;
                    padding: 10px;
                    margin-bottom: 8px;
                    border: none;
                    border-radius: 6px;
                    font-size: 12px;
                    font-weight: bold;
                    cursor: pointer;
                    transition: all 0.3s;
                }

                .play-btn-compact {
                    background: linear-gradient(45deg, #4CAF50, #45a049);
                    color: white;
                }

                .stop-btn-compact {
                    background: linear-gradient(45deg, #f44336, #da190b);
                    color: white;
                }

                .play-btn-compact:hover:not(:disabled) {
                    transform: scale(1.02);
                }

                .stop-btn-compact:hover:not(:disabled) {
                    transform: scale(1.02);
                }

                .play-btn-compact:disabled, .stop-btn-compact:disabled {
                    opacity: 0.5;
                    cursor: not-allowed;
                    transform: none;
                }

                .speed-compact {
                    background: #444;
                    padding: 8px;
                    border-radius: 5px;
                    text-align: center;
                }

                .speed-label {
                    display: block;
                    font-size: 11px;
                    margin-bottom: 5px;
                    color: #ccc;
                }

                .speed-slider {
                    width: 100%;
                    height: 4px;
                    background: #666;
                    outline: none;
                    border-radius: 2px;
                    cursor: pointer;
                }

                .speed-slider::-webkit-slider-thumb {
                    appearance: none;
                    width: 14px;
                    height: 14px;
                    background: #4CAF50;
                    border-radius: 50%;
                    cursor: pointer;
                }

                .speed-slider::-moz-range-thumb {
                    width: 14px;
                    height: 14px;
                    background: #4CAF50;
                    border-radius: 50%;
                    cursor: pointer;
                    border: none;
                }

                #speedValue {
                    font-weight: bold;
                    color: #4CAF50;
                }

                .layer-list-compact {
                    max-height: 120px;
                    overflow-y: auto;
                    background: #2a2a2a;
                    border-radius: 5px;
                    padding: 4px;
                }

                .layer-item-compact {
                    padding: 5px 8px;
                    border-bottom: 1px solid #444;
                    cursor: pointer;
                    font-size: 10px;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    border-radius: 3px;
                    transition: background 0.2s;
                }

                .layer-item-compact:hover {
                    background: #3a3a3a;
                }

                .layer-item-compact.active {
                    background: #4CAF50;
                    color: white;
                    font-weight: bold;
                }

                .layer-item-compact.has-content {
                    border-left: 3px solid #4CAF50;
                }

                .layer-visibility-compact {
                    cursor: pointer;
                    padding: 2px 4px;
                    border-radius: 2px;
                    background: #555;
                    font-size: 10px;
                }

                #socketIndicator.connected {
                    color: #4CAF50;
                }

                #socketIndicator.disconnected {
                    color: #f44336;
                }

                .layer-list-compact::-webkit-scrollbar {
                    width: 5px;
                }

                .layer-list-compact::-webkit-scrollbar-track {
                    background: #1a1a1a;
                    border-radius: 2px;
                }

                .layer-list-compact::-webkit-scrollbar-thumb {
                    background: #555;
                    border-radius: 2px;
                }

                .layer-list-compact::-webkit-scrollbar-thumb:hover {
                    background: #777;
                }

                .pokemon-loading {
                    animation: pokemonSpin 1s linear infinite;
                }

                @keyframes pokemonSpin {
                    0% { transform: rotate(0deg); }
                    100% { transform: rotate(360deg); }
                }
            `;

            const style = document.createElement('style');
            style.textContent = css;
            document.head.appendChild(style);
        }

        setupEventListeners() {
            document.getElementById('layerToggleBtn').addEventListener('click', () => this.togglePanel());

            this.setupCanvasDrawing();

            document.getElementById('prevLayer').addEventListener('click', () => this.previousLayer());
            document.getElementById('nextLayer').addEventListener('click', () => this.nextLayer());

            document.getElementById('addLayer').addEventListener('click', () => this.addLayer());
            document.getElementById('removeLayer').addEventListener('click', () => this.removeLayer());
            document.getElementById('clearLayer').addEventListener('click', () => this.clearCurrentLayer());
            document.getElementById('duplicateLayer').addEventListener('click', () => this.duplicateCurrentLayer());

            document.getElementById('toggleLoopBtn').addEventListener('click', () => this.toggleLoop());
            document.getElementById('importImageBtn').addEventListener('click', () => this.importImages());
            document.getElementById('imageFileInput').addEventListener('change', (e) => this.handleImageFiles(e.target.files));
            document.getElementById('toggleQualityBtn').addEventListener('click', () => this.toggleQuality());

            // Nuevo evento para el botón de Pokémon
            document.getElementById('loadPokemonBtn').addEventListener('click', () => this.loadRandomPokemon());

            document.getElementById('onionToggle').addEventListener('change', () => this.updateOnionSkin());
            document.getElementById('onionRange').addEventListener('input', (e) => {
                this.onionOpacity = e.target.value / 100;
                this.updateOnionSkin();
            });

            document.getElementById('playBtn').addEventListener('click', () => this.playRealAnimation());
            document.getElementById('stopBtn').addEventListener('click', () => this.stopAnimation());

            document.getElementById('speedRange').addEventListener('input', (e) => {
                this.animationSpeed = parseInt(e.target.value);
                document.getElementById('speedValue').textContent = this.animationSpeed;
            });
        }

        // Nueva función para cargar Pokémon aleatorio usando PokeAPI
        async loadRandomPokemon() {
            const pokemonBtn = document.getElementById('loadPokemonBtn');

            if (this.isAnimating) {
                console.log('No se puede cargar Pokémon durante la animación.');
                return;
            }

            // Animación de loading
            pokemonBtn.classList.add('pokemon-loading');
            pokemonBtn.disabled = true;

            try {
                // Generar ID aleatorio entre 1 y 1010 (cantidad aproximada de Pokémon en PokeAPI)
                const randomId = Math.floor(Math.random() * 1010) + 1;
                const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${randomId}`);

                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }

                const pokemonData = await response.json();
                const spriteUrl = pokemonData.sprites.front_default;

                if (!spriteUrl) {
                    throw new Error('No sprite disponible para este Pokémon');
                }

                console.log(`🎮 Cargando ${pokemonData.name.toUpperCase()} (ID: ${pokemonData.id})`);

                // Crear nueva imagen y procesarla
                const img = new Image();
                img.crossOrigin = 'anonymous';

                img.onload = async () => {
                    try {
                        const newCommands = await this.processImageToCommands(img);
                        if (newCommands.length > 0) {
                            // Crear nueva capa para el Pokémon
                            this.addLayer();
                            this.layers[this.currentLayer].name = `🎮 ${pokemonData.name.charAt(0).toUpperCase() + pokemonData.name.slice(1)}`;
                            this.layers[this.currentLayer].commands = newCommands;

                            console.log(`✅ ${pokemonData.name.toUpperCase()} importado exitosamente a la Capa ${this.currentLayer + 1}. Comandos: ${newCommands.length}`);
                            this.updateUI();
                        } else {
                            console.warn(`❌ No se pudieron generar comandos para ${pokemonData.name}`);
                        }
                    } catch (error) {
                        console.error('Error al procesar el sprite del Pokémon:', error);
                    } finally {
                        // Restaurar estado del botón
                        pokemonBtn.classList.remove('pokemon-loading');
                        pokemonBtn.disabled = false;
                    }
                };

                img.onerror = () => {
                    console.error(`❌ No se pudo cargar el sprite de ${pokemonData.name}`);
                    pokemonBtn.classList.remove('pokemon-loading');
                    pokemonBtn.disabled = false;
                };

                img.src = spriteUrl;

            } catch (error) {
                console.error('Error al cargar Pokémon desde PokeAPI:', error);
                pokemonBtn.classList.remove('pokemon-loading');
                pokemonBtn.disabled = false;
            }
        }

        // ... [resto de los métodos permanecen igual]

        togglePanel() {
            const panel = document.getElementById('layerCompactPanel');
            this.menuVisible = !this.menuVisible;
            panel.style.display = this.menuVisible ? 'block' : 'none';
        }

        setupCanvasDrawing() {
            if (!this.previewCanvas) return;

            this.previewCanvas.addEventListener('mousedown', (e) => this.startDrawing(e));
            this.previewCanvas.addEventListener('mousemove', (e) => this.draw(e));
            this.previewCanvas.addEventListener('mouseup', () => this.stopDrawing());
            this.previewCanvas.addEventListener('mouseout', () => this.stopDrawing());
        }

        getMousePos(e) {
            const rect = this.previewCanvas.getBoundingClientRect();
            const scaleX = this.previewCanvas.width / rect.width;
            const scaleY = this.previewCanvas.height / rect.height;

            return {
                x: (e.clientX - rect.left) * scaleX,
                y: (e.clientY - rect.top) * scaleY
            };
        }

        startDrawing(e) {
            this.isDrawing = true;
            const pos = this.getMousePos(e);
            this.lastX = pos.x;
            this.lastY = pos.y;
        }

        draw(e) {
            if (!this.isDrawing) return;

            const pos = this.getMousePos(e);
            const command = {
                type: 'line',
                x1: this.lastX,
                y1: this.lastY,
                x2: pos.x,
                y2: pos.y,
                color: this.getCurrentColor(),
                thickness: this.getCurrentThickness()
            };

            this.layers[this.currentLayer].commands.push(command);
            this.drawCommand(this.previewCtx, command);

            this.lastX = pos.x;
            this.lastY = pos.y;
            this.updateLayerList();
        }

        stopDrawing() {
            this.isDrawing = false;
        }

        getCurrentColor() {
            const colorPicker = document.querySelector('input[type="color"]');
            return colorPicker ? colorPicker.value : '#000000';
        }

        getCurrentThickness() {
            const thicknessPicker = document.querySelector('input[type="range"]');
            return thicknessPicker ? parseInt(thicknessPicker.value) : 5;
        }

        drawCommand(ctx, command) {
            if (command.type === 'line') {
                ctx.strokeStyle = command.color;
                ctx.lineWidth = command.thickness;
                ctx.lineCap = 'round';
                ctx.beginPath();
                ctx.moveTo(command.x1, command.y1);
                ctx.lineTo(command.x2, command.y2);
                ctx.stroke();
            }
        }

        async playRealAnimation() {
            if (!this.gameCanvas || !this.gameSocket || this.isAnimating) {
                console.log('Canvas o WebSocket no disponible o animación ya en curso.');
                return;
            }

            this.isAnimating = true;
            document.getElementById('playBtn').disabled = true;
            document.getElementById('stopBtn').disabled = false;
            this.disableLayerControls(true);

            do {
                await this.clearRealCanvas();
                await this.delay(300);

                for (let layerIndex = 0; layerIndex < this.layers.length && this.isAnimating; layerIndex++) {
                    const layer = this.layers[layerIndex];
                    if (!layer.visible || layer.commands.length === 0) continue;

                    if (layerIndex > 0) {
                        await this.clearRealCanvas();
                        await this.delay(200);
                    }

                    for (let i = 0; i < layer.commands.length && this.isAnimating; i++) {
                        const command = layer.commands[i];
                        await this.executeRealCommand(command);
                        await this.delay(this.animationSpeed);
                    }

                    if (this.isAnimating && layerIndex < this.layers.length - 1) {
                        await this.delay(300);
                    }
                }

                if (this.isAnimating && this.isLoopEnabled) {
                    await this.delay(500);
                }

            } while (this.isAnimating && this.isLoopEnabled);

            this.stopAnimation();
        }

        async executeRealCommand(command) {
            if (!this.gameCanvas || !this.gameSocket) return;

            const scaleX = this.gameCanvas.width / this.previewCanvas.width;
            const scaleY = this.gameCanvas.height / this.previewCanvas.height;

            const gameX1 = command.x1 * scaleX;
            const gameY1 = command.y1 * scaleY;
            const gameX2 = command.x2 * scaleX;
            const gameY2 = command.y2 * scaleY;

            this.gameCtx.strokeStyle = command.color;
            this.gameCtx.lineWidth = command.thickness + 5;
            this.gameCtx.lineCap = 'round';
            this.gameCtx.beginPath();
            this.gameCtx.moveTo(gameX1, gameY1);
            this.gameCtx.lineTo(gameX2, gameY2);
            this.gameCtx.stroke();

            const success = this.sendRealDrawCommand(
                gameX1, gameY1, gameX2, gameY2,
                command.color, command.thickness
            );

            if (!success) {
                console.log('Error enviando comando real');
            }
        }

        async clearRealCanvas() {
            if (!this.gameSocket || !this.gameCtx || !this.gameCanvas) return;

            this.gameCtx.clearRect(0, 0, this.gameCanvas.width, this.gameCanvas.height);

            try {
                const clearThickness = Math.max(this.gameCanvas.width, this.gameCanvas.height) * 0.8;
                const clearColor = '#ffffff';

                const steps = 3;
                for (let i = 0; i < steps; i++) {
                    const y = (i / (steps - 1)) * this.gameCanvas.height;
                    const success = this.sendRealDrawCommand(
                        0, y,
                        this.gameCanvas.width, y,
                        clearColor, clearThickness
                    );

                    if (success) {
                        await this.delay(10);
                    }
                }
            } catch (error) {
                console.error('Error limpiando canvas real:', error);
            }
        }

        updateSocketStatus() {
            const indicator = document.getElementById('socketIndicator');
            if (!indicator) return;

            if (this.gameSocket && this.gameSocket.readyState === 1) {
                indicator.textContent = '🟢';
                indicator.className = 'connected';
            } else {
                indicator.textContent = '🔴';
                indicator.className = 'disconnected';
            }

            setTimeout(() => this.updateSocketStatus(), 3000);
        }

        stopAnimation() {
            this.isAnimating = false;
            document.getElementById('playBtn').disabled = false;
            document.getElementById('stopBtn').disabled = true;
            this.disableLayerControls(false);
        }

        disableLayerControls(disable) {
            document.getElementById('prevLayer').disabled = disable;
            document.getElementById('nextLayer').disabled = disable;
            document.getElementById('addLayer').disabled = disable;
            document.getElementById('removeLayer').disabled = disable;
            document.getElementById('clearLayer').disabled = disable;
            document.getElementById('duplicateLayer').disabled = disable;
            document.getElementById('toggleLoopBtn').disabled = disable;
            document.getElementById('importImageBtn').disabled = disable;
            document.getElementById('toggleQualityBtn').disabled = disable;
            document.getElementById('loadPokemonBtn').disabled = disable; // Nuevo control
            document.getElementById('onionToggle').disabled = disable;
            document.getElementById('onionRange').disabled = disable;
            document.getElementById('speedRange').disabled = disable;
        }

        addLayer() {
            this.layers.push({ commands: [], visible: true, name: `Layer ${this.layers.length + 1}` });
            this.currentLayer = this.layers.length - 1;
            this.updateUI();
            console.log(`Capa ${this.currentLayer + 1} agregada.`);
        }

        removeLayer() {
            if (this.layers.length <= 1) {
                console.log('No se puede eliminar la última capa.');
                return;
            }
            if (this.currentLayer === this.layers.length - 1) {
                this.currentLayer = Math.max(0, this.currentLayer - 1);
            }
            this.layers.splice(this.currentLayer, 1);
            this.updateUI();
            console.log(`Capa eliminada. Capas restantes: ${this.layers.length}`);
        }

        previousLayer() {
            if (this.currentLayer > 0) {
                this.currentLayer--;
                this.updateUI();
            }
        }

        nextLayer() {
            if (this.currentLayer < this.layers.length - 1) {
                this.currentLayer++;
                this.updateUI();
            }
        }

        clearCurrentLayer() {
            this.layers[this.currentLayer].commands = [];
            this.updateOnionSkin();
            this.updateLayerList();
            console.log(`Capa ${this.currentLayer + 1} limpiada.`);
        }

        duplicateCurrentLayer() {
            const duplicated = {
                commands: [...this.layers[this.currentLayer].commands],
                visible: true,
                name: `${this.layers[this.currentLayer].name} Copy`
            };
            this.layers.push(duplicated);
            this.currentLayer = this.layers.length - 1;
            this.updateUI();
            console.log(`Capa ${this.currentLayer + 1} duplicada.`);
        }

        toggleLoop() {
            this.isLoopEnabled = !this.isLoopEnabled;
            this.updateLoopButtonState();
            console.log(`Modo de bucle: ${this.isLoopEnabled ? 'ACTIVADO' : 'DESACTIVADO'}`);
        }

        updateLoopButtonState() {
            const loopBtn = document.getElementById('toggleLoopBtn');
            if (loopBtn) {
                if (this.isLoopEnabled) {
                    loopBtn.classList.add('active');
                } else {
                    loopBtn.classList.remove('active');
                }
            }
        }

        toggleQuality() {
            this.highQualityImport = !this.highQualityImport;
            this.pixelProcessingStep = this.highQualityImport ? 1 : 2;
            this.targetImageResolution = this.highQualityImport ? 150 : 100;
            this.updateQualityButtonState();
            console.log(`Calidad de importación de imagen: ${this.highQualityImport ? 'ALTA' : 'NORMAL'} (paso de píxel: ${this.pixelProcessingStep}, resolución: ${this.targetImageResolution}x${this.targetImageResolution})`);
        }

        updateQualityButtonState() {
            const qualityBtn = document.getElementById('toggleQualityBtn');
            if (qualityBtn) {
                if (this.highQualityImport) {
                    qualityBtn.classList.add('active');
                } else {
                    qualityBtn.classList.remove('active');
                }
            }
        }

        importImages() {
            document.getElementById('imageFileInput').click();
        }

        async handleImageFiles(files) {
            if (files.length === 0) return;

            for (let i = 0; i < files.length; i++) {
                const file = files[i];
                if (!file.type.startsWith('image/')) {
                    console.warn(`El archivo ${file.name} no es una imagen, se omitirá.`);
                    continue;
                }

                console.log(`Procesando imagen: ${file.name}`);
                const reader = new FileReader();

                reader.onload = async (e) => {
                    const img = new Image();
                    img.onload = async () => {
                        try {
                            const newCommands = await this.processImageToCommands(img);
                            if (newCommands.length > 0) {
                                this.addLayer();
                                this.layers[this.currentLayer].name = `Image Layer (${file.name.substring(0,15)}...)`;
                                this.layers[this.currentLayer].commands = newCommands;
                                console.log(`Imagen "${file.name}" importada a la Capa ${this.currentLayer + 1}. Comandos generados: ${newCommands.length}`);
                                this.updateUI();
                            } else {
                                console.warn(`No se pudieron generar comandos de dibujo para la imagen "${file.name}".`);
                            }
                        } catch (error) {
                            console.error('Error al procesar la imagen:', error);
                        }
                    };
                    img.onerror = () => {
                        console.error(`No se pudo cargar la imagen: ${file.name}`);
                    };
                    img.src = e.target.result;
                };
                reader.readAsDataURL(file);
            }
        }

        async processImageToCommands(img) {
            const tempCanvas = document.createElement('canvas');
            const tempCtx = tempCanvas.getContext('2d');

            const maxWidth = this.targetImageResolution;
            const maxHeight = this.targetImageResolution;
            let width = img.width;
            let height = img.height;

            if (width > height) {
                if (width > maxWidth) {
                    height *= maxWidth / width;
                    width = maxWidth;
                }
            } else {
                if (height > maxHeight) {
                    width *= maxHeight / height;
                    height = maxHeight;
                }
            }

            tempCanvas.width = width;
            tempCanvas.height = height;

            tempCtx.imageSmoothingEnabled = this.highQualityImport;
            tempCtx.imageSmoothingQuality = this.highQualityImport ? 'high' : 'medium';

            tempCtx.drawImage(img, 0, 0, width, height);

            const imageData = tempCtx.getImageData(0, 0, width, height);
            const data = imageData.data;
            const commands = [];
            const previewWidth = this.previewCanvas.width;
            const previewHeight = this.previewCanvas.height;

            const currentPixelStep = this.pixelProcessingStep;
            const baseThickness = currentPixelStep;

            for (let y = 0; y < height; y += currentPixelStep) {
                let currentSegment = null;

                for (let x = 0; x < width; x += currentPixelStep) {
                    const i = (y * width + x) * 4;
                    const r = data[i];
                    const g = data[i + 1];
                    const b = data[i + 2];
                    const a = data[i + 3];

                    if (a < 50) {
                        if (currentSegment) {
                            const color = currentSegment.color;
                            commands.push({
                                type: 'line',
                                x1: (currentSegment.startX / width) * previewWidth,
                                y1: (y / height) * previewHeight,
                                x2: (x / width) * previewWidth,
                                y2: (y / height) * previewHeight,
                                color: color,
                                thickness: baseThickness
                            });
                            currentSegment = null;
                        }
                        continue;
                    }

                    const currentColor = `rgb(${r},${g},${b})`;

                    if (currentSegment === null) {
                        currentSegment = { startX: x, color: currentColor };
                    } else if (currentSegment.color !== currentColor) {
                        commands.push({
                            type: 'line',
                            x1: (currentSegment.startX / width) * previewWidth,
                            y1: (y / height) * previewHeight,
                            x2: (x / width) * previewWidth,
                            y2: (y / height) * previewHeight,
                            color: currentSegment.color,
                            thickness: baseThickness
                        });
                        currentSegment = { startX: x, color: currentColor };
                    }
                }

                if (currentSegment) {
                    commands.push({
                        type: 'line',
                        x1: (currentSegment.startX / width) * previewWidth,
                        y1: (y / height) * previewHeight,
                        x2: (width / width) * previewWidth,
                        y2: (y / height) * previewHeight,
                        color: currentSegment.color,
                        thickness: baseThickness
                    });
                }
            }

            return commands;
        }

        updateUI() {
            this.updateLayerInfo();
            this.updateOnionSkin();
            this.updateLayerList();
            this.updateButtonStates();
            this.updateLoopButtonState();
            this.updateQualityButtonState();
        }

        updateLayerInfo() {
            const info = document.getElementById('layerInfo');
            if (info) {
                info.textContent = `${this.currentLayer + 1}/${this.layers.length}`;
            }
        }

        updateButtonStates() {
            const prevBtn = document.getElementById('prevLayer');
            const nextBtn = document.getElementById('nextLayer');
            const removeBtn = document.getElementById('removeLayer');
            const addBtn = document.getElementById('addLayer');

            if (prevBtn) prevBtn.disabled = this.currentLayer === 0 || this.isAnimating;
            if (nextBtn) nextBtn.disabled = this.currentLayer === this.layers.length - 1 || this.isAnimating;
            if (removeBtn) removeBtn.disabled = this.layers.length <= 1 || this.isAnimating;
            if (addBtn) addBtn.disabled = this.isAnimating;

            document.getElementById('clearLayer').disabled = this.isAnimating;
            document.getElementById('duplicateLayer').disabled = this.isAnimating;
            document.getElementById('importImageBtn').disabled = this.isAnimating;
            document.getElementById('toggleQualityBtn').disabled = this.isAnimating;
            document.getElementById('loadPokemonBtn').disabled = this.isAnimating;
        }

        updateOnionSkin() {
            if (!this.previewCtx) return;

            this.previewCtx.clearRect(0, 0, this.previewCanvas.width, this.previewCanvas.height);
            const showOnion = document.getElementById('onionToggle')?.checked;

            if (showOnion) {
                if (this.currentLayer > 0) {
                    this.previewCtx.globalAlpha = this.onionOpacity;
                    this.layers[this.currentLayer - 1].commands.forEach(command => {
                        this.drawCommand(this.previewCtx, {...command, color: '#ff6b6b'});
                    });
                }

                if (this.currentLayer < this.layers.length - 1) {
                    this.previewCtx.globalAlpha = this.onionOpacity;
                    this.layers[this.currentLayer + 1].commands.forEach(command => {
                        this.drawCommand(this.previewCtx, {...command, color: '#6bb6ff'});
                    });
                }
            }

            this.previewCtx.globalAlpha = 1;
            this.layers[this.currentLayer].commands.forEach(command => {
                this.drawCommand(this.previewCtx, command);
            });
        }

        updateLayerList() {
            const container = document.getElementById('layerListCompact');
            if (!container) return;

            container.innerHTML = '';

            this.layers.forEach((layer, index) => {
                const item = document.createElement('div');
                item.className = `layer-item-compact ${index === this.currentLayer ? 'active' : ''} ${layer.commands.length > 0 ? 'has-content' : ''}`;

                item.innerHTML = `
                    <span>${layer.name || `L${index + 1}`} (${layer.commands.length})</span>
                    <span class="layer-visibility-compact" data-layer="${index}">${layer.visible ? '👁️' : '🚫'}</span>
                `;

                item.addEventListener('click', (e) => {
                    if (this.isAnimating) return;
                    if (e.target.classList.contains('layer-visibility-compact')) {
                        this.layers[index].visible = !this.layers[index].visible;
                        this.updateLayerList();
                    } else {
                        this.currentLayer = index;
                        this.updateUI();
                    }
                });

                container.appendChild(item);
            });
        }

        delay(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            setTimeout(() => new RealLayerAnimationSystem(), 3000);
        });
    } else {
        setTimeout(() => new RealLayerAnimationSystem(), 3000);
    }
})();