Drawaria Drawing Controls (Always Visible)

Forces Drawaria's drawing controls to be always visible.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Drawaria Drawing Controls (Always Visible)
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Forces Drawaria's drawing controls to be always visible.
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // --- Inyectar CSS para forzar la visibilidad y funcionalidad ---
    // Usamos !important para anular cualquier estilo inline o de media query
    const style = document.createElement('style');
    style.innerHTML = `
        #drawcontrols {
            display: flex !important; /* Asegura que el contenedor principal sea visible */
            pointer-events: auto !important; /* Permite interacción con el ratón */
            opacity: 1 !important; /* Asegura que no sea transparente */
            /* Puedes ajustar la posición si se superpone con otros elementos
               Ejemplos: */
            /* bottom: 0 !important; */
            /* left: 50% !important; */
            /* transform: translateX(-50%) !important; */
            /* width: auto !important; */
        }

        /* Asegurar que los botones dentro de drawcontrols también sean visibles y funcionales */
        #drawcontrols .drawcontrols-button,
        #drawcontrols .drawcontrols-toolstoggle,
        #drawcontrols .drawcontrols-dialogbutton {
            display: flex !important; /* O flex si usan flexbox para alinear contenido */
            pointer-events: auto !important;
            opacity: 1 !important;
        }

        /* Anular estilos de "deshabilitado" que el juego pueda aplicar */
        #drawcontrols.drawcontrols-disabled,
        #drawcontrols .drawcontrols-button.drawcontrols-disabled {
            color: initial !important; /* Restablece el color normal */
            pointer-events: auto !important;
            opacity: 1 !important;
        }

        /* Asegurar que el canvas sea interactivo */
        #canvas {
            pointer-events: auto !important;
        }
    `;
    document.head.appendChild(style);

    // --- Lógica de dibujo local en el canvas ---
    const canvas = document.querySelector('#canvas');
    if (canvas) {
        const ctx = canvas.getContext('2d');
        let drawing = false;
        let lastX = 0;
        let lastY = 0;

        // Establecer propiedades de dibujo iniciales (se actualizarán con los controles)
        ctx.strokeStyle = '#000000'; // Color de línea por defecto (negro)
        ctx.lineWidth = 5;           // Ancho de línea por defecto
        ctx.lineJoin = 'round';      // Tipo de unión de línea
        ctx.lineCap = 'round';       // Tipo de extremo de línea

        canvas.addEventListener('mousedown', (e) => {
            drawing = true;
            const rect = canvas.getBoundingClientRect();
            lastX = e.clientX - rect.left;
            lastY = e.clientY - rect.top;

            ctx.beginPath();
            ctx.moveTo(lastX, lastY);
        });

        canvas.addEventListener('mousemove', (e) => {
            if (!drawing) return;

            const rect = canvas.getBoundingClientRect();
            const currentX = e.clientX - rect.left;
            const currentY = e.clientY - rect.top;

            ctx.lineTo(currentX, currentY);
            ctx.stroke();

            lastX = currentX;
            lastY = currentY;
        });

        canvas.addEventListener('mouseup', () => {
            drawing = false;
            ctx.closePath();
        });

        canvas.addEventListener('mouseout', () => {
            if (drawing) {
                drawing = false;
                ctx.closePath();
            }
        });
    } else {
        console.warn("Drawaria Local Drawing Controls: Canvas element with ID 'canvas' not found.");
    }

    // --- Hacer que los controles de dibujo actualicen el contexto de dibujo LOCAL ---
    // Usamos MutationObserver para esperar a que jQuery esté disponible y los elementos del DOM se carguen.
    // También escuchamos los eventos click y input de los controles.
    const observer = new MutationObserver((mutations, obs) => {
        // Ejecutar solo si jQuery está cargado
        if (typeof jQuery === 'undefined') {
            return;
        }

        // Una vez que jQuery esté listo, podemos desconectar el observer si lo deseamos.
        // O lo mantenemos para capturar elementos que se puedan añadir dinámicamente.
        // Para este caso, lo mantendremos para mayor robustez con elementos dinámicos.

        const drawControls = jQuery('#drawcontrols');
        if (drawControls.length === 0) {
            return; // Los controles aún no están en el DOM
        }

        // 1. Deshabilitar cualquier clase de "deshabilitado" que el juego pueda añadir dinámicamente
        drawControls.removeClass('drawcontrols-disabled');
        drawControls.find('.drawcontrols-button').removeClass('drawcontrols-disabled');


        // 2. Capturar clics en los botones de color
        drawControls.off('click.userScriptColors', '.drawcontrols-color').on('click.userScriptColors', '.drawcontrols-color', function(e) {
            e.stopPropagation(); // Evita que el evento llegue a los manejadores del juego
            e.preventDefault();  // Previene cualquier acción por defecto (como cambiar el cursor real del juego)

            const color = jQuery(this).css('background-color');
            if (canvas && canvas.getContext) {
                canvas.getContext('2d').strokeStyle = color;
                console.log('Local drawing color changed to:', color);

                // Puedes añadir un feedback visual, como un borde al color seleccionado
                drawControls.find('.drawcontrols-color').css('border', '');
                jQuery(this).css('border', '2px solid white');
            }
        });

        // 3. Capturar cambios en el slider de ancho de línea
        drawControls.off('input.userScriptWidth', '#drawwidthrange').on('input.userScriptWidth', '#drawwidthrange', function(e) {
            e.stopPropagation();
            e.preventDefault();

            const rangeValue = parseFloat(jQuery(this).val());
            let lineWidth = 5; // Valor por defecto

            // Mapeo simple de los valores del rango a los tamaños del pincel de Drawaria
            // Basado en LINEWIDTHLIST=[5,12,45] en el JS del juego
            if (rangeValue <= 0.5) {
                lineWidth = 5;
            } else if (rangeValue <= 1.5) {
                lineWidth = 12;
            } else {
                lineWidth = 45;
            }

            if (canvas && canvas.getContext) {
                canvas.getContext('2d').lineWidth = lineWidth;
                console.log('Local drawing line width changed to:', lineWidth);
            }
        });

        // 4. Implementar la funcionalidad de la goma de borrar (Eraser)
        // El botón de goma de borrar tiene la clase drawcontrols-button y el ícono fas fa-eraser
        drawControls.off('click.userScriptEraser', '.drawcontrols-button .fas.fa-eraser').on('click.userScriptEraser', '.drawcontrols-button .fas.fa-eraser', function(e) {
            e.stopPropagation();
            e.preventDefault();

            if (canvas && canvas.getContext) {
                const currentCtx = canvas.getContext('2d');
                // Para borrar, podemos cambiar el color del trazo al color de fondo del canvas (blanco)
                currentCtx.strokeStyle = '#FFFFFF';
                // Opcional: ajustar el ancho de la goma para que se note la diferencia
                currentCtx.lineWidth = 20; // Un ancho mayor para la goma
                console.log('Local drawing set to Eraser mode (white color).');
            }
        });

        // 5. Implementar la funcionalidad de Limpiar todo (Clear All)
        // El botón de limpiar todo tiene la clase drawcontrols-button y el ícono fas fa-trash-alt
        drawControls.off('click.userScriptClear', '.drawcontrols-button .fas.fa-trash-alt').on('click.userScriptClear', '.drawcontrols-button .fas.fa-trash-alt', function(e) {
            e.stopPropagation();
            e.preventDefault();

            if (canvas && canvas.getContext) {
                const currentCtx = canvas.getContext('2d');
                currentCtx.clearRect(0, 0, canvas.width, canvas.height); // Limpiar todo el canvas
                console.log('Local canvas cleared.');

                // Después de limpiar, restablecer el color a negro por defecto
                currentCtx.strokeStyle = '#000000';
                currentCtx.lineWidth = 5;
            }
        });

        // 6. Asegurar que los botones de toolstoggle (como el color picker o pressure settings) también sean visibles
        // Estos botones tienen la clase .drawcontrols-toolstoggle y .drawcontrols-dialogbutton
        drawControls.off('click.userScriptToggleTools', '.drawcontrols-toolstoggle, .drawcontrols-dialogbutton').on('click.userScriptToggleTools', '.drawcontrols-toolstoggle, .drawcontrols-dialogbutton', function(e) {
            // Permitimos la propagación para estos botones para que el juego pueda abrir sus modales/popups
            // Sin embargo, si quieres que *solo* sean visuales y no activen nada del juego,
            // puedes añadir e.stopPropagation() y e.preventDefault() aquí también.
            // Para "funcionales" en el sentido de que abran sus modales, no los bloqueamos.
            console.log('Tool toggle/dialog button clicked. Game\'s original handler might open a modal.');
        });


        // Desconectar el observer si ya hemos configurado todos los eventos principales.
        // Sin embargo, mantenerlo conectado puede ser útil si el juego reconstruye partes del DOM.
        // Para este script, lo dejaremos funcionando para que re-aplique los listeners si es necesario.
        // obs.disconnect();
    });

    // Iniciar el observer en el body para detectar cambios en el DOM
    observer.observe(document.body, { childList: true, subtree: true });

    // Forzar la remoción de la clase 'drawcontrols-disabled' en la carga inicial y cada vez que aparezca
    // (Útil si el juego añade la clase después de que se carga el script)
    window.addEventListener('load', () => {
        const drawControlsElement = document.querySelector('#drawcontrols');
        if (drawControlsElement) {
            drawControlsElement.classList.remove('drawcontrols-disabled');
        }
    });

    // Usar jQuery para asegurar que el 'drawcontrols' se muestre en cuanto se detecte.
    // Esto es un 'fallback' por si el observer no lo pilla a tiempo o si se usa jQuery en el juego.
    // Asegurarse de que jQuery esté cargado antes de intentar usarlo.
    if (typeof jQuery !== 'undefined') {
        jQuery(document).ready(function() {
            jQuery('#drawcontrols').css({
                'display': 'flex',
                'pointer-events': 'auto',
                'opacity': '1'
            }).removeClass('drawcontrols-disabled');
            jQuery('#drawcontrols').find('.drawcontrols-button').removeClass('drawcontrols-disabled');
            jQuery('#canvas').css('pointer-events', 'auto');
        });
    }

})();