// ==UserScript==
// @name Color Picker
// @namespace https://greasyfork.org/users/281093
// @match https://sketchful.io/*
// @grant none
// @version 0.4
// @author Bell
// @description Color picker for Sketchful
// @run-at document-end
// jshint esversion: 6
// ==/UserScript==
let storedPalettes = JSON.parse(localStorage.getItem('palettes'));
let paletteIndex = 0;
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 colorButtons = document.querySelectorAll(".gameToolsColor");
const colorsDiv = document.querySelector("#gameToolsColors");
const colorButton = document.querySelector("#gameToolsColors > div:nth-child(1) > div:nth-child(1)");
const colorPickerWrapper = document.createElement("div");
const colorInput = document.createElement("input");
const colorPicker = document.createElement("input");
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;`;
(function init() {
updatePageStyle();
addListeners();
addObservers();
addPicker();
})();
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);
addButtons();
}
function addObservers() {
const heightObserver = new MutationObserver(adjustChatSize);
const config = {
attributes: true,
childList: false,
subtree: false
};
heightObserver.observe(gameTools, config);
heightObserver.observe(chatBox, config);
}
function addListeners() {
canvas.addEventListener('pointerdown', pickCanvasColor, false);
colorsDiv.addEventListener("click", removeColor, false);
}
function updatePageStyle() {
document.querySelector("#gameToolsSlider").style.top = "77px";
gameTools.style.height = "200px";
getDefaultPalette();
}
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;
let 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 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.altKey) {
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)";
}