// ==UserScript== // @name wplace.live — Hotkeys All Colors // @version 1.0 // @description Assign hotkeys to all colors on wplace.live; supports side mouse buttons // @author Anayy_n // @match https://wplace.live/* // @grant none // @license MIT // @namespace https://greasyfork.org/users/1505124 // @downloadURL none // ==/UserScript== (function() { 'use strict'; const STORAGE_KEY = 'wplace.manualHotkeys'; const SWATCH_SELECTOR = 'button[id^="color-"][aria-label]'; const PANEL_Z = 2147483647; let keyMap = {}; let swatches = []; function loadMap() { try { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); } catch { return {}; } } function saveMap() { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(keyMap)); } catch {} } function normKey(e) { if(['Shift','Control','Alt','Meta'].includes(e.key)) return ''; let mods=[]; if(e.ctrlKey) mods.push('ctrl'); if(e.altKey) mods.push('alt'); if(e.shiftKey) mods.push('shift'); let k=e.key.toLowerCase(); if(k===' ') k='space'; if(k==='escape') k='esc'; return [...mods.sort(),k].join('+'); } function isTyping(el){ if(!el) return false; if(el.closest('#wphk-panel')) return true; // typing in panel const t = el.tagName?.toLowerCase(); return t==='input'||t==='textarea'||el.isContentEditable; } function clickColor(el){ if(!el) return; el.dispatchEvent(new MouseEvent('click',{bubbles:true,cancelable:true})); } function scanSwatches(){ swatches = Array.from(document.querySelectorAll(SWATCH_SELECTOR)) .filter(el=>el && el.offsetParent && el.getBoundingClientRect().width>0); } function onKeyDown(e){ if(e.repeat) return; if(isTyping(document.activeElement)) return; const key = normKey(e); if(!key) return; const id = keyMap[key]; if(!id) return; const el = document.getElementById(id); clickColor(el); e.preventDefault(); e.stopPropagation(); } function onMouseDown(e){ if(isTyping(document.activeElement)) return; if(e.button === 0 || e.button === 2) return; // ignore left/right let btn = ''; if(e.button === 3) btn = 'mouse4'; if(e.button === 4) btn = 'mouse5'; if(!btn) return; const id = keyMap[btn]; if(!id) return; const el = document.getElementById(id); clickColor(el); e.preventDefault(); e.stopPropagation(); } function panelCSS(){ const css=`#wphk-btn{position:fixed;right:12px;bottom:12px;z-index:${PANEL_Z};border:0;padding:10px 12px;border-radius:8px;background:rgba(0,0,0,.7);color:#fff;font:13px/1.2 sans-serif;cursor:pointer} #wphk-panel{position:fixed;right:12px;bottom:56px;z-index:${PANEL_Z};width:min(480px,92vw);max-height:70vh;background:#111;color:#eee;border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.45);font:13px/1.4 system-ui,sans-serif;display:none} #wphk-panel .hdr{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-bottom:1px solid #333} #wphk-panel .hdr h3{margin:0;font-size:14px;font-weight:600} #wphk-panel .hdr .actions{display:flex;gap:8px} #wphk-panel .hdr button{border:0;padding:6px 8px;border-radius:6px;background:#222;color:#eaeaea;cursor:pointer} #wphk-panel .hdr button:hover{background:#2b2b2b} #wphk-panel .body{padding:8px 12px;overflow:auto;max-height:calc(70vh - 48px)} #wphk-list{width:100%;border-collapse:collapse} #wphk-list th,#wphk-list td{padding:6px 6px;border-bottom:1px solid #222;vertical-align:middle} #wphk-list th{position:sticky;top:0;background:#111;z-index:1} .swatch{width:24px;height:24px;border-radius:6px;border:1px solid rgba(255,255,255,.2)} .name{opacity:.85} .keybox{width:130px;padding:6px 8px;border-radius:6px;border:1px solid #333;background:#1a1a1a;color:#fff} .keybox:focus{outline:1px solid #555} .mini{font-size:11px;opacity:.8}`; const tag=document.createElement('style'); tag.textContent=css; document.head.appendChild(tag); } function colorOf(el){ const st=getComputedStyle(el); const inline=el.getAttribute('style'); if(inline && /background\s*:\s*[^;]+/.test(inline)){ const m=inline.match(/background\s*:\s*([^;]+)/i); if(m) return m[1].trim(); } return st.backgroundColor||'#000'; } function buildPanel(){ const openBtn=document.createElement('button'); openBtn.id='wphk-btn'; openBtn.textContent='🎨 Hotkeys'; document.body.appendChild(openBtn); const panel=document.createElement('div'); panel.id='wphk-panel'; panel.innerHTML=`
Color | Name | Shortcut | Test |
---|