Last active
January 4, 2021 06:32
-
-
Save Meshiest/e1791bbb97ac1da34663a83e714dba69 to your computer and use it in GitHub Desktop.
Revisions
-
Meshiest revised this gist
Jan 4, 2021 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -159,6 +159,7 @@ .group::before { content: attr(name); white-space: nowrap; min-width: 40px; height: 24px; padding: 0 4px; -
Meshiest revised this gist
Jan 4, 2021 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -727,7 +727,7 @@ const palette = $('#palette'); const group = document.createElement('div'); group.className = 'group'; group.setAttribute('name', 'Group ' + ($$('.group').length + 1)); const stub = document.createElement('div'); stub.className = 'stub button'; @@ -776,7 +776,7 @@ groups: $$('.group').map((c, columnIndex) => { // convert colors to linear rgb from whatever format is thrown in return { name: c.getAttribute('name') || ('Group ' + (columnIndex + 1)), colors: $$('.color', c).map(e => { // a technique so cursed you will shit the bed (pulling rgb from hex) let [sR, sG, sB] = e.style.backgroundColor.match(/[\d\.]+/g).map(Number); -
Meshiest revised this gist
Jan 4, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -919,5 +919,5 @@ <h2>Example images (Click to demo)</h2> </div> </div> <h1 style="margin-left: 14px;">Palette</h1> <input type="color" id="colorPicker" value="#ffffff"> <div id="palette"></div> -
Meshiest revised this gist
Jan 4, 2021 . 1 changed file with 111 additions and 10 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -105,6 +105,7 @@ display: flex; padding: 2px; align-items: flex-start; position: relative; } .group { @@ -117,6 +118,7 @@ flex-direction: column; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.6); background-color: #335; position: relative; } .group .stub { @@ -141,23 +143,73 @@ margin-bottom: 4px; } .group.selected::after, .group.selected::before { opacity: 1; top: -20px; } .group::after, .group::before { position: absolute; pointer-events: none; opacity: 0; top: -10px; background-color: #335; left: 0; transition: opacity .1s ease, top .1s ease; } .group::before { content: attr(name); min-width: 40px; height: 24px; padding: 0 4px; transform: translate(0%, -100%); display: flex; align-items: center; z-index: 1; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; } .group::after { content: ''; width: 24px; height: 24px; transform: translate(5px, -12px) rotate(45deg); } #palette > .add { margin: 4px; } #palette > .add::before { content: "Description: " attr(description); position: absolute; pointer-events: none; top: -2px; left: 0; transform: translateY(-100%); font-weight: normal; font-size: 14px; } .color { order: 0; width: 32px; height: 32px; margin-bottom: 4px; cursor: pointer; transform: scale(1); transition: transform .1s ease; } .color.selected { width: 28px; height: 28px; border: 2px solid #aad; transform: scale(1.4); z-index: 1; /*border-radius: 50%;*/ } .button:hover { background-color: #779; } @@ -168,6 +220,14 @@ order: 10; } #colorPicker { position: absolute; left: 28px; margin-top: -15px; opacity: 0; pointer-events: none; } </style> <script> @@ -339,7 +399,7 @@ const [r, g, b] = linearRGB([sR, sG, sB]); return { r, g, b, a: 255 }; }), name: div.match(/DIV: ?(.*)/)[1], })), } initPalette(data); @@ -407,11 +467,43 @@ undo(); save(); // rename group on r } else if (e.code === 'KeyR' && !e.ctrlKey && !e.shiftKey) { if (!selected || !selected.classList.contains('group')) return; const name = prompt('Enter a column name', selected.getAttribute('name')); if (name) { selected.setAttribute('name', name); snapshot(); } // change palette description on shift R } else if (e.code === 'KeyR' && !e.ctrlKey && e.shiftKey) { const btn = $('#palette > .add'); const description = prompt('Enter a palette description', btn.getAttribute('description')); if (description) { btn.setAttribute('description', description); snapshot(); } } else if (e.code === 'KeyC' && !e.ctrlKey && !e.shiftKey) { if (!selected || !selected.classList.contains('color')) return; $('#colorPicker').value = '#' + selected.getAttribute('hex'); $('#colorPicker').onchange = e => { selected.setAttribute('hex', e.target.value.replace(/^#/, '')) selected.style.background = e.target.value; snapshot(); $('#colorPicker').onchange = () => {}; }; $('#colorPicker').click(); // save on ctrl s } else if (e.code === 'KeyS' && e.ctrlKey && e.shiftKey) { e.preventDefault(); const name = prompt('Enter a save name', localStorage.lastName || 'Generated'); if (typeof name === 'object') return; localStorage.lastName = name; $('#download').href = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(save(), 0, 2)); $('#download').download = name + '.bp'; $('#download').click(); } else if ((e.code === 'KeyS' || e.code === 'KeyW') && e.ctrlKey) { @@ -474,7 +566,7 @@ if (numGroups < 2) return; modFn(getAt((col + 1) % numGroups, row)); // move color to the left } else if (e.code === 'KeyA' && e.ctrlKey) { e.preventDefault(); // if nothing is selected, ignore @@ -499,6 +591,7 @@ snapshot(); // move color to the right } else if (e.code === 'KeyD' && e.ctrlKey) { e.preventDefault(); if (!selected) return; @@ -508,7 +601,6 @@ const numGroups = $$('.group').length; if (numGroups < 2) return; const el = getAt((col + 1) % numGroups, row); // ignore group movements if (selected.classList.contains('group')) return; @@ -635,6 +727,7 @@ const palette = $('#palette'); const group = document.createElement('div'); group.className = 'group'; group.setAttribute('name', 'Col ' + ($$('.group').length + 1)); const stub = document.createElement('div'); stub.className = 'stub button'; @@ -678,12 +771,12 @@ presetVersion: '1', type: 'ColorPalette', data: { description: $('#palette > .add').getAttribute('description') || 'Built with palette creator', // populate columns groups: $$('.group').map((c, columnIndex) => { // convert colors to linear rgb from whatever format is thrown in return { name: c.getAttribute('name') || ('Col ' + (columnIndex + 1)), colors: $$('.color', c).map(e => { // a technique so cursed you will shit the bed (pulling rgb from hex) let [sR, sG, sB] = e.style.backgroundColor.match(/[\d\.]+/g).map(Number); @@ -708,7 +801,7 @@ function initPalette(data) { if (!data) { data = { description: 'Built with palette creator', groups: [], } } @@ -756,10 +849,14 @@ } }; const btn = addBtn(); btn.setAttribute('description', data.description || 'Generated palette') palette.appendChild(btn); let i = 0; for (const group of data.groups) { const el = createGroup(group.colors, true); el.setAttribute('name', group.name || ('Col' + ++i)) } } @@ -802,6 +899,9 @@ <h2>Keybinds</h2> <tr><td>Ctrl+Shift+S</td><td>Download preset</td></tr> <tr><td>Enter, Shift+E</td><td>Next group, new if last group/no other groups</td></tr> <tr><td>Space</td><td>Unselect selected</td></tr> <tr><td>R</td><td>Rename selected group</td></tr> <tr><td>Shift+R</td><td>Change palette description</td></tr> <tr><td>C</td><td>Show color picker for selected color</td></tr> <tr><td>W/S</td><td>Up/down in group</td></tr> <tr><td>A/D</td><td>Left/Right among groups</td></tr> <tr><td>Shift+W/S</td><td>Swap color up/down in group</td></tr> @@ -819,4 +919,5 @@ <h2>Example images (Click to demo)</h2> </div> </div> <h1 style="margin-left: 14px;">Palette</h1> <input type="color" id="colorPicker" value="#fffff"> <div id="palette"></div> -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -462,6 +462,7 @@ // select the previous group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; if (numGroups < 2) return; modFn(getAt((col + numGroups - 1) % numGroups, row)); } else if (e.code === 'KeyD' && !e.ctrlKey) { @@ -505,6 +506,7 @@ // select the next group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; if (numGroups < 2) return; const el = getAt((col + 1) % numGroups, row); console.log(el, (col + 1) % numGroups, row); -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -470,6 +470,7 @@ // select the next group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; if (numGroups < 2) return; modFn(getAt((col + 1) % numGroups, row)); // delete everything @@ -481,6 +482,7 @@ // select the previous group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; if (numGroups < 2) return; const el = getAt((col + numGroups - 1) % numGroups, row); // ignore group movements -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -785,6 +785,7 @@ <h2>Usage</h2> <li>Selected groups/colors can be re-arranged with the below keybinds.</group.> <li>Paste an image from clipboard to upload to the color selector.</li> <li>Paste a preset from clipboard to replace the current preset.</li> <li>Paste a blockland colorset from clipboard to replace the current preset.</li> <li>Brickadia will not load any palettes larger than 16x16.</li> <li>Click <a href="#noinfo">here</a> to hide info.</li> </ul> -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -342,7 +342,6 @@ name: div.match(/DIV: (.*)/)[1], })), } initPalette(data); snapshot(); return; -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 5 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -344,6 +344,7 @@ } console.log(data); initPalette(data); snapshot(); return; } @@ -353,8 +354,10 @@ const data = JSON.parse(pasteData); if (data.formatVersion === '1' && data.presetVersion === '1' && data.type === 'ColorPalette') { initPalette(data.data); snapshot(); } } catch (e) { console.error('error pasting json', e); } -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 27 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -321,14 +321,40 @@ } else { const pasteData = e.clipboardData.getData('Text'); const blocklandRegex = /(((\d{1,3} \d{1,3} \d{1,3} \d{1,3}|\d\.\d{3} \d\.\d{3} \d\.\d{3} \d\.\d{3})\r?\n)+DIV:.*)/g; const blMatches = pasteData.match(blocklandRegex); if (blMatches) { const data = { description: 'Imported from blockland colorset', groups: blMatches.map(div => ({ colors: div .match(/(\d{1,3} \d{1,3} \d{1,3} \d{1,3}|\d\.\d{3} \d\.\d{3} \d\.\d{3} \d\.\d{3})/g) .map(c => { let [sR, sG, sB] = c.split(' ').map(Number); if (c.match(/\d\.\d{3} \d\.\d{3} \d\.\d{3} \d\.\d{3}/)) { sR *= 255; sG *= 255; sB *= 255; } const [r, g, b] = linearRGB([sR, sG, sB]); return { r, g, b, a: 255 }; }), name: div.match(/DIV: (.*)/)[1], })), } console.log(data); initPalette(data); return; } // try to parse the pasted data if (pasteData && pasteData.length > 0) { try { const data = JSON.parse(pasteData); if (data.formatVersion === '1' && data.presetVersion === '1' && data.type === 'ColorPalette') return initPalette(data.data); } catch (e) { console.error('error pasting json', e); } -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 5 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -35,6 +35,9 @@ pointer-events: none; } #noinfo:target { display: none; } .eyedrop-container { width: 600px; @@ -743,7 +746,7 @@ <div id="dropper"></div> </div> </div> <div class="info" id="noinfo"> <a id="download" style="display: none"></a> <h1>Info</h1> <h2>Usage</h2> @@ -755,6 +758,7 @@ <h2>Usage</h2> <li>Paste an image from clipboard to upload to the color selector.</li> <li>Paste a preset from clipboard to replace the current preset.</li> <li>Brickadia will not load any palettes larger than 16x16.</li> <li>Click <a href="#noinfo">here</a> to hide info.</li> </ul> <h2>Keybinds</h2> <table class="keybinds"> -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 15 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -19,6 +19,12 @@ #dropper { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); display: flex; align-items: center; justify-content: center; font-size: 30px; text-align: center; width: 40px; height: 40px; border-radius: 50%; @@ -170,6 +176,7 @@ const history = []; let undoStack = []; let used = []; // add a palette snapshot to history // if you read this code and want to kill me, I understand @@ -223,6 +230,12 @@ dropper.style.transform = 'translate(-50%, -100%)'; } dropper.style.background = `rgb(${pixels[off]}, ${pixels[off+1]}, ${pixels[off+2]})`; const hex = [pixels[off], pixels[off+1], pixels[off+2]].map(i => i.toString(16).padStart(2, '0')).join(''); if (used.includes(hex)) dropper.innerHTML = '✓'; else dropper.innerHTML = ''; }; // add the color on click @@ -623,6 +636,7 @@ // save the palette to data function save() { used = []; const data = { // generate the preset file formatVersion: '1', @@ -642,6 +656,7 @@ // convert to hex const hex = [sR, sG, sB].map(i => i.toString(16).padStart(2, '0')).join(''); used.push(hex); // convert sRGB to linear rgb const [r, g, b] = linearRGB([sR, sG, sB]); -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -370,7 +370,7 @@ $('#download').download = 'Generated' + '.bp'; $('#download').click(); } else if ((e.code === 'KeyS' || e.code === 'KeyW') && e.ctrlKey) { e.preventDefault(); // prevent annoying save popup } else if (e.code === 'KeyW') { -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -370,6 +370,8 @@ $('#download').download = 'Generated' + '.bp'; $('#download').click(); } else if (e.code === 'KeyS' && e.ctrlKey) { e.preventDefault(); // prevent annoying save popup } else if (e.code === 'KeyW') { // if nothing is selected, select the first group -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -364,7 +364,7 @@ save(); // save on ctrl s } else if (e.code === 'KeyS' && e.ctrlKey && e.shiftKey) { e.preventDefault(); $('#download').href = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(save(), 0, 2)); $('#download').download = 'Generated' + '.bp'; @@ -745,7 +745,7 @@ <h2>Keybinds</h2> <tbody> <tr><td>Ctrl+Z</td><td>Undo</td></tr> <tr><td>Ctrl+Shift+Z</td><td>Redo</td></tr> <tr><td>Ctrl+Shift+S</td><td>Download preset</td></tr> <tr><td>Enter, Shift+E</td><td>Next group, new if last group/no other groups</td></tr> <tr><td>Space</td><td>Unselect selected</td></tr> <tr><td>W/S</td><td>Up/down in group</td></tr> -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 55 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -324,7 +324,7 @@ const getAt = (col, row=-1) => { const group = $$('.group')[col]; const colors = $$('.color', group); return row > -1 && colors.length > row ? colors[Math.min(row, colors.length - 1)] : row == -2 ? colors[colors.length - 1] @@ -409,7 +409,7 @@ } } } else if (e.code === 'KeyA' && !e.ctrlKey) { // if nothing is selected, select the first group if (!selected) return modFn(getAt(0)); @@ -418,12 +418,61 @@ const numGroups = $$('.group').length; modFn(getAt((col + numGroups - 1) % numGroups, row)); } else if (e.code === 'KeyD' && !e.ctrlKey) { if (!selected) return modFn(getAt(0)); // select the next group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; modFn(getAt((col + 1) % numGroups, row)); // delete everything } else if (e.code === 'KeyA' && e.ctrlKey) { e.preventDefault(); // if nothing is selected, ignore if (!selected) return; // select the previous group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; const el = getAt((col + numGroups - 1) % numGroups, row); // ignore group movements if (selected.classList.contains('group')) return; // if the dest is a group, put the color in there if (el.classList.contains('group')) { el.appendChild(selected); } else { // move selected to the element el.before(selected); } snapshot(); } else if (e.code === 'KeyD' && e.ctrlKey) { e.preventDefault(); if (!selected) return; // select the next group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; const el = getAt((col + 1) % numGroups, row); console.log(el, (col + 1) % numGroups, row); // ignore group movements if (selected.classList.contains('group')) return; // if the dest is a group, put the color in there if (el.classList.contains('group')) { el.appendChild(selected); } else { // move selected to the element el.before(selected); } snapshot(); // delete everything } else if (e.code === 'Delete' && e.shiftKey && e.ctrlKey) { e.preventDefault(); @@ -612,11 +661,8 @@ } } const palette = $('#palette'); palette.innerHTML = ''; // handle all click events through the parent due to the nature of the undo/redo $('#palette').onclick = e => { @@ -659,7 +705,6 @@ }; palette.appendChild(addBtn()); for (const group of data.groups) { createGroup(group.colors, true); @@ -705,8 +750,9 @@ <h2>Keybinds</h2> <tr><td>Space</td><td>Unselect selected</td></tr> <tr><td>W/S</td><td>Up/down in group</td></tr> <tr><td>A/D</td><td>Left/Right among groups</td></tr> <tr><td>Shift+W/S</td><td>Swap color up/down in group</td></tr> <tr><td>Shift+A/D</td><td>Swap color to group left/right or move group</td></tr> <tr><td>Ctrl+A/D</td><td>Move color to group left/right</td></tr> <tr><td>Delete, Shift+X</td><td>Remove color, will remove group if group is empty</td></tr> <tr><td>Ctrl+Shift+Delete</td><td>Reset palette</td></tr> </tbody> -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -674,7 +674,7 @@ <ol> <li>Paste an image from your clipboard.</li> <li>Hover over the colors to preview.</li> <li>Click on color to add to palette.</li> </ol> </div> <canvas id="selector"></canvas> -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 9 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -424,8 +424,14 @@ const numGroups = $$('.group').length; modFn(getAt((col + 1) % numGroups, row)); // delete everything } else if (e.code === 'Delete' && e.shiftKey && e.ctrlKey) { e.preventDefault(); initPalette(); snapshot(); // delete selected thing } else if (e.code === 'Delete' && !e.shiftKey && !e.ctrlKey || e.code === 'KeyX' && e.shiftKey) { if (!selected) return; // delete a group, select previous group @@ -702,6 +708,7 @@ <h2>Keybinds</h2> <tr><td>Shift+W/S</td><td>Move color up/down in group</td></tr> <tr><td>Shift+A/D</td><td>Move color to group left/right or move group</td></tr> <tr><td>Delete, Shift+X</td><td>Remove color, will remove group if group is empty</td></tr> <tr><td>Ctrl+Shift+Delete</td><td>Reset palette</td></tr> </tbody> </table> <h2>Example images (Click to demo)</h2> -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 11 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -260,6 +260,8 @@ try { if (localStorage.temp) { initPalette(JSON.parse(localStorage.temp)); } else { initPalette(); } } catch (e) { console.warn('error parsing json', e); @@ -423,7 +425,7 @@ modFn(getAt((col + 1) % numGroups, row)); // deselect everything } else if (e.code === 'Delete' || e.code === 'KeyX' && e.shiftKey) { if (!selected) return; // delete a group, select previous group @@ -457,7 +459,7 @@ $$('.selected').forEach(e => e.classList.remove('selected')); // next group/new group } else if (e.key === 'Enter' || e.code === 'KeyE' && e.shiftKey) { // nothing is selected - create a new group if (!selected) { createGroup([]); @@ -604,8 +606,11 @@ } } console.log('a'); const palette = $('#palette'); console.log('b'); palette.innerHTML = ''; console.log('c'); // handle all click events through the parent due to the nature of the undo/redo $('#palette').onclick = e => { @@ -648,11 +653,11 @@ }; palette.appendChild(addBtn()); console.log(palette); for (const group of data.groups) { createGroup(group.colors, true); } } </script> @@ -690,13 +695,13 @@ <h2>Keybinds</h2> <tr><td>Ctrl+Z</td><td>Undo</td></tr> <tr><td>Ctrl+Shift+Z</td><td>Redo</td></tr> <tr><td>Ctrl+S</td><td>Download preset</td></tr> <tr><td>Enter, Shift+E</td><td>Next group, new if last group/no other groups</td></tr> <tr><td>Space</td><td>Unselect selected</td></tr> <tr><td>W/S</td><td>Up/down in group</td></tr> <tr><td>A/D</td><td>Left/Right among groups</td></tr> <tr><td>Shift+W/S</td><td>Move color up/down in group</td></tr> <tr><td>Shift+A/D</td><td>Move color to group left/right or move group</td></tr> <tr><td>Delete, Shift+X</td><td>Remove color, will remove group if group is empty</td></tr> </tbody> </table> <h2>Example images (Click to demo)</h2> @@ -706,7 +711,5 @@ <h2>Example images (Click to demo)</h2> </div> </div> </div> <h1 style="margin-left: 14px;">Palette</h1> <div id="palette"></div> -
Meshiest revised this gist
Jan 3, 2021 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -681,6 +681,7 @@ <h2>Usage</h2> <li>Selected groups/colors can be re-arranged with the below keybinds.</group.> <li>Paste an image from clipboard to upload to the color selector.</li> <li>Paste a preset from clipboard to replace the current preset.</li> <li>Brickadia will not load any palettes larger than 16x16.</li> </ul> <h2>Keybinds</h2> <table class="keybinds"> -
Meshiest created this gist
Jan 3, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,711 @@ <style> body, html { margin: 0; background-color: black; color: white; font-family: monospace; } body { margin: 14px; } #selector { } h1, h2, h3 { margin: 8px 0; } #dropper { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); width: 40px; height: 40px; border-radius: 50%; position: absolute; top: -100px; left: 0; transform: translate(-50%, -100%); pointer-events: none; } .eyedrop-container { width: 600px; height: 600px; resize: both; overflow: scroll; margin: 14px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); background: repeating-conic-gradient(#f5f5f5 0% 25%, white 0% 50%) 50% / 20px 20px; } .eyedrop { position: relative; } .instructions { color: #444; font-weight: bold; position: absolute; top: 14px; left: 14px; background-color: white; box-shadow: 0 0 30px 10px white; } .picker { display: flex; } .info { display: flex; flex-direction: column; } .images { display: flex; flex-flow: row wrap; } .images img { cursor: pointer; width: 100px; height: 100px; object-fit: cover; } .button { background-color: #557; color: white; display: flex; align-items: center; justify-content: center; text-align: center; font-size: 20px; font-weight: bold; height: 32px; user-select: none; cursor: pointer; } #palette { margin: 14px; background-color: #224; display: flex; padding: 2px; align-items: flex-start; } .group { min-width: 32px; padding: 2px; border: 2px solid transparent; margin: 4px; order: 0; display: flex; flex-direction: column; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.6); background-color: #335; } .group .stub { background-color: #112; width: 40px; height: 24px; order: -10; display: flex; margin: -4px; margin-bottom: 4px; } .group.selected { border: 2px solid #aad; } .group.selected .stub { margin: -2px; width: 36px; height: 22px; margin-bottom: 4px; } #palette > .add { margin: 4px; } .color { order: 0; width: 32px; height: 32px; margin-bottom: 4px; cursor: pointer; } .color.selected { width: 28px; height: 28px; border: 2px solid #aad; border-radius: 50%; } .button:hover { background-color: #779; } .button:active { background-color: #99b; } .add { width: 32px; order: 10; } </style> <script> // poor man's jquery const $ = document.querySelector.bind(document); const $$ = (q, el) => Array.from((el || document).querySelectorAll(q)); let pixels, dropWidth, dropHeight; const history = []; let undoStack = []; // add a palette snapshot to history // if you read this code and want to kill me, I understand function snapshot() { history.push($('#palette').innerHTML); save(); // remove entries over 1000 history.splice(1000); undoStack = []; } // undo an undo function redo() { if (!undoStack.length) return; const state = undoStack.pop(); history.push(state); $('#palette').innerHTML = state; } // undo some history function undo() { if (history.length < 2) return; const state = history.pop(); undoStack.push(state); $('#palette').innerHTML = history[history.length - 1]; } window.onload = () => { // hide the dropper on mouse leave $('#selector').onmouseleave = e => { const dropper = $('#dropper'); dropper.style.display = 'none'; }; // set the eyedrop color on hover $('#selector').onmousemove = e => { if (!pixels) return; const dropper = $('#dropper'); const { layerX: x, layerY: y } = e; const off = (dropWidth * y + x) * 4; if ((pixels[off+3]) === 0) { dropper.style.display = 'none'; return; } dropper.style.display = 'block'; dropper.style.left = x + 'px'; dropper.style.top = y + 'px'; if (y < 40) { dropper.style.transform = 'translate(-50%, 0)'; } else { dropper.style.transform = 'translate(-50%, -100%)'; } dropper.style.background = `rgb(${pixels[off]}, ${pixels[off+1]}, ${pixels[off+2]})`; }; // add the color on click $('#selector').onclick = e => { if (!pixels) return; const { layerX: x, layerY: y } = e; const off = (dropWidth * y + x) * 4; const selected = $('.selected'); const hex = [pixels[off], pixels[off+1], pixels[off+2]].map(i => i.toString(16).padStart(2, '0')).join(''); if ((pixels[off+3]) === 0) return; if (!selected) { // create a new group if there is nothing currently selected const group = createGroup([]); group.appendChild(createColor(hex, true)); snapshot(); } else if (selected.classList.contains('group')) { // add a new color to the group if a group is selected selected.appendChild(createColor(hex, true)); snapshot(); } else if (selected.classList.contains('color') && selected.getAttribute('hex') !== hex) { // update a color if a color is selected selected.style.background = '#' + hex; selected.setAttribute('hex', hex); snapshot(); } }; $$('.images img').forEach(el => el.onclick = () => renderEyedropImage(el)); try { if (localStorage.temp) { initPalette(JSON.parse(localStorage.temp)); } } catch (e) { console.warn('error parsing json', e); initPalette(); } snapshot(); }; // swap to elements in dom function swapDom(a, b) { const aParent = a.parentNode; const bParent = b.parentNode; const aHolder = document.createElement('div'); const bHolder = document.createElement('div'); aParent.replaceChild(aHolder, a); bParent.replaceChild(bHolder, b); aParent.replaceChild(b, aHolder); bParent.replaceChild(a, bHolder); } // when you paste, render the image on the canvas document.onpaste = e => { const items = Array.from(e.clipboardData.items) .filter(i => i.type.indexOf('image') === 0); if (items.length > 0) { const reader = new FileReader(); reader.onload = function(event) { const img = new Image(); img.src = event.target.result; img.onload = res => { if (img.width > 0 && img.height > 0) { renderEyedropImage(img); } } }; reader.readAsDataURL(items[0].getAsFile()); } else { const pasteData = e.clipboardData.getData('Text'); // try to parse the pasted data if (pasteData && pasteData.length > 0) { try { const data = JSON.parse(pasteData); if (data.formatVersion === '1' && data.presetVersion === '1' && data.type === 'ColorPalette') initPalette(data.data); } catch (e) { console.error('error pasting json', e); } } } }; // get the color or group given a column and a row const getAt = (col, row=-1) => { const group = $$('.group')[col]; const colors = $$('.color', group); return row > -1 ? colors[Math.min(row, colors.length - 1)] : row == -2 ? colors[colors.length - 1] : group; }; // get the position of a color/group const getIndex = el => { const groups = $$('.group'); // if the selected thing is a group, return -1 for the row if (el.classList.contains('group')) return [groups.findIndex(e => e == el), -1]; // otherwise return the group and index return [groups.findIndex(e => e == el.parentNode), $$('.color', el.parentNode).findIndex(e => e == el)]; }; document.onkeydown = e => { const selected = $('.selected'); // if shift key is pressed, use swap instead of select const modFn = e.shiftKey ? el => { // if the swap would be illegal, do a select instead if (el.classList.contains('group') && selected.classList.contains('color') || selected.classList.contains('group') && el.classList.contains('color')) return select(el); // swap the dom and save to history swapDom(selected, el); snapshot(); } : select; // undo and redo on CTRL + Z if (e.code === 'KeyZ' && e.ctrlKey) { if (e.shiftKey) redo() else undo(); save(); // save on ctrl s } else if (e.code === 'KeyS' && e.ctrlKey) { e.preventDefault(); $('#download').href = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(save(), 0, 2)); $('#download').download = 'Generated' + '.bp'; $('#download').click(); } else if (e.code === 'KeyW') { // if nothing is selected, select the first group if (!selected) return modFn(getAt(0)); const [col, row] = getIndex(selected); const lastColor = getAt(col, -2); // if the group is selected, select the last color if ((row === -1 || row === 0 && e.shiftKey) && lastColor) { modFn(lastColor); // select the group if it's the first color } else if (row === 0) { modFn(getAt(col)); // otherwise select the previous color } else { modFn(getAt(col, row-1)); } } else if (e.code === 'KeyS') { const selected = $('.selected'); // if nothing is selected, select the first group if (!selected) return modFn(getAt(0)); const [col, row] = getIndex(selected); const firstColor = getAt(col, 0); // if the group is selected, select the last color if (row === -1 && firstColor) { modFn(firstColor); // otherwise select the previous color } else { // if there's no more colors in this group, select the group if (row + 1 >= $$('.color', getAt(col)).length) { modFn(getAt(col, e.shiftKey ? 0 : -1)); } else { // otherwise select the next color modFn(getAt(col, row+1)); } } } else if (e.code === 'KeyA') { // if nothing is selected, select the first group if (!selected) return modFn(getAt(0)); // select the previous group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; modFn(getAt((col + numGroups - 1) % numGroups, row)); } else if (e.code === 'KeyD') { // select the next group + wrap around const [col, row] = getIndex(selected); const numGroups = $$('.group').length; modFn(getAt((col + 1) % numGroups, row)); // deselect everything } else if (e.code === 'Delete') { if (!selected) return; // delete a group, select previous group if (selected.classList.contains('group')) { if (selected.previousSibling && selected.previousSibling.classList.contains('group')) // select the previous group select(selected.previousSibling); else { // select the first group const groups = $$('.group').filter(g => g !== selected); if (groups.length > 0) select(groups[0]); } // delete a color, select previous color } else if (selected.classList.contains('color')) { // if the previous sibling is a color, select it if (selected.previousSibling.classList.contains('color')) select(selected.previousSibling); else if (selected.nextSibling) select(selected.nextSibling); else // select the group instead select(selected.parentNode); } selected.remove(); snapshot(); // delete whatever is selected } else if (e.code === 'Space') { $$('.selected').forEach(e => e.classList.remove('selected')); // next group/new group } else if (e.key === 'Enter') { // nothing is selected - create a new group if (!selected) { createGroup([]); snapshot(); // a group is selected } else if (selected.classList.contains('group')) { // if there is a next group, select it if (selected.nextSibling) { select(selected.nextSibling); } else { // otherwise create a new group createGroup([]); snapshot(); } } } else { // debug key stuff // console.log(e.key, e.code, e); } }; // update the color selecting canvas with an image function renderEyedropImage(image) { // create the element const canvas = $('#selector'); const ctx = canvas.getContext('2d'); // set the canvas size canvas.style.width = (dropWidth = canvas.width = ctx.canvas.width = image.naturalWidth) + 'px'; canvas.style.height = (dropHeight = canvas.height = ctx.canvas.height = image.naturalHeight) + 'px'; // draw the image ctx.drawImage(image, 0, 0); const imageData = ctx.getImageData(0, 0, image.naturalWidth, image.naturalHeight); pixels = imageData.data; $('.instructions').style.display = 'none'; } function addBtn() { const elem = document.createElement('div'); elem.className = 'add button'; elem.innerText = '+'; return elem; } function select(elem) { if (!elem) return; $$('.selected').forEach(e => e.classList.remove('selected')); elem.classList.add('selected'); } // create a color function createColor(hex, ignoreSelect) { const colorElem = document.createElement('div'); colorElem.className = 'color'; colorElem.setAttribute('hex', hex); colorElem.style.backgroundColor = '#' + hex; if (!ignoreSelect) select(colorElem); return colorElem; } // create a group function createGroup(colors, ignoreSelect) { const palette = $('#palette'); const group = document.createElement('div'); group.className = 'group'; const stub = document.createElement('div'); stub.className = 'stub button'; group.appendChild(stub); group.appendChild(addBtn()); palette.appendChild(group); if (!ignoreSelect) select(group); for (const {r: lR, g: lG, b: lB} of colors) { const [r, g, b] = sRGB([lR, lG, lB]); group.appendChild(createColor([r, g, b].map(i => i.toString(16).padStart(2, '0')).join(''), true)); } return group; } // convert srgb to linear rgb const linearRGB = rgba => rgba.map((c, i) => i === 3 ? c : Math.round(((c/255) > 0.04045 ? Math.pow((c/255) * (1.0 / 1.055) + 0.0521327, 2.4 ) : (c/255) * (1.0 / 12.92))*255) ); // convert linear rgb to srgb const sRGB = linear => linear.map((c, i) => i === 3 ? c : Math.round(((c/255) > 0.0031308 ? 1.055 * Math.pow((c/255), 1/2.4) - 0.055 : c / 255 * 12.92)*255) ); // save the palette to data function save() { const data = { // generate the preset file formatVersion: '1', presetVersion: '1', type: 'ColorPalette', data: { description: 'Generated', // populate columns groups: $$('.group').map((c, columnIndex) => { // convert colors to linear rgb from whatever format is thrown in return { name: 'Col ' + (columnIndex + 1), colors: $$('.color', c).map(e => { // a technique so cursed you will shit the bed (pulling rgb from hex) let [sR, sG, sB] = e.style.backgroundColor.match(/[\d\.]+/g).map(Number); // convert to hex const hex = [sR, sG, sB].map(i => i.toString(16).padStart(2, '0')).join(''); // convert sRGB to linear rgb const [r, g, b] = linearRGB([sR, sG, sB]); return {r, g, b, a: 255}; }) }; }), }, }; localStorage.temp = JSON.stringify(data.data); return data; } function initPalette(data) { if (!data) { data = { description: 'New Palette', groups: [], } } const palette = $('#palette'); palette.innerHTML = ''; // handle all click events through the parent due to the nature of the undo/redo $('#palette').onclick = e => { const elem = e.target; // toggle color select if (elem.classList.contains('color')) { if (elem.classList.contains('selected')) elem.classList.remove('selected'); else select(elem); } // detect clicks on buttons if (elem.classList.contains('button')) { // button is in the group if (elem.parentNode.classList.contains('group')) { const group = elem.parentNode; // group add button if (elem.classList.contains('add')) { group.appendChild(createColor('ffffff')); snapshot(); } // group stub button (toggle select) if (elem.classList.contains('stub')) { if (group.classList.contains('selected')) group.classList.remove('selected'); else select(group); } } else { // palette add button if (elem.classList.contains('add')) { createGroup([]); snapshot(); } } } }; palette.appendChild(addBtn()); for (const group of data.groups) { createGroup(group.colors, true); } snapshot(); } </script> <div class="picker"> <div class="eyedrop-container"> <div class="eyedrop"> <div class="instructions"> <ol> <li>Paste an image from your clipboard.</li> <li>Hover over the colors to preview.</li> <li>Click or press a number on your keyboard to add to palette.</li> </ol> </div> <canvas id="selector"></canvas> <div id="dropper"></div> </div> </div> <div class="info"> <a id="download" style="display: none"></a> <h1>Info</h1> <h2>Usage</h2> <ul> <li>Click + buttons to add groups/colors to the palette.</li> <li>Click the group stub or a color to select a color.</li> <li>Clicking on the color selector image will modify the selected color or add a new color to the group.</li> <li>Selected groups/colors can be re-arranged with the below keybinds.</group.> <li>Paste an image from clipboard to upload to the color selector.</li> <li>Paste a preset from clipboard to replace the current preset.</li> </ul> <h2>Keybinds</h2> <table class="keybinds"> <thead><tr><th>Key</th><th>Description</th></tr></thead> <tbody> <tr><td>Ctrl+Z</td><td>Undo</td></tr> <tr><td>Ctrl+Shift+Z</td><td>Redo</td></tr> <tr><td>Ctrl+S</td><td>Download preset</td></tr> <tr><td>Enter</td><td>Next group, new if last group/no other groups</td></tr> <tr><td>Space</td><td>Unselect selected</td></tr> <tr><td>W/S</td><td>Up/down in group</td></tr> <tr><td>A/D</td><td>Left/Right among groups</td></tr> <tr><td>Shift+W/S</td><td>Move color up/down in group</td></tr> <tr><td>Shift+A/D</td><td>Move color to group left/right or move group</td></tr> <tr><td>Delete</td><td>Remove color, will remove group if group is empty</td></tr> </tbody> </table> <h2>Example images (Click to demo)</h2> <div class="images"> <img src="https://i.imgur.com/qzF7dNY.png" crossorigin="anonymous"> <img src="https://i.imgur.com/wdUUC5I.png" crossorigin="anonymous"> </div> </div> </div> <style id="dynamic"></style> <h1 style="margin-left: 14px;">Palette</h1> <div id="palette"> </div>