// ==UserScript==
// @name Color Picker
// @namespace https://greasyfork.org/users/281093
// @match https://sketchful.io/*
// @grant none
// @version 0.3
// @author Bell
// @description Color picker for Sketchful
// @run-at document-end
// jshint esversion: 6
// ==/UserScript==
let storedPalettes = JSON.parse(localStorage.getItem('palettes'));
let palettes = storedPalettes || [
[],
[
"#3a3a3c", "#8e8e93", "#f8f9fa", "#ffadad", "#ffd6a5", "#fdffb6", "#caffbf", "#9bf6ff", "#a0c4ff", "#bdb2ff", "#ffc6ff", "#fdad88", "#9e5425",
"#2c2c2e", "#636366", "#e0e0e0", "#ff7070", "#f3a220", "#f9e079", "#049d6f", "#92ddea", "#6dafe0", "#ab87ff", "#ff87ab", "#e38a5e", "#5e320d",
"#1c1c1e", "#48484a", "#c2c2c2", "#f54d4d", "#dc8700", "#f0c808", "#00766a", "#219bc3", "#548bbc", "#715aff", "#ff5d8f", "#d1754e", "#421e06"
],
];
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
const gameTools = document.querySelector("#gameTools");
const chatBox = document.querySelector("#gameChat");
const colorPickerWrapper = document.createElement("div");
const colorInput = document.createElement("input");
const colorPicker = document.createElement("input");
const colorButtons = document.querySelectorAll(".gameToolsColor");
const inputStyle = `margin: 5px 0;
height: 20px;
width: 50%;
text-align: center;
border: none;
font-weight: 800;
border-radius: 5px;
background-color: #CBCBCB;`;
const wrapperStyle = `position: absolute;
margin: 5px 50%;
height: 20px;
width: 30px;
border-radius: 5px;`;
document.querySelector("#gameToolsSlider").style.top = "77px";
canvas.addEventListener('pointerdown', pickCanvasColor, false);
gameTools.style.height = "200px";
const config = {
attributes: true,
childList: false,
subtree: false
};
const heightObserver = new MutationObserver(adjustChatSize);
heightObserver.observe(gameTools, config);
heightObserver.observe(chatBox, config);
const colorsDiv = document.querySelector("#gameToolsColors");
colorsDiv.addEventListener("click", removeColor, false);
(function addPicker() {
colorPicker.type = "color";
colorPicker.setAttribute("style", "opacity: 0; width: 30px; cursor: pointer;");
colorPicker.oninput = updatePicker;
colorPickerWrapper.setAttribute("style", wrapperStyle);
colorPickerWrapper.style.backgroundColor = colorPicker.value;
colorPickerWrapper.appendChild(colorPicker);
colorInput.oninput = updateInput;
colorInput.addEventListener("click", selectInputText, false);
colorInput.setAttribute("style", inputStyle);
colorInput.setAttribute("spellcheck", "false");
colorInput.value = colorPicker.value;
gameTools.appendChild(colorPickerWrapper);
gameTools.appendChild(colorInput);
})();
let paletteIndex = 0;
(function addButtons() {
let prevPaletteBtn = document.createElement("button");
let nextPaletteBtn = document.createElement("button");
let saveColorBtn = document.createElement("button");
addButton(saveColorBtn, "save", "5px 5px 5px 70px;");
addButton(prevPaletteBtn, "arrow-left", "5px 5px 5px 40px;");
addButton(nextPaletteBtn, "arrow-right", "5px 5px 5px 100px;");
prevPaletteBtn.addEventListener("click", prevPalette, false);
nextPaletteBtn.addEventListener("click", nextPalette, false);
saveColorBtn.addEventListener("click", saveColor, false);
})();
function nextPalette() {
paletteIndex < (palettes.length - 1) && paletteIndex++;
changePalette(paletteIndex);
}
function prevPalette() {
paletteIndex > 0 && paletteIndex--;
changePalette(paletteIndex);
}
function saveColor() {
let currentPalette = palettes[paletteIndex];
while (currentPalette.length >= 39) {
paletteIndex++;
if (paletteIndex === palettes.length) {
palettes.push([]);
}
currentPalette = palettes[paletteIndex];
}
palettes[paletteIndex].push(colorPicker.value);
changePalette(paletteIndex);
localStorage.setItem("palettes", JSON.stringify(palettes));
}
function removeColor(event) {
if (event.altKey) {
event.preventDefault();
let color = event.target;
var index = Array.prototype.indexOf.call(colorButtons, color);
if (index >= 0 && paletteIndex > 1) {
let palette = palettes[paletteIndex]
palette.splice(index, 1);
if (!palette.length) {
palettes.splice(paletteIndex, 1);
paletteIndex--;
}
changePalette(paletteIndex);
localStorage.setItem("palettes", JSON.stringify(palettes));
}
}
}
function addButton(button, icon, pos, id = "") {
let buttonStyle = `margin: ${pos};
position: absolute;
height: 20px;
border: none;
background-color: #CBCBCB;
border-radius: 5px;`;
button.setAttribute("style", buttonStyle);
button.setAttribute("class", `fas fa-${icon}`);
button.id = id;
gameTools.appendChild(button);
}
function updatePicker(event) {
let color = event.target.value;
colorPickerWrapper.style.backgroundColor = color;
colorInput.value = color;
setColor(color);
}
function updateInput(event) {
let color = event.target.value;
colorPickerWrapper.style.backgroundColor = color;
colorPicker.value = color;
setColor(color);
}
function setColor(color) {
let colorButton = document.querySelector("#gameToolsColors > div:nth-child(1) > div:nth-child(1)");
let prevColor = colorButton.style.backgroundColor;
colorButton.style.backgroundColor = color;
colorButton.dispatchEvent(new Event("pointerdown"));
colorButton.style.backgroundColor = prevColor;
}
function selectInputText() {
colorInput.select();
}
function pickCanvasColor(event) {
if (event.button === 1) {
event.stopImmediatePropagation();
let pos = getPos(event);
let [r, g, b, a] = ctx.getImageData(pos.x, pos.y, 1, 1).data;
let color = `rgb(${r}, ${g}, ${b})`;
setColor(color);
}
}
function getPos(event) {
let canvasRect = canvas.getBoundingClientRect();
let canvasScale = canvas.width / canvasRect.width;
return {
x: (event.clientX - canvasRect.left) * canvasScale,
y: (event.clientY - canvasRect.top) * canvasScale
};
}
function changePalette(palette) {
colorButtons.forEach((button, idx) => {
let color = palettes[palette][idx] || "#fff";
button.style.backgroundColor = color;
});
}
(function getDefaultPalette() {
if (!palettes[0][0]) {
colorButtons.forEach((button, idx) => {
palettes[0][idx] = button.style.backgroundColor;
});
}
})();
function isDrawing() {
return document.querySelector("#gameTools").style.display !== "none";
}
function adjustChatSize() {
chatBox.style.height = isDrawing() ? "calc(100% - 200px)" : "calc(100% - 180px)";
}