// ==UserScript==
// @name Drawaria Pixel Art Studio
// @namespace http://tampermonkey.net/
// @version 1.1
// @description A pixelart tool with colors and figures to draw
// @author YouTubeDrawaria
// @match https://drawaria.online/*
// @include https://drawaria.online*
// @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// @grant none
// @license GNU GPLv3
// ==/UserScript==
(function () {
'use strict';
// === Canvas and WebSocket Setup ===
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let socket;
let canvasCenter = { x: 0, y: 0 };
let canvasDimensions = { width: 0, height: 0 };
const originalSend = WebSocket.prototype.send;
WebSocket.prototype.send = function (...args) {
if (!socket) {
socket = this;
}
return originalSend.apply(this, args);
};
// === Canvas Detection and Center Calculation ===
function detectCanvasInfo() {
// Intentar obtener el canvas principal
const drawingCanvas = document.querySelector("#drawing-assistant-overlay") ||
document.getElementById('canvas') ||
document.querySelector('canvas');
if (drawingCanvas) {
// Obtener dimensiones reales del canvas
const rect = drawingCanvas.getBoundingClientRect();
canvasDimensions.width = drawingCanvas.width || rect.width;
canvasDimensions.height = drawingCanvas.height || rect.height;
// Calcular centro
canvasCenter.x = Math.floor(canvasDimensions.width / 2);
canvasCenter.y = Math.floor(canvasDimensions.height / 2);
console.log(`📐 Canvas detectado - Tamaño: ${canvasDimensions.width}x${canvasDimensions.height} - Centro: (${canvasCenter.x}, ${canvasCenter.y})`);
return true;
}
return false;
}
// === Console Status System (Replaces Visual Panel) ===
function updateStatus(message, show = true) {
if (show) {
// Limpiar HTML tags para consola
const cleanMessage = message.replace(/<br\/>/g, ' | ').replace(/<[^>]*>/g, '');
console.log(`🎨 PIXEL STUDIO: ${cleanMessage}`);
}
}
// === Drawing Functions with Local Rendering ===
function sendDrawCommand(x1, y1, x2, y2, color, thickness) {
if (!socket || !canvas) return;
const normX1 = (x1 / canvasDimensions.width).toFixed(4);
const normY1 = (y1 / canvasDimensions.height).toFixed(4);
const normX2 = (x2 / canvasDimensions.width).toFixed(4);
const normY2 = (y2 / canvasDimensions.height).toFixed(4);
const command = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${0 - thickness},"${color}",0,0,{}]]`;
socket.send(command);
}
// === LOCAL PIXEL DRAWING FUNCTION ===
function drawPixelLocally(x, y, width, height, color) {
if (!ctx || !canvas) return;
ctx.fillStyle = color;
ctx.fillRect(x, y, width, height);
}
// === ADVANCED PIXEL FILL WITH LOCAL RENDERING ===
function fillPixelAdvanced(x, y, pixelSize, color, thickness = 2) {
drawPixelLocally(x, y, pixelSize, pixelSize, color);
const step = Math.max(1, Math.floor(thickness));
// Líneas horizontales para rellenar
for (let i = 0; i < pixelSize; i += step) {
sendDrawCommand(x, y + i, x + pixelSize, y + i, color, thickness);
}
// Líneas verticales adicionales para mayor cobertura
for (let i = 0; i < pixelSize; i += step * 2) {
sendDrawCommand(x + i, y, x + i, y + pixelSize, color, Math.max(1, thickness - 1));
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// === PIXEL ART PATTERNS ===
const pixelPatterns = {
'smiley': [
" YYYYYYY ",
" Y Y ",
"Y BB BB Y",
"Y Y",
"Y B B Y",
"Y BBB Y",
" Y Y ",
" YYYYYYY "
],
'heart': [
" RR RR ",
"RRRR RRRR",
"RRRRRRRRR",
" RRRRRRR ",
" RRRRR ",
" RRR ",
" R "
],
'mushroom': [
" RRRRR ",
" RRR RRR ",
" RRR W RRR ",
"RRRRRRRRRRR",
" WWWWW ",
" WWWWW ",
" WWWWW ",
" WWWWWWW "
],
'flower': [
" R R ",
" RRR RRR ",
"RRR Y RRR",
"RRR Y RRR",
" RRRRR ",
" GGG ",
" GGG ",
" GGG "
],
'cat': [
"W W W W",
" W W W W ",
" WWWWWWW ",
" WWWWWWWWW ",
"WW RR RR WW",
"W B W",
"W BBBBB W",
" WWWWWWWWW "
],
'tree': [
" GGG ",
" GGGGG ",
" GGGGGGG ",
" GGGGGGGGG ",
"GGGGGGGGGGG",
" BBB ",
" BBB ",
" BBB "
],
'house': [
" RRRRR ",
" RRRRRRR ",
" RRRRRRRRR ",
"RRRRRRRRRRR",
"BBBBBBBBBBB",
"B YY B BB B",
"B YY B BB B",
"B B B",
"BBBBBBBBBBB"
]
};
const colorSchemes = {
classic: {
'Y': '#FFFF00', 'B': '#000000', 'R': '#FF0000', 'W': '#FFFFFF', 'G': '#00FF00', ' ': null
},
neon: {
'Y': '#FFFF00', 'B': '#FF00FF', 'R': '#00FFFF', 'W': '#FFFFFF', 'G': '#00FF00', ' ': null
},
pastel: {
'Y': '#FFE4B5', 'B': '#87CEEB', 'R': '#FFB6C1', 'W': '#F5F5F5', 'G': '#98FB98', ' ': null
},
dark: {
'Y': '#DAA520', 'B': '#2F2F2F', 'R': '#8B0000', 'W': '#D3D3D3', 'G': '#006400', ' ': null
},
rainbow: {
'Y': '#FFFF00', 'B': '#4B0082', 'R': '#FF1493', 'W': '#FFFFFF', 'G': '#32CD32', ' ': null
},
fire: {
'Y': '#FFD700', 'B': '#8B0000', 'R': '#FF4500', 'W': '#FFA500', 'G': '#FF6347', ' ': null
}
};
// === PIXEL ART CREATION WITH POSITIONING ===
async function createCustomPixelArt(patternName, colorScheme, pixelSize, offsetX = 0, offsetY = 0) {
if (!socket || !canvas || !ctx) return;
const pattern = pixelPatterns[patternName];
const colors = colorSchemes[colorScheme];
if (!pattern || !colors) return;
const totalWidth = pattern.length * pixelSize;
const totalHeight = pattern.length * pixelSize;
// Calcular posición con offset personalizado
const startX = Math.max(0, canvasCenter.x - totalWidth / 2 + offsetX);
const startY = Math.max(0, canvasCenter.y - totalHeight / 2 + offsetY);
console.log(`🎨 Iniciando dibujo: ${patternName.toUpperCase()} - Posición: (${Math.floor(startX)}, ${Math.floor(startY)}) - Tamaño: ${pixelSize}px`);
let pixelsDrawn = 0;
let totalPixels = 0;
// Contar píxeles totales
for (let row = 0; row < pattern.length; row++) {
for (let col = 0; col < pattern[row].length; col++) {
if (colors[pattern[row][col]]) totalPixels++;
}
}
// Dibujar patrón
for (let row = 0; row < pattern.length; row++) {
for (let col = 0; col < pattern[row].length; col++) {
const char = pattern[row][col];
if (!colors[char]) continue;
const x = startX + col * pixelSize;
const y = startY + row * pixelSize;
fillPixelAdvanced(x, y, pixelSize, colors[char], Math.max(1, pixelSize <= 2 ? 1 : 2));
pixelsDrawn++;
if (pixelsDrawn % 10 === 0) {
const progress = Math.round((pixelsDrawn / totalPixels) * 100);
console.log(`🎨 Progreso ${patternName.toUpperCase()}: ${progress}% - Píxeles: ${pixelsDrawn}/${totalPixels}`);
}
if (pixelsDrawn % 3 === 0) {
await sleep(pixelSize <= 2 ? 2 : 5);
}
}
await sleep(pixelSize <= 2 ? 5 : 10);
}
console.log(`✅ ${patternName.toUpperCase()} COMPLETADO - Total píxeles: ${pixelsDrawn} - Posición final: (${Math.floor(startX)}, ${Math.floor(startY)})`);
}
// === INTERFACE CREATION ===
function createPixelStudio() {
const studio = document.createElement('div');
studio.style.position = 'fixed';
studio.style.top = '20px';
studio.style.left = '1400px';
studio.style.backgroundColor = 'rgba(255, 255, 255, 0.98)';
studio.style.padding = '20px';
studio.style.zIndex = '1001';
studio.style.border = '3px solid #4a90e2';
studio.style.borderRadius = '12px';
studio.style.boxShadow = '0 8px 24px rgba(0,0,0,0.4)';
studio.style.fontFamily = 'Arial, sans-serif';
studio.style.width = '300px';
studio.style.maxHeight = '80vh';
studio.style.overflowY = 'auto';
// === HEADER ===
const header = document.createElement('div');
header.innerHTML = '🎨 PIXEL ART STUDIO';
header.style.fontSize = '16px';
header.style.fontWeight = 'bold';
header.style.color = '#4a90e2';
header.style.textAlign = 'center';
header.style.marginBottom = '15px';
header.style.textShadow = '1px 1px 2px rgba(0,0,0,0.1)';
studio.appendChild(header);
// === CANVAS INFO ===
const infoSection = document.createElement('div');
infoSection.style.marginBottom = '15px';
infoSection.style.padding = '8px';
infoSection.style.backgroundColor = '#f8f9fa';
infoSection.style.borderRadius = '5px';
infoSection.style.fontSize = '12px';
infoSection.style.color = '#666';
const canvasInfo = document.createElement('div');
canvasInfo.id = 'canvas-info';
canvasInfo.innerHTML = `📐 Canvas: ${canvasDimensions.width}x${canvasDimensions.height}<br/>🎯 Centro: (${canvasCenter.x}, ${canvasCenter.y})`;
infoSection.appendChild(canvasInfo);
studio.appendChild(infoSection);
// === PATTERN SELECTOR ===
const patternSection = document.createElement('div');
patternSection.style.marginBottom = '15px';
const patternLabel = document.createElement('label');
patternLabel.innerText = '🖼️ Selecciona Patrón:';
patternLabel.style.display = 'block';
patternLabel.style.fontWeight = 'bold';
patternLabel.style.color = '#333';
patternLabel.style.marginBottom = '5px';
const patternSelect = document.createElement('select');
patternSelect.id = 'pattern-select';
patternSelect.style.width = '100%';
patternSelect.style.padding = '8px';
patternSelect.style.borderRadius = '5px';
patternSelect.style.border = '2px solid #4a90e2';
patternSelect.style.fontSize = '14px';
Object.keys(pixelPatterns).forEach(pattern => {
const option = document.createElement('option');
option.value = pattern;
option.textContent = pattern.charAt(0).toUpperCase() + pattern.slice(1);
patternSelect.appendChild(option);
});
patternSection.appendChild(patternLabel);
patternSection.appendChild(patternSelect);
// === COLOR SCHEME SELECTOR ===
const colorSection = document.createElement('div');
colorSection.style.marginBottom = '15px';
const colorLabel = document.createElement('label');
colorLabel.innerText = '🎨 Esquema de Colores:';
colorLabel.style.display = 'block';
colorLabel.style.fontWeight = 'bold';
colorLabel.style.color = '#333';
colorLabel.style.marginBottom = '5px';
const colorSelect = document.createElement('select');
colorSelect.id = 'color-select';
colorSelect.style.width = '100%';
colorSelect.style.padding = '8px';
colorSelect.style.borderRadius = '5px';
colorSelect.style.border = '2px solid #e74c3c';
colorSelect.style.fontSize = '14px';
Object.keys(colorSchemes).forEach(scheme => {
const option = document.createElement('option');
option.value = scheme;
option.textContent = scheme.charAt(0).toUpperCase() + scheme.slice(1);
colorSelect.appendChild(option);
});
colorSection.appendChild(colorLabel);
colorSection.appendChild(colorSelect);
// === SIZE SELECTOR (1px minimum) ===
const sizeSection = document.createElement('div');
sizeSection.style.marginBottom = '15px';
const sizeLabel = document.createElement('label');
sizeLabel.innerText = '📏 Tamaño de Píxel:';
sizeLabel.style.display = 'block';
sizeLabel.style.fontWeight = 'bold';
sizeLabel.style.color = '#333';
sizeLabel.style.marginBottom = '5px';
const sizeRange = document.createElement('input');
sizeRange.type = 'range';
sizeRange.id = 'size-range';
sizeRange.min = '1';
sizeRange.max = '50';
sizeRange.value = '15';
sizeRange.style.width = '100%';
sizeRange.style.marginBottom = '5px';
const sizeValue = document.createElement('span');
sizeValue.id = 'size-value';
sizeValue.innerText = '15px';
sizeValue.style.fontSize = '12px';
sizeValue.style.color = '#666';
sizeRange.oninput = () => {
sizeValue.innerText = sizeRange.value + 'px';
if (parseInt(sizeRange.value) <= 3) {
sizeValue.style.color = '#e74c3c';
sizeValue.innerText += ' (Ultra Preciso)';
} else {
sizeValue.style.color = '#666';
}
};
sizeSection.appendChild(sizeLabel);
sizeSection.appendChild(sizeRange);
sizeSection.appendChild(sizeValue);
// === POSITION CONTROLS (X/Y) ===
const positionSection = document.createElement('div');
positionSection.style.marginBottom = '15px';
positionSection.style.padding = '10px';
positionSection.style.backgroundColor = '#f8f9fa';
positionSection.style.borderRadius = '8px';
positionSection.style.border = '2px solid #28a745';
const positionLabel = document.createElement('label');
positionLabel.innerText = '🎯 Posicionamiento:';
positionLabel.style.display = 'block';
positionLabel.style.fontWeight = 'bold';
positionLabel.style.color = '#28a745';
positionLabel.style.marginBottom = '10px';
// X Position Slider
const xPositionDiv = document.createElement('div');
xPositionDiv.style.marginBottom = '8px';
const xLabel = document.createElement('label');
xLabel.innerText = '↔️ Posición X:';
xLabel.style.display = 'block';
xLabel.style.fontSize = '12px';
xLabel.style.color = '#333';
xLabel.style.marginBottom = '3px';
const xRange = document.createElement('input');
xRange.type = 'range';
xRange.id = 'x-range';
xRange.min = -canvasDimensions.width / 2;
xRange.max = canvasDimensions.width / 2;
xRange.value = '0';
xRange.style.width = '100%';
const xValue = document.createElement('span');
xValue.id = 'x-value';
xValue.innerText = 'Centro (0)';
xValue.style.fontSize = '11px';
xValue.style.color = '#666';
xRange.oninput = () => {
const val = parseInt(xRange.value);
xValue.innerText = val === 0 ? 'Centro (0)' :
val > 0 ? `Derecha (+${val})` : `Izquierda (${val})`;
};
xPositionDiv.appendChild(xLabel);
xPositionDiv.appendChild(xRange);
xPositionDiv.appendChild(xValue);
// Y Position Slider
const yPositionDiv = document.createElement('div');
const yLabel = document.createElement('label');
yLabel.innerText = '↕️ Posición Y:';
yLabel.style.display = 'block';
yLabel.style.fontSize = '12px';
yLabel.style.color = '#333';
yLabel.style.marginBottom = '3px';
const yRange = document.createElement('input');
yRange.type = 'range';
yRange.id = 'y-range';
yRange.min = -canvasDimensions.height / 2;
yRange.max = canvasDimensions.height / 2;
yRange.value = '0';
yRange.style.width = '100%';
const yValue = document.createElement('span');
yValue.id = 'y-value';
yValue.innerText = 'Centro (0)';
yValue.style.fontSize = '11px';
yValue.style.color = '#666';
yRange.oninput = () => {
const val = parseInt(yRange.value);
yValue.innerText = val === 0 ? 'Centro (0)' :
val > 0 ? `Abajo (+${val})` : `Arriba (${val})`;
};
yPositionDiv.appendChild(yLabel);
yPositionDiv.appendChild(yRange);
yPositionDiv.appendChild(yValue);
// Center Reset Button
const centerButton = document.createElement('button');
centerButton.innerHTML = '🎯 CENTRAR';
centerButton.style.width = '100%';
centerButton.style.padding = '5px';
centerButton.style.backgroundColor = '#6c757d';
centerButton.style.color = 'white';
centerButton.style.border = 'none';
centerButton.style.borderRadius = '4px';
centerButton.style.fontSize = '11px';
centerButton.style.marginTop = '8px';
centerButton.style.cursor = 'pointer';
centerButton.onclick = () => {
xRange.value = '0';
yRange.value = '0';
xValue.innerText = 'Centro (0)';
yValue.innerText = 'Centro (0)';
console.log('🎯 Posicionamiento centrado: X=0, Y=0');
};
positionSection.appendChild(positionLabel);
positionSection.appendChild(xPositionDiv);
positionSection.appendChild(yPositionDiv);
positionSection.appendChild(centerButton);
// === PREVIEW AREA ===
const previewSection = document.createElement('div');
previewSection.style.marginBottom = '15px';
previewSection.style.textAlign = 'center';
const previewLabel = document.createElement('label');
previewLabel.innerText = '👁️ Vista Previa:';
previewLabel.style.display = 'block';
previewLabel.style.fontWeight = 'bold';
previewLabel.style.color = '#333';
previewLabel.style.marginBottom = '8px';
const previewCanvas = document.createElement('canvas');
previewCanvas.id = 'preview-canvas';
previewCanvas.width = 120;
previewCanvas.height = 120;
previewCanvas.style.border = '2px solid #ccc';
previewCanvas.style.borderRadius = '8px';
previewCanvas.style.backgroundColor = '#f9f9f9';
previewSection.appendChild(previewLabel);
previewSection.appendChild(previewCanvas);
// === ACTION BUTTONS ===
const buttonSection = document.createElement('div');
buttonSection.style.textAlign = 'center';
const drawButton = document.createElement('button');
drawButton.innerHTML = '🎨 DIBUJAR PIXEL ART';
drawButton.style.width = '100%';
drawButton.style.padding = '12px';
drawButton.style.backgroundColor = '#27ae60';
drawButton.style.color = 'white';
drawButton.style.border = 'none';
drawButton.style.borderRadius = '8px';
drawButton.style.fontSize = '14px';
drawButton.style.fontWeight = 'bold';
drawButton.style.cursor = 'pointer';
drawButton.style.marginBottom = '10px';
drawButton.style.transition = 'all 0.3s ease';
drawButton.onmouseover = () => drawButton.style.backgroundColor = '#229954';
drawButton.onmouseout = () => drawButton.style.backgroundColor = '#27ae60';
drawButton.onclick = () => {
const pattern = patternSelect.value;
const colorScheme = colorSelect.value;
const pixelSize = parseInt(sizeRange.value);
const offsetX = parseInt(xRange.value);
const offsetY = parseInt(yRange.value);
console.log(`🎮 Iniciando pixel art - Patrón: ${pattern} | Colores: ${colorScheme} | Tamaño: ${pixelSize}px | Offset: (${offsetX}, ${offsetY})`);
createCustomPixelArt(pattern, colorScheme, pixelSize, offsetX, offsetY);
};
const randomButton = document.createElement('button');
randomButton.innerHTML = '🎲 ALEATORIO';
randomButton.style.width = '100%';
randomButton.style.padding = '8px';
randomButton.style.backgroundColor = '#f39c12';
randomButton.style.color = 'white';
randomButton.style.border = 'none';
randomButton.style.borderRadius = '8px';
randomButton.style.fontSize = '12px';
randomButton.style.fontWeight = 'bold';
randomButton.style.cursor = 'pointer';
randomButton.style.transition = 'all 0.3s ease';
randomButton.onmouseover = () => randomButton.style.backgroundColor = '#e67e22';
randomButton.onmouseout = () => randomButton.style.backgroundColor = '#f39c12';
randomButton.onclick = () => {
const patterns = Object.keys(pixelPatterns);
const colors = Object.keys(colorSchemes);
const selectedPattern = patterns[Math.floor(Math.random() * patterns.length)];
const selectedColor = colors[Math.floor(Math.random() * colors.length)];
const selectedSize = Math.floor(Math.random() * 30) + 3;
patternSelect.value = selectedPattern;
colorSelect.value = selectedColor;
sizeRange.value = selectedSize;
sizeValue.innerText = selectedSize + 'px';
// Posición aleatoria pero no muy extrema
const randomX = Math.floor(Math.random() * 200) - 100;
const randomY = Math.floor(Math.random() * 200) - 100;
xRange.value = randomX;
yRange.value = randomY;
xRange.oninput();
yRange.oninput();
console.log(`🎲 Configuración aleatoria generada - Patrón: ${selectedPattern} | Color: ${selectedColor} | Tamaño: ${selectedSize}px | Posición: (${randomX}, ${randomY})`);
updatePreview();
};
buttonSection.appendChild(drawButton);
buttonSection.appendChild(randomButton);
// === ASSEMBLY ===
studio.appendChild(patternSection);
studio.appendChild(colorSection);
studio.appendChild(sizeSection);
studio.appendChild(positionSection);
studio.appendChild(previewSection);
studio.appendChild(buttonSection);
document.body.appendChild(studio);
// === PREVIEW FUNCTION ===
function updatePreview() {
const ctx = previewCanvas.getContext('2d');
ctx.clearRect(0, 0, previewCanvas.width, previewCanvas.height);
const pattern = pixelPatterns[patternSelect.value];
const colors = colorSchemes[colorSelect.value];
if (!pattern || !colors) return;
const cellSize = Math.min(
previewCanvas.width / pattern.length,
previewCanvas.height / pattern.length
);
const offsetX = (previewCanvas.width - pattern.length * cellSize) / 2;
const offsetY = (previewCanvas.height - pattern.length * cellSize) / 2;
for (let row = 0; row < pattern.length; row++) {
for (let col = 0; col < pattern[row].length; col++) {
const char = pattern[row][col];
if (!colors[char]) continue;
ctx.fillStyle = colors[char];
ctx.fillRect(
offsetX + col * cellSize,
offsetY + row * cellSize,
cellSize,
cellSize
);
}
}
}
// === EVENT LISTENERS ===
patternSelect.addEventListener('change', updatePreview);
colorSelect.addEventListener('change', updatePreview);
// Initial preview
updatePreview();
// Actualizar información del canvas periódicamente
setInterval(() => {
if (detectCanvasInfo()) {
document.getElementById('canvas-info').innerHTML =
`📐 Canvas: ${canvasDimensions.width}x${canvasDimensions.height}<br/>🎯 Centro: (${canvasCenter.x}, ${canvasCenter.y})`;
// Actualizar rangos de posición
xRange.min = -canvasDimensions.width / 2;
xRange.max = canvasDimensions.width / 2;
yRange.min = -canvasDimensions.height / 2;
yRange.max = canvasDimensions.height / 2;
}
}, 2000);
}
// === INITIALIZATION ===
// Detectar canvas info al inicio
setTimeout(() => {
if (detectCanvasInfo() && canvas && ctx) {
createPixelStudio();
console.log('🎨 PIXEL ART STUDIO v1.1 CARGADO EXITOSAMENTE');
console.log('✨ Precisión hasta 1px habilitada');
console.log('🎯 Control de posición XY activado');
console.log('📡 Sistema de notificaciones movido a consola');
} else {
console.error('❌ Error: Canvas no detectado');
}
}, 1000);
})();