ported to static site, removed _ext folder, split hbs files into partials
17
build.js
@ -2,11 +2,11 @@ const fs = require('fs');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
const include = require('gulp-include');
|
const include = require('gulp-include');
|
||||||
const hb = require('gulp-hb');
|
const handlebars = require('gulp-hb');
|
||||||
const sass = require('gulp-sass');
|
const sass = require('gulp-sass');
|
||||||
const rename = require('gulp-rename');
|
const rename = require('gulp-rename');
|
||||||
|
|
||||||
const hb_svg = require('handlebars-helper-svg');
|
//const hb_svg = require('handlebars-helper-svg');
|
||||||
|
|
||||||
const BUILDDIR = process.argv[2] || './build/';
|
const BUILDDIR = process.argv[2] || './build/';
|
||||||
|
|
||||||
@ -30,7 +30,6 @@ function copy_logs() {
|
|||||||
function render_js(){
|
function render_js(){
|
||||||
gulp.src('./js/*.js')
|
gulp.src('./js/*.js')
|
||||||
.pipe(include({includePaths: [
|
.pipe(include({includePaths: [
|
||||||
'_ext/scripts',
|
|
||||||
'js',
|
'js',
|
||||||
'!js/_*.js',
|
'!js/_*.js',
|
||||||
]}))
|
]}))
|
||||||
@ -41,16 +40,18 @@ function render_js(){
|
|||||||
|
|
||||||
function render_css(){
|
function render_css(){
|
||||||
gulp.src('css/*.scss')
|
gulp.src('css/*.scss')
|
||||||
.pipe(sass({includePaths: ['css', '_ext/sass', '_ext/modules/css']}))
|
.pipe(sass({includePaths: ['css']}))
|
||||||
.pipe(gulp.dest(BUILDDIR));
|
.pipe(gulp.dest(BUILDDIR));
|
||||||
}
|
}
|
||||||
|
|
||||||
function compile_page(){
|
function compile_page(){
|
||||||
gulp.src(path.join('./views/index.hbs'))
|
gulp.src(path.join('./views/index.hbs'))
|
||||||
.pipe(hb({encoding: 'utf8'})
|
.pipe(include({includePaths: ['/svg']}))
|
||||||
.partials('./_ext/modules/_*.hbs')
|
|
||||||
.helpers({ svg: hb_svg })
|
.pipe(handlebars({encoding: 'utf8', debug: true, bustCache: true})
|
||||||
.helpers('./_ext/modules/hbs/helpers/**/*.js')
|
.partials('./views/[!index]*.hbs')
|
||||||
|
//.helpers({ svg: hb_svg })
|
||||||
|
.helpers('./helpers/**/*.js')
|
||||||
.data({
|
.data({
|
||||||
projectSlug: 'pixel-editor',
|
projectSlug: 'pixel-editor',
|
||||||
title: 'Lospec Pixel Editor',
|
title: 'Lospec Pixel Editor',
|
||||||
|
@ -296,7 +296,7 @@ svg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.drawingCanvas {
|
.drawingCanvas {
|
||||||
cursor: url('/pixel-art-where-to-start/pencil-tool-cursor.png');
|
cursor: url('/pixel-editor/pencil-tool-cursor.png');
|
||||||
|
|
||||||
border: solid 1px #fff;
|
border: solid 1px #fff;
|
||||||
image-rendering: optimizeSpeed;
|
image-rendering: optimizeSpeed;
|
||||||
|
41
helpers/svg.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const handlebars = require("handlebars");
|
||||||
|
const ltx = require("ltx");
|
||||||
|
const resolve = require("resolve");
|
||||||
|
|
||||||
|
const path = "../svg/";
|
||||||
|
const nameToModule = {};
|
||||||
|
const cache = {};
|
||||||
|
|
||||||
|
module.exports = function (name, opts) {
|
||||||
|
name = path + name;
|
||||||
|
|
||||||
|
const mod =
|
||||||
|
nameToModule[name] ||
|
||||||
|
(nameToModule[name] = resolve.sync(name, {
|
||||||
|
extensions: [".svg"],
|
||||||
|
}));
|
||||||
|
|
||||||
|
const content =
|
||||||
|
cache[name] || (cache[name] = fs.readFileSync(mod, "utf-8"));
|
||||||
|
|
||||||
|
const svg = parse(content);
|
||||||
|
|
||||||
|
Object.assign(svg.attrs, opts.hash);
|
||||||
|
|
||||||
|
return new handlebars.SafeString(svg.root().toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.cache = cache;
|
||||||
|
|
||||||
|
function parse(xml, mod) {
|
||||||
|
const svg = ltx.parse(xml);
|
||||||
|
if (svg.name != "svg") {
|
||||||
|
throw new TypeError("Input must be an SVG");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete svg.attrs.xmlns;
|
||||||
|
delete svg.attrs["xmlns:xlink"];
|
||||||
|
|
||||||
|
return svg;
|
||||||
|
}
|
15
js/_logs.js
@ -1,15 +0,0 @@
|
|||||||
var rawFile = new XMLHttpRequest();
|
|
||||||
rawFile.open("GET", '/pixel-editor/latestLog.html', false);
|
|
||||||
rawFile.onreadystatechange = function ()
|
|
||||||
{
|
|
||||||
if(rawFile.readyState === 4)
|
|
||||||
{
|
|
||||||
if(rawFile.status === 200 || rawFile.status == 0)
|
|
||||||
{
|
|
||||||
var allText = rawFile.responseText;
|
|
||||||
|
|
||||||
document.getElementById("latest-update").innerHTML = allText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rawFile.send(null);
|
|
@ -103,7 +103,7 @@ function newPixel (width, height, editorMode, fileContent = null) {
|
|||||||
|
|
||||||
// If the user selected a palette and isn't opening a file, I load the selected palette
|
// If the user selected a palette and isn't opening a file, I load the selected palette
|
||||||
if (selectedPalette != 'Choose a palette...' && fileContent == null) {
|
if (selectedPalette != 'Choose a palette...' && fileContent == null) {
|
||||||
|
console.log('HELO', selectedPalette, palettes[selectedPalette])
|
||||||
//if this palette isnt the one specified in the url, then reset the url
|
//if this palette isnt the one specified in the url, then reset the url
|
||||||
if (!palettes[selectedPalette].specified)
|
if (!palettes[selectedPalette].specified)
|
||||||
history.pushState(null, null, '/pixel-editor');
|
history.pushState(null, null, '/pixel-editor');
|
||||||
|
@ -1,17 +1,68 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//when the page is done loading, you can get ready to start
|
//when the page is done loading, you can get ready to start
|
||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
|
|
||||||
featureToggles.onLoad();
|
featureToggles.onLoad();
|
||||||
|
|
||||||
currentTool.updateCursor();
|
currentTool.updateCursor();
|
||||||
|
|
||||||
|
//check if there are any url parameters
|
||||||
|
if (window.location.pathname.replace('/pixel-editor/','').length <= 1) {
|
||||||
|
console.log('no url parameters were found');
|
||||||
|
|
||||||
//if the user specified dimensions
|
//show splash screen
|
||||||
if (specifiedDimentions) {
|
showDialogue('splash', false);
|
||||||
//create a new pixel
|
}
|
||||||
newPixel(getValue('size-width'), getValue('size-height'), getValue('editor-mode'));
|
|
||||||
} else {
|
|
||||||
//otherwise show the new pixel dialog
|
|
||||||
showDialogue('splash', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//url parameters were specified
|
||||||
|
else {
|
||||||
|
console.log('loading preset from url parameters', window.location.pathname);
|
||||||
|
|
||||||
|
let args = window.location.pathname.split('/');
|
||||||
|
let paletteSlug = args[2];
|
||||||
|
let dimentions = args[3];
|
||||||
|
|
||||||
|
//fetch palette via lospec palette API
|
||||||
|
fetch('https://lospec.com/palette-list/'+paletteSlug+'.json')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
//palette loaded successfully
|
||||||
|
console.log('loaded palette', data);
|
||||||
|
palettes[paletteSlug] = data;
|
||||||
|
palettes[paletteSlug].specified = true;
|
||||||
|
|
||||||
|
//refresh list of palettes
|
||||||
|
document.getElementById('palette-menu-splash').refresh();
|
||||||
|
|
||||||
|
//if the dimentions were specified
|
||||||
|
if (dimentions && dimentions.length >= 3 && dimentions.includes('x')) {
|
||||||
|
let width = dimentions.split('x')[0];
|
||||||
|
let height = dimentions.split('x')[1];
|
||||||
|
|
||||||
|
console.log('dimentions were specified',width,'x',height)
|
||||||
|
|
||||||
|
//firstPixel = false;
|
||||||
|
|
||||||
|
//create new document
|
||||||
|
newPixel(width, height, getValue('editor-mode'));
|
||||||
|
}
|
||||||
|
|
||||||
|
//dimentions were not specified -- show splash screen with palette preselected
|
||||||
|
else {
|
||||||
|
//show splash
|
||||||
|
showDialogue('new-pixel', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
//error fetching url (either palette doesn't exist, or lospec is down)
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('failed to load palette "'+paletteSlug+'"', error);
|
||||||
|
|
||||||
|
//proceed to splash screen
|
||||||
|
showDialogue('splash', false);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
123
js/_palettes.js
@ -1,3 +1,59 @@
|
|||||||
|
|
||||||
|
palettes = {
|
||||||
|
"Endesga 32": {
|
||||||
|
colors: "be4a2f,d77643,ead4aa,e4a672,b86f50,733e39,3e2731,a22633,e43b44,f77622,feae34,fee761,63c74d,3e8948,265c42,193c3e,124e89,0099db,2ce8f5,ffffff,c0cbdc,8b9bb4,5a6988,3a4466,262b44,181425,ff0044,68386c,b55088,f6757a,e8b796,c28569".split(
|
||||||
|
","
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
"Resurrect 64": {
|
||||||
|
colors: "2e222f,3e3546,625565,966c6c,ab947a,694f62,7f708a,9babb2,c7dcd0,ffffff,6e2727,b33831,ea4f36,f57d4a,ae2334,e83b3b,fb6b1d,f79617,f9c22b,7a3045,9e4539,cd683d,e6904e,fbb954,4c3e24,676633,a2a947,d5e04b,fbff86,165a4c,239063,1ebc73,91db69,cddf6c,313638,374e4a,547e64,92a984,b2ba90,0b5e65,0b8a8f,0eaf9b,30e1b9,8ff8e2,323353,484a77,4d65b4,4d9be6,8fd3ff,45293f,6b3e75,905ea9,a884f3,eaaded,753c54,a24b6f,cf657f,ed8099,831c5d,c32454,f04f78,f68181,fca790,fdcbb0".split(
|
||||||
|
","
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
"AAP-64": {
|
||||||
|
colors: "060608,141013,3b1725,73172d,b4202a,df3e23,fa6a0a,f9a31b,ffd541,fffc40,d6f264,9cdb43,59c135,14a02e,1a7a3e,24523b,122020,143464,285cc4,249fde,20d6c7,a6fcdb,ffffff,fef3c0,fad6b8,f5a097,e86a73,bc4a9b,793a80,403353,242234,221c1a,322b28,71413b,bb7547,dba463,f4d29c,dae0ea,b3b9d1,8b93af,6d758d,4a5462,333941,422433,5b3138,8e5252,ba756a,e9b5a3,e3e6ff,b9bffb,849be4,588dbe,477d85,23674e,328464,5daf8d,92dcba,cdf7e2,e4d2aa,c7b08b,a08662,796755,5a4e44,423934".split(
|
||||||
|
","
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
"Zughy 32": {
|
||||||
|
colors: "472d3c,5e3643,7a444a,a05b53,bf7958,eea160,f4cca1,b6d53c,71aa34,397b44,3c5956,302c2e,5a5353,7d7071,a0938e,cfc6b8,dff6f5,8aebf1,28ccdf,3978a8,394778,39314b,564064,8e478c,cd6093,ffaeb6,f4b41b,f47e1b,e6482e,a93b3b,827094,4f546b".split(
|
||||||
|
","
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
Journey: {
|
||||||
|
colors: "050914,110524,3b063a,691749,9c3247,d46453,f5a15d,ffcf8e,ff7a7d,ff417d,d61a88,94007a,42004e,220029,100726,25082c,3d1132,73263d,bd4035,ed7b39,ffb84a,fff540,c6d831,77b02a,429058,2c645e,153c4a,052137,0e0421,0c0b42,032769,144491,488bd4,78d7ff,b0fff1,faffff,c7d4e1,928fb8,5b537d,392946,24142c,0e0f2c,132243,1a466b,10908e,28c074,3dff6e,f8ffb8,f0c297,cf968c,8f5765,52294b,0f022e,35003b,64004c,9b0e3e,d41e3c,ed4c40,ff9757,d4662f,9c341a,691b22,450c28,2d002e".split(
|
||||||
|
","
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
Vinik24: {
|
||||||
|
colors: "000000,6f6776,9a9a97,c5ccb8,8b5580,c38890,a593a5,666092,9a4f50,c28d75,7ca1c0,416aa3,8d6268,be955c,68aca9,387080,6e6962,93a167,6eaa78,557064,9d9f7f,7e9e99,5d6872,433455".split(
|
||||||
|
","
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
"Sweetie 16": {
|
||||||
|
colors: "1a1c2c,5d275d,b13e53,ef7d57,ffcd75,a7f070,38b764,257179,29366f,3b5dc9,41a6f6,73eff7,f4f4f4,94b0c2,566c86,333c57".split(
|
||||||
|
","
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
Lospec500: {
|
||||||
|
colors: "10121c,2c1e31,6b2643,ac2847,ec273f,94493a,de5d3a,e98537,f3a833,4d3533,6e4c30,a26d3f,ce9248,dab163,e8d282,f7f3b7,1e4044,006554,26854c,5ab552,9de64e,008b8b,62a477,a6cb96,d3eed3,3e3b65,3859b3,3388de,36c5f4,6dead6,5e5b8c,8c78a5,b0a7b8,deceed,9a4d76,c878af,cc99ff,fa6e79,ffa2ac,ffd1d5,f6e8e0,ffffff".split(
|
||||||
|
","
|
||||||
|
),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
palettes["Commodore 64"] = {"name":"Commodore 64","author":"","colors":["000000","626262","898989","adadad","ffffff","9f4e44","cb7e75","6d5412","a1683c","c9d487","9ae29b","5cab5e","6abfc6","887ecb","50459b","a057a3"]};
|
||||||
|
palettes["PICO-8"] = {"name":"PICO-8","author":"","colors":["000000","1D2B53","7E2553","008751","AB5236","5F574F","C2C3C7","FFF1E8","FF004D","FFA300","FFEC27","00E436","29ADFF","83769C","FF77A8","FFCCAA"]};
|
||||||
|
palettes["Gameboy Color"] = {"name":"Nintendo Gameboy (Black Zero)","author":"","colors":["2e463d","385d49","577b46","7e8416"]};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//populate palettes list in new pixel menu
|
//populate palettes list in new pixel menu
|
||||||
(() => {
|
(() => {
|
||||||
const palettesMenu = document.getElementById('palette-menu');
|
const palettesMenu = document.getElementById('palette-menu');
|
||||||
@ -9,43 +65,50 @@
|
|||||||
const loadPaletteButton = document.getElementById('load-palette-button');
|
const loadPaletteButton = document.getElementById('load-palette-button');
|
||||||
const loadPaletteButtonSplash = document.getElementById('load-palette-button-splash');
|
const loadPaletteButtonSplash = document.getElementById('load-palette-button-splash');
|
||||||
|
|
||||||
Object.keys(palettes).forEach((paletteName,) => {
|
splashPalettes.refresh = function () {
|
||||||
|
splashPalettes.innerHTML = '';
|
||||||
|
palettesMenu.innerHTML = '';
|
||||||
|
|
||||||
const button = document.createElement('button');
|
Object.keys(palettes).forEach((paletteName,) => {
|
||||||
button.appendChild(document.createTextNode(paletteName));
|
|
||||||
|
|
||||||
//if the palette was specified by the user, change the dropdown to it
|
const button = document.createElement('button');
|
||||||
if (palettes[paletteName].specified) {
|
button.appendChild(document.createTextNode(paletteName));
|
||||||
Util.setText('palette-button', paletteName);
|
|
||||||
Util.setText('palette-button-splash', paletteName)
|
|
||||||
//Show empty palette option
|
|
||||||
noPaletteButton.style.display = 'block';
|
|
||||||
}
|
|
||||||
|
|
||||||
const buttonEvent = () => {
|
//if the palette was specified by the user, change the dropdown to it
|
||||||
//hide the dropdown menu
|
if (palettes[paletteName].specified) {
|
||||||
Util.deselect('palette-menu');
|
Util.setText('palette-button', paletteName);
|
||||||
Util.deselect('palette-button');
|
Util.setText('palette-button-splash', paletteName)
|
||||||
Util.deselect('palette-menu-splash');
|
//Show empty palette option
|
||||||
Util.deselect('palette-button-splash');
|
noPaletteButton.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
//show empty palette option
|
const buttonEvent = () => {
|
||||||
noPaletteButton.style.display = 'block';
|
//hide the dropdown menu
|
||||||
|
Util.deselect('palette-menu');
|
||||||
|
Util.deselect('palette-button');
|
||||||
|
Util.deselect('palette-menu-splash');
|
||||||
|
Util.deselect('palette-button-splash');
|
||||||
|
|
||||||
//set the text of the dropdown to the newly selected preset
|
//show empty palette option
|
||||||
Util.setText('palette-button', paletteName);
|
noPaletteButton.style.display = 'block';
|
||||||
Util.setText('palette-button-splash', paletteName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Making a copy for the splash page too
|
//set the text of the dropdown to the newly selected preset
|
||||||
const copyButton = button.cloneNode(true);
|
Util.setText('palette-button', paletteName);
|
||||||
copyButton.addEventListener('click', buttonEvent);
|
Util.setText('palette-button-splash', paletteName);
|
||||||
button.addEventListener('click', buttonEvent);
|
}
|
||||||
|
|
||||||
// Appending it to the splash palette menu
|
// Making a copy for the splash page too
|
||||||
splashPalettes.appendChild(copyButton);
|
const copyButton = button.cloneNode(true);
|
||||||
palettesMenu.appendChild(button);
|
copyButton.addEventListener('click', buttonEvent);
|
||||||
});
|
button.addEventListener('click', buttonEvent);
|
||||||
|
|
||||||
|
// Appending it to the splash palette menu
|
||||||
|
splashPalettes.appendChild(copyButton);
|
||||||
|
palettesMenu.appendChild(button);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
splashPalettes.refresh();
|
||||||
|
|
||||||
|
|
||||||
const loadPaletteButtonEvent = () => {
|
const loadPaletteButtonEvent = () => {
|
||||||
|
@ -18,6 +18,6 @@ let coverImage = document.getElementById('editor-logo');
|
|||||||
let authorLink = coverImage.getElementsByTagName('a')[0];
|
let authorLink = coverImage.getElementsByTagName('a')[0];
|
||||||
let chosenImage = images[Math.round(Math.random() * (images.length - 1))];
|
let chosenImage = images[Math.round(Math.random() * (images.length - 1))];
|
||||||
|
|
||||||
coverImage.style.backgroundImage = 'url("/pixel-editor/' + chosenImage.path + '.png")';
|
coverImage.style.backgroundImage = 'url("' + chosenImage.path + '.png")';
|
||||||
authorLink.setAttribute('href', chosenImage.link);
|
authorLink.setAttribute('href', chosenImage.link);
|
||||||
authorLink.innerHTML = 'Art by ' + chosenImage.author;
|
authorLink.innerHTML = 'Art by ' + chosenImage.author;
|
@ -3,7 +3,7 @@ var canvasSize;
|
|||||||
var zoom = 7;
|
var zoom = 7;
|
||||||
var dragging = false;
|
var dragging = false;
|
||||||
var lastMouseClickPos = [0,0];
|
var lastMouseClickPos = [0,0];
|
||||||
var dialogueOpen = false;
|
var dialogueOpen = true;
|
||||||
var documentCreated = false;
|
var documentCreated = false;
|
||||||
var pixelEditorMode = "Advanced";
|
var pixelEditorMode = "Advanced";
|
||||||
|
|
||||||
|
15
js/checkCompatibilityPixelEditor.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
function closeCompatibilityWarning() {
|
||||||
|
document.getElementById("compatibility-warning").style.visibility = "hidden";
|
||||||
|
}
|
||||||
|
|
||||||
|
//check browser/version
|
||||||
|
if (
|
||||||
|
(bowser.firefox && bowser.version >= 28) ||
|
||||||
|
(bowser.chrome && bowser.version >= 29) ||
|
||||||
|
(!bowser.mobile && !bowser.tablet)
|
||||||
|
)
|
||||||
|
console.log("compatibility check passed");
|
||||||
|
|
||||||
|
|
||||||
|
//show warning
|
||||||
|
else document.getElementById("compatibility-warning").style.visibility = "visible";
|
@ -1,18 +1,18 @@
|
|||||||
/**utilities**/
|
/**utilities**/
|
||||||
//=include utilities/on.js
|
//=include util/on.js
|
||||||
//=include utilities/onChildren.js
|
//=include util/onChildren.js
|
||||||
//=include utilities/onClick.js
|
//=include util/onClick.js
|
||||||
//=include utilities/onClickChildren.js
|
//=include util/onClickChildren.js
|
||||||
//=include utilities/select.js
|
//=include util/select.js
|
||||||
//=include utilities/getSetText.js
|
//=include util/getSetText.js
|
||||||
//=include utilities/getSetValue.js
|
//=include util/getSetValue.js
|
||||||
//=include utilities/hexToRgb.js
|
//=include util/hexToRgb.js
|
||||||
//=include utilities/rgbToHex.js
|
//=include util/rgbToHex.js
|
||||||
//=include utilities/rgbToHsl.js
|
//=include util/rgbToHsl.js
|
||||||
//=include utilities/hslToRgb.js
|
//=include util/hslToRgb.js
|
||||||
//=include libraries/cookies.js
|
//=include lib/cookies.js
|
||||||
//=include _pixelEditorUtility.js
|
//=include _pixelEditorUtility.js
|
||||||
//=include sortable.js
|
//=include lib/sortable.js
|
||||||
//=include _algorithms.js
|
//=include _algorithms.js
|
||||||
//=include Util.js
|
//=include Util.js
|
||||||
|
|
||||||
@ -36,7 +36,7 @@
|
|||||||
//=include _colorChanged.js
|
//=include _colorChanged.js
|
||||||
//=include _initColor.js
|
//=include _initColor.js
|
||||||
//=include _dialogue.js
|
//=include _dialogue.js
|
||||||
//=include _featuresLog.js
|
//!=include _featuresLog.js
|
||||||
//=include _drawLine.js
|
//=include _drawLine.js
|
||||||
//=include _getCursorPosition.js
|
//=include _getCursorPosition.js
|
||||||
//=include _fill.js
|
//=include _fill.js
|
||||||
@ -53,7 +53,6 @@
|
|||||||
//=include _colorPicker.js
|
//=include _colorPicker.js
|
||||||
//=include _paletteBlock.js
|
//=include _paletteBlock.js
|
||||||
//=include _splashPage.js
|
//=include _splashPage.js
|
||||||
//=include _logs.js
|
|
||||||
|
|
||||||
/**load file**/
|
/**load file**/
|
||||||
//=include _loadImage.js
|
//=include _loadImage.js
|
||||||
|
79
js/util/ajax.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//GET: ajax(String url, Function success [,timeout])
|
||||||
|
//POST: ajax(String url, Object postData, Function success [,timeout])
|
||||||
|
Util.ajax = function (url, arg2, arg3, arg4) {
|
||||||
|
if (typeof arg2 == 'function') {
|
||||||
|
var success = arg2;
|
||||||
|
var timeout = arg3 || 10000;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var postData = arg2;
|
||||||
|
var success = arg3;
|
||||||
|
var timeout = arg4 || 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
var start = new Date();
|
||||||
|
console.log('AJAX - STARTING REQUEST', url, '(' + timeout + ')');
|
||||||
|
|
||||||
|
//start new request
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
//try to parse as json
|
||||||
|
try {
|
||||||
|
result = JSON.parse(this.response);
|
||||||
|
console.log('AJAX - COMPLETE ('+(new Date()-start)+'ms) - json:', result);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
result = this.response;
|
||||||
|
console.log('AJAX - COMPLETE ('+(new Date()-start)+'ms) - string:', this.response, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//return result
|
||||||
|
success(result);
|
||||||
|
|
||||||
|
xhr = null;
|
||||||
|
}
|
||||||
|
else if (this.readyState == 4) {
|
||||||
|
console.log('ajax failed', this.readyState, this.status);
|
||||||
|
success({ error: 'failure' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.ontimeout = function(e) {
|
||||||
|
console.log('ajax request timed out')
|
||||||
|
success({ error: 'timeout' });
|
||||||
|
};
|
||||||
|
|
||||||
|
if (postData) {
|
||||||
|
//post request
|
||||||
|
console.log('post data: ', postData instanceof FormData, postData);
|
||||||
|
|
||||||
|
//the the input isn't already formdata, convert it to form data
|
||||||
|
if (!(postData instanceof FormData)) {
|
||||||
|
console.log('converting to form data');
|
||||||
|
|
||||||
|
var formData = new FormData();
|
||||||
|
|
||||||
|
for (var key in postData) {
|
||||||
|
formData.append(key, postData[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
postData = formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
//send to server
|
||||||
|
xhr.open("POST", url, true);
|
||||||
|
xhr.timeout = timeout;
|
||||||
|
xhr.send(postData);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//get request
|
||||||
|
xhr.open("GET", url, true);
|
||||||
|
xhr.timeout = timeout;
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
return xhr;
|
||||||
|
}
|
11
package-lock.json
generated
@ -3135,8 +3135,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlebars-helper-svg": {
|
"handlebars-helper-svg": {
|
||||||
"version": "git+ssh://git@bitbucket.org/skeddles/npm-handlebars-helper-svg-lospec-open-source.git#2feeec5000aecce96ba2f714ec540880537ae208",
|
"version": "2.0.2",
|
||||||
"from": "handlebars-helper-svg@git+https://bitbucket.org/skeddles/npm-handlebars-helper-svg-lospec-open-source.git",
|
"resolved": "https://registry.npmjs.org/handlebars-helper-svg/-/handlebars-helper-svg-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-uCLLeD3F+6pcTczOz2DH6OtFkJ2lKixWUT0nrZimME36BdCwHheAwL5tfyYpsUUUB/yle/ZRK0/Cv7Def/d5XA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ltx": "^2.3.0",
|
"ltx": "^2.3.0",
|
||||||
"resolve": "^1.1.7"
|
"resolve": "^1.1.7"
|
||||||
@ -3855,9 +3856,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ltx": {
|
"ltx": {
|
||||||
"version": "2.9.2",
|
"version": "2.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/ltx/-/ltx-2.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/ltx/-/ltx-2.10.0.tgz",
|
||||||
"integrity": "sha512-llB7HflFhlfsYYT1SAe80elCBO5C20ryLdwPB/A/BZk38hhVeZztDlWQ9uTyvKNPX4aK6sA+JfS1f/mfzp5cxA==",
|
"integrity": "sha512-RB4zR6Mrp/0wTNS9WxMvpgfht/7u/8QAC9DpPD19opL/4OASPa28uoliFqeDkLUU8pQ4aeAfATBZmz1aSAHkMw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "^2.0.4"
|
"inherits": "^2.0.4"
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
"gulp-include": "^2.3.1",
|
"gulp-include": "^2.3.1",
|
||||||
"gulp-rename": "^2.0.0",
|
"gulp-rename": "^2.0.0",
|
||||||
"gulp-sass": "^4.0.2",
|
"gulp-sass": "^4.0.2",
|
||||||
"handlebars-helper-svg": "git+https://bitbucket.org/skeddles/npm-handlebars-helper-svg-lospec-open-source.git",
|
"handlebars-helper-svg": "^2.0.2",
|
||||||
"nodemon": "^2.0.7",
|
"nodemon": "^2.0.7",
|
||||||
"open": "^8.0.6",
|
"open": "^8.0.6",
|
||||||
"open-cli": "^6.0.1",
|
"open-cli": "^6.0.1",
|
||||||
|
47
server.js
@ -6,30 +6,10 @@ const app = express();
|
|||||||
const BUILDDIR = process.argv[2] || './build';
|
const BUILDDIR = process.argv[2] || './build';
|
||||||
const PORT = process.argv[3] || 3000;
|
const PORT = process.argv[3] || 3000;
|
||||||
|
|
||||||
//ROUTE - index.htm
|
|
||||||
app.get('/', (req, res) => {
|
|
||||||
res.sendFile(path.join(__dirname, BUILDDIR, 'index.htm'), {}, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log('error sending file', err);
|
|
||||||
} else {
|
|
||||||
console.log("Server: Successfully served index.html");
|
|
||||||
|
|
||||||
/*setTimeout(()=>{
|
|
||||||
console.log('closing server');
|
|
||||||
res.app.server.close();
|
|
||||||
process.exit();
|
|
||||||
},1000*10); */
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Better to show landing page rather than 404 on editor page reload
|
|
||||||
app.get('/pixel-editor/app', (req, res) => {
|
|
||||||
res.redirect('/');
|
|
||||||
})
|
|
||||||
|
|
||||||
//ROUTE - other files
|
//ROUTE - other files
|
||||||
app.use(express.static(path.join(__dirname, BUILDDIR)));
|
app.use('/pixel-editor', express.static(path.join(__dirname, BUILDDIR)));
|
||||||
|
|
||||||
|
|
||||||
// "reload" module allows us to trigger webpage reload automatically on file changes, but inside pixel editor it also
|
// "reload" module allows us to trigger webpage reload automatically on file changes, but inside pixel editor it also
|
||||||
// makes browser steal focus from any other window in order to ask user about unsaved changes. It might be quite
|
// makes browser steal focus from any other window in order to ask user about unsaved changes. It might be quite
|
||||||
@ -46,3 +26,26 @@ if (process.env.RELOAD === "yes") {
|
|||||||
console.log(`Web server listening on port ${PORT}`);
|
console.log(`Web server listening on port ${PORT}`);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Better to show landing page rather than 404 on editor page reload
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
res.redirect('/pixel-editor');
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
//ROUTE - match / or any route with just numbers letters and dashes, and return index.htm (all other routes should have been handled already)
|
||||||
|
app.get(['/pixel-editor', /^\/pixel-editor\/[\/a-z0-9-]+$/gi ], (req, res) => {
|
||||||
|
res.sendFile(path.join(__dirname, BUILDDIR, 'index.htm'), {}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.log('error sending file', err);
|
||||||
|
} else {
|
||||||
|
console.log("Server: Successfully served index.html", req.originalUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Better to show landing page rather than 404 on editor page reload
|
||||||
|
app.get('/pixel-editor/app', (req, res) => {
|
||||||
|
res.redirect('/');
|
||||||
|
})
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 793 B After Width: | Height: | Size: 793 B |
Before Width: | Height: | Size: 782 B After Width: | Height: | Size: 782 B |
Before Width: | Height: | Size: 771 B After Width: | Height: | Size: 771 B |
Before Width: | Height: | Size: 831 B After Width: | Height: | Size: 831 B |
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
Before Width: | Height: | Size: 837 B After Width: | Height: | Size: 837 B |
Before Width: | Height: | Size: 796 B After Width: | Height: | Size: 796 B |
Before Width: | Height: | Size: 809 B After Width: | Height: | Size: 809 B |
Before Width: | Height: | Size: 798 B After Width: | Height: | Size: 798 B |
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 325 B After Width: | Height: | Size: 325 B |
Before Width: | Height: | Size: 439 B After Width: | Height: | Size: 439 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 528 B After Width: | Height: | Size: 528 B |
@ -1,41 +1,41 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M497,51H15C6.716,51,0,57.716,0,66v380c0,8.284,6.716,15,15,15h482c8.284,0,15-6.716,15-15V66
|
<path d="M497,51H15C6.716,51,0,57.716,0,66v380c0,8.284,6.716,15,15,15h482c8.284,0,15-6.716,15-15V66
|
||||||
C512,57.716,505.284,51,497,51z"/>
|
C512,57.716,505.284,51,497,51z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 695 B After Width: | Height: | Size: 654 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -1,41 +1,41 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve">
|
viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve">
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M506.143,5.859c-7.811-7.811-20.475-7.811-28.285,0l-472,472c-7.811,7.811-7.811,20.474,0,28.284
|
<path d="M506.143,5.859c-7.811-7.811-20.475-7.811-28.285,0l-472,472c-7.811,7.811-7.811,20.474,0,28.284
|
||||||
c3.905,3.906,9.024,5.858,14.142,5.858s10.237-1.953,14.143-5.858l472-472C513.954,26.333,513.954,13.67,506.143,5.859z"/>
|
c3.905,3.906,9.024,5.858,14.142,5.858s10.237-1.953,14.143-5.858l472-472C513.954,26.333,513.954,13.67,506.143,5.859z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 799 B After Width: | Height: | Size: 758 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 222 B After Width: | Height: | Size: 222 B |
Before Width: | Height: | Size: 815 B After Width: | Height: | Size: 815 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 726 B After Width: | Height: | Size: 726 B |
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 327 B After Width: | Height: | Size: 327 B |
@ -1,41 +1,41 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M497,51H15C6.716,51,0,57.716,0,66v380c0,8.284,6.716,15,15,15h482c8.284,0,15-6.716,15-15V66
|
<path d="M497,51H15C6.716,51,0,57.716,0,66v380c0,8.284,6.716,15,15,15h482c8.284,0,15-6.716,15-15V66
|
||||||
C512,57.716,505.284,51,497,51z M482,431H30V81h452V431z"/>
|
C512,57.716,505.284,51,497,51z M482,431H30V81h452V431z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 678 B |
@ -1,108 +1,108 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M160.003,21.333h-42.667c-5.888,0-10.667,4.779-10.667,10.667s4.779,10.667,10.667,10.667h42.667
|
<path d="M160.003,21.333h-42.667c-5.888,0-10.667,4.779-10.667,10.667s4.779,10.667,10.667,10.667h42.667
|
||||||
c5.909,0,10.667-4.779,10.667-10.667S165.913,21.333,160.003,21.333z"/>
|
c5.909,0,10.667-4.779,10.667-10.667S165.913,21.333,160.003,21.333z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M288.003,21.333h-42.667c-5.888,0-10.667,4.779-10.667,10.667s4.779,10.667,10.667,10.667h42.667
|
<path d="M288.003,21.333h-42.667c-5.888,0-10.667,4.779-10.667,10.667s4.779,10.667,10.667,10.667h42.667
|
||||||
c5.909,0,10.667-4.779,10.667-10.667S293.913,21.333,288.003,21.333z"/>
|
c5.909,0,10.667-4.779,10.667-10.667S293.913,21.333,288.003,21.333z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M160.003,352h-42.667c-5.888,0-10.667,4.779-10.667,10.667s4.779,10.667,10.667,10.667h42.667
|
<path d="M160.003,352h-42.667c-5.888,0-10.667,4.779-10.667,10.667s4.779,10.667,10.667,10.667h42.667
|
||||||
c5.909,0,10.667-4.779,10.667-10.667S165.913,352,160.003,352z"/>
|
c5.909,0,10.667-4.779,10.667-10.667S165.913,352,160.003,352z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M288.003,352h-42.667c-5.888,0-10.667,4.779-10.667,10.667s4.779,10.667,10.667,10.667h42.667
|
<path d="M288.003,352h-42.667c-5.888,0-10.667,4.779-10.667,10.667s4.779,10.667,10.667,10.667h42.667
|
||||||
c5.888,0,10.667-4.779,10.667-10.667S293.913,352,288.003,352z"/>
|
c5.888,0,10.667-4.779,10.667-10.667S293.913,352,288.003,352z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M32.003,234.667c-5.909,0-10.667,4.779-10.667,10.667V288c0,5.888,4.779,10.667,10.667,10.667S42.67,293.888,42.67,288
|
<path d="M32.003,234.667c-5.909,0-10.667,4.779-10.667,10.667V288c0,5.888,4.779,10.667,10.667,10.667S42.67,293.888,42.67,288
|
||||||
v-42.667C42.67,239.445,37.913,234.667,32.003,234.667z"/>
|
v-42.667C42.67,239.445,37.913,234.667,32.003,234.667z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M32.003,106.667c-5.909,0-10.667,4.779-10.667,10.667V160c0,5.888,4.779,10.667,10.667,10.667
|
<path d="M32.003,106.667c-5.909,0-10.667,4.779-10.667,10.667V160c0,5.888,4.779,10.667,10.667,10.667
|
||||||
c5.909,0,10.667-4.779,10.667-10.667v-42.667C42.67,111.445,37.913,106.667,32.003,106.667z"/>
|
c5.909,0,10.667-4.779,10.667-10.667v-42.667C42.67,111.445,37.913,106.667,32.003,106.667z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M373.337,234.667c-5.888,0-10.667,4.779-10.667,10.667V288c0,5.888,4.779,10.667,10.667,10.667
|
<path d="M373.337,234.667c-5.888,0-10.667,4.779-10.667,10.667V288c0,5.888,4.779,10.667,10.667,10.667
|
||||||
c5.888,0,10.667-4.779,10.667-10.667v-42.667C384.003,239.445,379.246,234.667,373.337,234.667z"/>
|
c5.888,0,10.667-4.779,10.667-10.667v-42.667C384.003,239.445,379.246,234.667,373.337,234.667z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M373.337,106.667c-5.909,0-10.667,4.779-10.667,10.667V160c0,5.888,4.779,10.667,10.667,10.667
|
<path d="M373.337,106.667c-5.909,0-10.667,4.779-10.667,10.667V160c0,5.888,4.779,10.667,10.667,10.667
|
||||||
c5.888,0,10.667-4.779,10.667-10.667v-42.667C384.003,111.445,379.246,106.667,373.337,106.667z"/>
|
c5.888,0,10.667-4.779,10.667-10.667v-42.667C384.003,111.445,379.246,106.667,373.337,106.667z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M394.67,0h-42.667c-5.888,0-10.667,4.779-10.667,10.667v42.667c0,5.888,4.779,10.667,10.667,10.667h42.667
|
<path d="M394.67,0h-42.667c-5.888,0-10.667,4.779-10.667,10.667v42.667c0,5.888,4.779,10.667,10.667,10.667h42.667
|
||||||
c5.909,0,10.667-4.779,10.667-10.667V10.667C405.337,4.779,400.579,0,394.67,0z"/>
|
c5.909,0,10.667-4.779,10.667-10.667V10.667C405.337,4.779,400.579,0,394.67,0z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M53.337,0H10.67C4.782,0,0.003,4.779,0.003,10.667v42.667C0.003,59.221,4.782,64,10.67,64h42.667
|
<path d="M53.337,0H10.67C4.782,0,0.003,4.779,0.003,10.667v42.667C0.003,59.221,4.782,64,10.67,64h42.667
|
||||||
c5.909,0,10.667-4.779,10.667-10.667V10.667C64.003,4.779,59.246,0,53.337,0z"/>
|
c5.909,0,10.667-4.779,10.667-10.667V10.667C64.003,4.779,59.246,0,53.337,0z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M53.337,330.667H10.67c-5.888,0-10.667,4.779-10.667,10.667V384c0,5.888,4.779,10.667,10.667,10.667h42.667
|
<path d="M53.337,330.667H10.67c-5.888,0-10.667,4.779-10.667,10.667V384c0,5.888,4.779,10.667,10.667,10.667h42.667
|
||||||
c5.909,0,10.667-4.779,10.667-10.667v-42.667C64.003,335.445,59.246,330.667,53.337,330.667z"/>
|
c5.909,0,10.667-4.779,10.667-10.667v-42.667C64.003,335.445,59.246,330.667,53.337,330.667z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M506.521,385.344l-192-106.667c-3.968-2.197-8.875-1.664-12.224,1.323c-3.392,2.987-4.544,7.765-2.859,11.968
|
<path d="M506.521,385.344l-192-106.667c-3.968-2.197-8.875-1.664-12.224,1.323c-3.392,2.987-4.544,7.765-2.859,11.968
|
||||||
l85.333,213.333c1.6,4.011,5.461,6.656,9.771,6.699c0.043,0,0.085,0,0.128,0c4.267,0,8.128-2.539,9.813-6.464l30.315-70.741
|
l85.333,213.333c1.6,4.011,5.461,6.656,9.771,6.699c0.043,0,0.085,0,0.128,0c4.267,0,8.128-2.539,9.813-6.464l30.315-70.741
|
||||||
l70.741-30.315c3.733-1.6,6.229-5.205,6.443-9.259C512.195,391.168,510.062,387.328,506.521,385.344z"/>
|
l70.741-30.315c3.733-1.6,6.229-5.205,6.443-9.259C512.195,391.168,510.062,387.328,506.521,385.344z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 648 B After Width: | Height: | Size: 648 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 875 B After Width: | Height: | Size: 875 B |
@ -1,3 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="13.9" height="12.4" viewBox="0 0 13.9 12.4">
|
<svg xmlns="http://www.w3.org/2000/svg" width="13.9" height="12.4" viewBox="0 0 13.9 12.4">
|
||||||
<path d="M13.9,10.8,8,1A1.4,1.4,0,0,0,6,1L.1,10.7c-.3.6,1.1,2.3,1.6,2.3H12.3C12.9,13,14.2,11.3,13.9,10.8ZM8,12H6V10H8ZM8,9H6V4H8Z" transform="translate(-0.1 -0.6)" style="fill-rule: evenodd"/>
|
<path d="M13.9,10.8,8,1A1.4,1.4,0,0,0,6,1L.1,10.7c-.3.6,1.1,2.3,1.6,2.3H12.3C12.9,13,14.2,11.3,13.9,10.8ZM8,12H6V10H8ZM8,9H6V4H8Z" transform="translate(-0.1 -0.6)" style="fill-rule: evenodd"/>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 298 B After Width: | Height: | Size: 295 B |
Before Width: | Height: | Size: 389 B After Width: | Height: | Size: 389 B |
Before Width: | Height: | Size: 710 B After Width: | Height: | Size: 710 B |
10
views/about-popup.hbs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<div id="about">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
<h1>About Lospec Pixel Editor</h1>
|
||||||
|
<div>version 1.1.0</div>
|
||||||
|
<p>This is a web-based tool for creating and editing pixel art.</p>
|
||||||
|
<p>The goal of this tool is to be an accessible and intuitive tool that's simple enough for a first time pixel artist while still being usable enough for a veteran. </p>
|
||||||
|
<p>In the future I hope to add enough features to become a full fledged pixel art editor, with everything an artist could need.</p>
|
||||||
|
<h1>About Lospec</h1>
|
||||||
|
<p>Lospec is a website created to host tools for pixel artists. To see more of our tools, visit our <a href="/">homepage</a>. To hear about any updates or new tools, follow us on <a href="http://twitter.com/lospecofficial">Twitter</a>.</p>
|
||||||
|
</div>
|
59
views/canvas-resize-popup.hbs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<!--CANVAS RESIZE-->
|
||||||
|
<div class="update" id = "resize-canvas">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
<h1>Resize canvas</h1>
|
||||||
|
|
||||||
|
<!--PIVOTS-->
|
||||||
|
<span id = "pivot-menu">
|
||||||
|
<button class="pivot-button" value="topleft">{{svg "arrows/topleft.svg" width="20" height="20"}}</button>
|
||||||
|
<button class="pivot-button" value="top">{{svg "arrows/top.svg" width="20" height="20"}}</button>
|
||||||
|
<button class="pivot-button" value="topright">{{svg "arrows/topright.svg" width="20" height="20"}}</button>
|
||||||
|
<button class="pivot-button" value="left">{{svg "arrows/left.svg" width="20" height="20"}}</button>
|
||||||
|
<button class="pivot-button rc-selected-pivot" value="middle">{{svg "arrows/middle.svg" width="20" height="20"}}</button>
|
||||||
|
<button class="pivot-button" value="right">{{svg "arrows/right.svg" width="20" height="20"}}</button>
|
||||||
|
<button class="pivot-button" value="bottomleft">{{svg "arrows/bottomleft.svg" width="20" height="20"}}</button>
|
||||||
|
<button class="pivot-button" value="bottom">{{svg "arrows/bottom.svg" width="20" height="20"}}</button>
|
||||||
|
<button class="pivot-button" value="bottomright">{{svg "arrows/bottomright.svg" width="20" height="20"}}</button>
|
||||||
|
</span>
|
||||||
|
<!-- SIZE-->
|
||||||
|
<span id = "rc-size-menu">
|
||||||
|
<h2>Size</h2>
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
Width: <input id="rc-width" type="number" default="0" step="1"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Height: <input id="rc-height" default="0" step="1" type="number"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<!--BORDERS-->
|
||||||
|
<span id = "borders-menu">
|
||||||
|
<h2>Borders offsets</h2>
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
Left: <input id="rc-border-left" type="number" default="0" step="1"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Right: <input id="rc-border-right" type="number" default="0" step="1"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Top: <input id="rc-border-top" type="number" default="0" step="1"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Bottom: <input id="rc-border-bottom" default="0" step="1" type="number"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button id = "resize-canvas-confirm">Resize canvas</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
9
views/canvases.hbs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<!-- CANVASES -->
|
||||||
|
<div id="canvas-view">
|
||||||
|
<canvas id="vfx-canvas" class = "drawingCanvas"></canvas>
|
||||||
|
<canvas id = "tmp-canvas" class = "drawingCanvas"></canvas>
|
||||||
|
<canvas id="pixel-canvas" class = "drawingCanvas"></canvas>
|
||||||
|
<canvas id="checkerboard" class = "drawingCanvas"></canvas>
|
||||||
|
<canvas id="pixel-grid" class = "drawingCanvas"></canvas>
|
||||||
|
</div>
|
||||||
|
<div id="canvas-view-shadow"></div>
|
11
views/changelog-popup.hbs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<div id="changelog">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
|
||||||
|
<h1>Changelog</h1>
|
||||||
|
{{#each changelog}}
|
||||||
|
<h2>Version {{@key}}</h2>
|
||||||
|
<ul>{{#each this}}
|
||||||
|
<li>{{change}} <span class="weak">- {{author}}</span></li>
|
||||||
|
{{/each}}</ul>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
14
views/colors-menu.hbs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<ul id="colors-menu">
|
||||||
|
<li class="noshrink"><button title="Add Current Color To Palette" id="add-color-button">{{svg "./plus.svg" width="30" height="30"}}</button></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="jscolor-picker-bottom">
|
||||||
|
<span>#</span><input type="text" id="jscolor-hex-input" />
|
||||||
|
<div id="duplicate-color-warning" title="Color is a duplicate of another in palette">{{svg "warning.svg" width="14"
|
||||||
|
height="12" }}</div>
|
||||||
|
<button class="delete-color-button">{{svg "trash.svg" width="20" height="20" }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="color-edit-button">
|
||||||
|
{{svg "adjust.svg" width="20" height="20" }}
|
||||||
|
</div>
|
15
views/compatibility-warning.hbs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<div id="compatibility-warning">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<p><strong>Warning: a modern, desktop, web browser is required to use this tool.</strong></p>
|
||||||
|
<p>We detected that you may have an out of date or unsupported web browser. This tool, like many others on
|
||||||
|
this site and across the web uses features only available in new web browsers. We reccommend updating
|
||||||
|
your current browser or downloading <a href="https://www.mozilla.org/en-US/firefox/new/"
|
||||||
|
target="_blank">Firefox</a> or <a href="https://www.google.com/chrome/browser/desktop/index.html"
|
||||||
|
target="_blank">Chrome</a>. </p>
|
||||||
|
<button onclick="closeCompatibilityWarning()">Continue</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bowser@2.11.0/es5.min.js"></script>
|
||||||
|
<script src="/pixel-editor/checkCompatibilityPixelEditor.js"></script>
|
10
views/credits-popup.hbs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<div id="credits">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
<h1>Credits</h1>
|
||||||
|
<h2>Icons</h2>
|
||||||
|
<ul>
|
||||||
|
<li><div>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div></li>
|
||||||
|
<li><div>Font Awesome by Dave Gandy - <a href="http://fontawesome.io">http://fontawesome.io</a></div></li>
|
||||||
|
<li><div>Icons made by <a href="http://www.flaticon.com/authors/those-icons" title="Those Icons">Those Icons</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
0
views/data-asdfgasd.hbs
Normal file
44
views/help-popup.hbs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<div id="help">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
<h1>Help</h1>
|
||||||
|
<h2>Palette</h2>
|
||||||
|
<ul>
|
||||||
|
<li>Left Click - Choose Color</li>
|
||||||
|
<li>Right Click - Edit Color</li>
|
||||||
|
</ul>
|
||||||
|
<h2>Hotkeys</h2>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Pencil:</strong> <span class="keyboard-key">B</span> or <span class="keyboard-key">1</span></li>
|
||||||
|
<li><strong>Eraser:</strong> <span class="keyboard-key">R</span></li>
|
||||||
|
<li><strong>Rectangle:</strong> <span class="keyboard-key">U</span></li>
|
||||||
|
<li><strong>Line:</strong> <span class="keyboard-key">L</span></li>
|
||||||
|
<li><strong>Fill:</strong> <span class="keyboard-key">F</span> or <span class="keyboard-key">2</span></li>
|
||||||
|
<li><strong>Eyedropper:</strong> <span class="keyboard-key">E</span> or <span class="keyboard-key">3</span></li>
|
||||||
|
<li><strong>Pan:</strong> <span class="keyboard-key">P</span> or <span class="keyboard-key">M</span> or <span class="keyboard-key">4</span></li>
|
||||||
|
<li><strong>Zoom:</strong> <span class="keyboard-key">Z</span> or <span class="keyboard-key">5</span></li>
|
||||||
|
<li><strong>Undo:</strong> Ctrl + <span class="keyboard-key">Z</span></li>
|
||||||
|
<li><strong>Redo:</strong> Ctrl + <span class="keyboard-key">Y</span> or Ctrl + Alt + <span class="keyboard-key">Z</span></li>
|
||||||
|
<li><strong>Rectangular selection:</strong> <span class="keyboard-key">M</span></li>
|
||||||
|
</ul>
|
||||||
|
<h2>Mouse Shortcuts</h2>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Eyedropper: </strong>Alt + Click</li>
|
||||||
|
<li><strong>Pan: </strong>Space + Click</li>
|
||||||
|
<li><strong>Zoom: </strong>Alt + Scroll Wheel</li>
|
||||||
|
</ul>
|
||||||
|
<h2>Layers</h2>
|
||||||
|
<ul>
|
||||||
|
<li>{{svg "visible.svg" width="15" height="15" class = "default-icon"}}: show / hide layer</li>
|
||||||
|
<li>{{svg "lockedpadlock.svg" width="15" height="15" class = "default-icon"}}: lock / unlock layer, when a layer is locked it's not possible to draw on it</li>
|
||||||
|
<li>Right click on a layer to open the <strong>menu</strong>:
|
||||||
|
<ul>
|
||||||
|
<li><strong>Rename:</strong> change the name of the layer</li>
|
||||||
|
<li><strong>Duplicate:</strong> duplicate the layer</li>
|
||||||
|
<li><strong>Delete:</strong> delete the layer (doesn't work if there's only one layer)</li>
|
||||||
|
<li><strong>Merge below:</strong> merges the selected the layer with the one below it</li>
|
||||||
|
<li><strong>Flatten visible:</strong> merges all the visible layers</li>
|
||||||
|
<li></strong>Flatten all:</strong> merges all the layers</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
7
views/holders.hbs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<div id="data-holders">
|
||||||
|
<a id="save-image-link-holder" href="#">dl</a>
|
||||||
|
<a id="save-project-link-holder" href="#">dl</a>
|
||||||
|
<input id="open-image-browse-holder" type="file" accept="image/png, image/gif, .lpe" />
|
||||||
|
<input id="load-palette-browse-holder" type="file" accept="image/png, image/gif" />
|
||||||
|
<canvas id="load-palette-canvas-holder"></canvas>
|
||||||
|
</div>
|
656
views/index.hbs
@ -6,651 +6,39 @@
|
|||||||
<title>{{title}}</title>
|
<title>{{title}}</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,400i,700,900" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,400i,700,900" rel="stylesheet">
|
||||||
<link rel='stylesheet' href='pixel-editor.css' />
|
<link rel="stylesheet" href="/pixel-editor/pixel-editor.css" />
|
||||||
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
|
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
|
||||||
{{{google-analytics}}}
|
{{{google-analytics}}}
|
||||||
{{{favicons}}}
|
{{{favicons}}}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body oncontextmenu="return false;">
|
<body oncontextmenu="return false;">
|
||||||
<div id="compatibility-warning">
|
{{> compatibility-warning}}
|
||||||
<div><div>
|
{{> preload}}
|
||||||
<p><strong>Warning: a modern, desktop, web browser is required to use this tool.</strong></p>
|
|
||||||
<p>We detected that you may have an out of date or unsupported web browser. This tool, like many others on this site and across the web uses features only available in new web browsers. We reccommend updating your current browser or downloading <a href="https://www.mozilla.org/en-US/firefox/new/" target="_blank">Firefox</a> or <a href="https://www.google.com/chrome/browser/desktop/index.html" target="_blank">Chrome</a>. </p>
|
|
||||||
<button onclick="closeCompatibilityWarning()">Continue</button>
|
|
||||||
</div></div>
|
|
||||||
</div>
|
|
||||||
<script src="/javascripts/checkCompatibilityPixelEditor.js"></script>
|
|
||||||
|
|
||||||
<div class="preload">
|
{{> main-menu}}
|
||||||
<img src="dropdown-arrow.png" />
|
{{> tools-menu}}
|
||||||
<img src="dropdown-arrow-hover.png" />
|
{{> colors-menu}}
|
||||||
<img src="eyedropper.png" />
|
{{> layers-menu}}
|
||||||
<img src="fill.png" />
|
|
||||||
<img src="pan.png" />
|
|
||||||
<img src="pan-held.png" />
|
|
||||||
<img src="pencil.png" />
|
|
||||||
<img src="zoom-in.png" />
|
|
||||||
<img src = "eraser.png"/>
|
|
||||||
<img src = "rectselect.png"/>
|
|
||||||
<!-- TODO: [ELLIPSE] Where is this icon used? Do we need similar one for ellipsis? -->
|
|
||||||
<img src= "rectangle.png">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul id="main-menu">
|
|
||||||
<li class="logo">Lospec Pixel Editor</li>
|
|
||||||
<li>
|
|
||||||
<button>File</button>
|
|
||||||
<ul>
|
|
||||||
<li><button>New</button></li>
|
|
||||||
<li><button>Save project</button></li>
|
|
||||||
<li><button>Open</button></li>
|
|
||||||
<li><button id="export-button" class="disabled">Export</button></li>
|
|
||||||
<li><a href="/pixel-editor">Exit</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button>Edit</button>
|
|
||||||
<ul>
|
|
||||||
<li><button id="resize-canvas-button" onclick = "openResizeCanvasWindow()">Resize canvas</button></li>
|
|
||||||
<li><button id="resize-sprite-button" onclick = "openResizeSpriteWindow()">Scale sprite</button></li>
|
|
||||||
<li><button onclick = "trimCanvas()">Trim canvas</button></li>
|
|
||||||
<li><button id="undo-button" class="disabled">Undo</button></li>
|
|
||||||
<li><button id="redo-button" class="disabled">Redo</button></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button>View</button>
|
|
||||||
<ul>
|
|
||||||
<li><button id="toggle-pixelgrid-button" onclick="togglePixelGrid()">Show pixel grid</button></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button id = "layer-button">Layer</button>
|
|
||||||
<ul>
|
|
||||||
<li><button onclick = "addLayer()">New layer</button></li>
|
|
||||||
<li><button onclick = "duplicateLayer()">Duplicate</button></li>
|
|
||||||
<li><button onclick = "renameLayer()">Rename</button></li>
|
|
||||||
<li><button onclick = "deleteLayer()">Delete</button></li>
|
|
||||||
<li><button onclick = "merge()">Merge below</button></li>
|
|
||||||
<li><button onclick = "flatten(false)">Flatten all</button></li>
|
|
||||||
<li><button onclick = "flatten(true)">Flatten visible</button></li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button>Selection</button>
|
|
||||||
<ul>
|
|
||||||
<li><button id="copy-button">Copy</button></li>
|
|
||||||
<li><button id="cut-button">Cut</button></li>
|
|
||||||
<li><button id="paste-button">Paste</button></li>
|
|
||||||
<li><button id="cancelSelection-button">Cancel</button></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button>Editor</button>
|
|
||||||
<ul>
|
|
||||||
<li><button id="switch-mode-button">Switch to basic mode</button></li>
|
|
||||||
<li><button onclick="showDialogue('splash', false)">Splash page</button></li>
|
|
||||||
<li><button>Settings</button></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<button>Help</button>
|
|
||||||
<ul>
|
|
||||||
<li><button>Help</button></li>
|
|
||||||
<li><button>About</button></li>
|
|
||||||
<li><button>Changelog</button></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul id="tools-menu">
|
|
||||||
<li class="selected expanded">
|
|
||||||
<button title="Pencil Tool (B)" id="pencil-button">{{svg "pencil.svg" width="32" height="32"}}</button>
|
|
||||||
<button title="Increase Brush Size" id="pencil-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
|
||||||
<button title="Decrease Brush Size" id="pencil-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class = "expanded">
|
|
||||||
<button title="Eraser tool (R)" id="eraser-button">{{svg "eraser.svg" width="32" height="32"}}</button>
|
|
||||||
<button title="Increase Eraser Size" id="eraser-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
|
||||||
<button title="Decrease Eraser Size" id="eraser-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="expanded">
|
|
||||||
<button title="Rectangle Tool (U)" id="rectangle-button">{{svg "rectangle.svg" width="32" height="32" id = "rectangle-empty-button-svg"}}
|
|
||||||
{{svg "fullrect.svg" width="32" height="32" id = "rectangle-full-button-svg" display = "none"}}</button>
|
|
||||||
<button title="Increase Rectangle Size" id="rectangle-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
|
||||||
<button title="Decrease Rectangle Size" id="rectangle-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- TODO: [ELLIPSE] Once ellipse is ready for release make it visible by default -->
|
|
||||||
<li class="expanded" id="tools-menu--ellipse" style="display: none">
|
|
||||||
<!-- TODO: [ELLIPSE] Decide on a shortcut to use. "S" was chosen without any in-team consultation. -->
|
|
||||||
<!-- TODO: [ELLIPSE] Decide on icons to use. Current ones are quickly prepared drafts and display with incorrect color. -->
|
|
||||||
<button title="Ellipse Tool (S)" id="ellipse-button">
|
|
||||||
{{svg "ellipse.svg" width="32" height="32" id = "ellipse-empty-button-svg"}}
|
|
||||||
{{svg "filledellipse.svg" width="32" height="32" id = "ellipse-full-button-svg" display = "none"}}
|
|
||||||
</button>
|
|
||||||
<button title="Increase Ellipse Size" id="ellipse-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
|
||||||
<button title="Decrease Ellipse Size" id="ellipse-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="expanded">
|
|
||||||
<button title="Line Tool (L)" id="line-button">{{svg "line.svg" width="32" height="32"}}</button>
|
|
||||||
<button title="Increase Line Size" id="line-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
|
||||||
<button title="Decrease Line Size" id="line-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><button title="Fill Tool (F)" id="fill-button">{{svg "fill.svg" width="32" height="32"}}</button></li>
|
|
||||||
|
|
||||||
<li><button title="Eyedropper Tool (E)" id="eyedropper-button">{{svg "eyedropper.svg" width="32" height="32"}}</button></li>
|
|
||||||
|
|
||||||
<li><button title="Pan Tool (P)" id="pan-button">{{svg "pan.svg" width="32" height="32"}}</button></li>
|
|
||||||
|
|
||||||
<li><button title = "Rectangular Selection Tool (M)" id = "rectselect-button">{{svg "rectselect.svg" width = "32" height = "32"}}</button><li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul id="colors-menu">
|
|
||||||
<li class="noshrink"><button title="Add Current Color To Palette" id="add-color-button">{{svg "./plus.svg" width="30" height="30"}}</button></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<!-- LAYER MENU -->
|
|
||||||
<ul id = "layers-menu">
|
|
||||||
<li class = "layers-menu-entry selected-layer">
|
|
||||||
<canvas class = "preview-canvas"></canvas>
|
|
||||||
<ul class="layer-buttons">
|
|
||||||
<li class = "layer-button">
|
|
||||||
<button title="Lock layer" class="lock-layer-button">
|
|
||||||
{{svg "unlockedpadlock.svg" width="15" height="15" class = "default-icon"}}
|
|
||||||
{{svg "lockedpadlock.svg" width="15" height="15" class = "edited-icon" display = "none"}}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li class = "layer-button">
|
|
||||||
<button title="Show / hide layer" class="hide-layer-button">
|
|
||||||
{{svg "visible.svg" width="15" height="15" class = "default-icon"}}
|
|
||||||
{{svg "invisible.svg" width="15" height="15" class = "edited-icon" display = "none"}}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Layer 0<div class = "gradient"></div></p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<button id = "add-layer-button">
|
|
||||||
{{svg "plus.svg" width="20" height="20"}} Add layer
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul id = "layer-properties-menu">
|
|
||||||
<li>
|
|
||||||
<button onclick = "renameLayer()">Rename</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button onclick = "duplicateLayer()">Duplicate</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button onclick = "deleteLayer()">Delete</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button onclick = "merge()">Merge below</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button onclick = "flatten(true)">Flatten visible</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button onclick = "flatten(false)">Flatten all</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<!-- TOOL PREVIEWS -->
|
|
||||||
<div id="eyedropper-preview"></div>
|
|
||||||
<div id="brush-preview"></div>
|
|
||||||
|
|
||||||
<!-- CANVASES -->
|
|
||||||
<div id="canvas-view">
|
|
||||||
<canvas id="vfx-canvas" class = "drawingCanvas"></canvas>
|
|
||||||
<canvas id = "tmp-canvas" class = "drawingCanvas"></canvas>
|
|
||||||
<canvas id="pixel-canvas" class = "drawingCanvas"></canvas>
|
|
||||||
<canvas id="checkerboard" class = "drawingCanvas"></canvas>
|
|
||||||
<canvas id="pixel-grid" class = "drawingCanvas"></canvas>
|
|
||||||
</div>
|
|
||||||
<div id="canvas-view-shadow"></div>
|
|
||||||
|
|
||||||
<div id="data-holders">
|
|
||||||
<a id="save-image-link-holder" href="#">dl</a>
|
|
||||||
<a id="save-project-link-holder" href="#">dl</a>
|
|
||||||
<input id="open-image-browse-holder" type="file" accept="image/png, image/gif, .lpe"/>
|
|
||||||
<input id="load-palette-browse-holder" type="file" accept="image/png, image/gif"/>
|
|
||||||
<canvas id="load-palette-canvas-holder"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="jscolor-picker-bottom">
|
|
||||||
<span>#</span><input type="text" id="jscolor-hex-input"/>
|
|
||||||
<div id="duplicate-color-warning" title="Color is a duplicate of another in palette">{{svg "warning.svg" width="14" height="12" }}</div>
|
|
||||||
<button class="delete-color-button">{{svg "trash.svg" width="20" height="20" }}</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="color-edit-button">
|
|
||||||
{{svg "adjust.svg" width="20" height="20" }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
{{> tool-previews}}
|
||||||
|
{{> canvases}}
|
||||||
|
{{> holders}}
|
||||||
|
|
||||||
<div id="pop-up-container">
|
<div id="pop-up-container">
|
||||||
<!-- NEW PIXEL -->
|
{{> start-pixel-popup}}
|
||||||
<div id="new-pixel" class="update">
|
{{> splash-page-popup}}
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
{{> sprite-resize-popup}}
|
||||||
<h1>New Pixel</h1>
|
{{> canvas-resize-popup}}
|
||||||
|
{{> palette-popup}}
|
||||||
<!-- Editor mode-->
|
{{> help-popup}}
|
||||||
<h2>Editor mode</h2>
|
{{> about-popup}}
|
||||||
<button id = "editor-mode-button" class = "dropdown-button">Choose a mode...</button>
|
{{> changelog-popup}}
|
||||||
<div id = "editor-mode-menu" class = "dropdown-menu"></div>
|
{{> credits-popup}}
|
||||||
<input id="editor-mode" value="{{#if mode}}{{mode}}{{else}}'Advanced'{{/if}}" autocomplete="off" />
|
{{> settings-popup}}
|
||||||
<p id = "editor-mode-info"></p>
|
|
||||||
|
|
||||||
<!-- Preset-->
|
|
||||||
<h2>Preset</h2>
|
|
||||||
<button id="preset-button" class="dropdown-button">Choose a preset...</button>
|
|
||||||
<div id="preset-menu" class="dropdown-menu"></div>
|
|
||||||
|
|
||||||
<h2>Size</h2>
|
|
||||||
<input id="size-width" value="{{#if width}}{{width}}{{else}}64{{/if}}" autocomplete="off" />{{svg "x.svg" width="16" height="16" class="dimentions-x"}}<input id="size-height" value="{{#if height}}{{height}}{{else}}64{{/if}}" autocomplete="off" />
|
|
||||||
<h2>Palette</h2>
|
|
||||||
<button id="palette-button" class="dropdown-button">Choose a palette...</button>
|
|
||||||
<div id="palette-menu" class="dropdown-menu"><button id="no-palette-button">Empty Palette</button><button id="load-palette-button">Load palette...</button></div>
|
|
||||||
|
|
||||||
<div id="new-pixel-warning">Creating a new pixel will discard your current one.</div>
|
|
||||||
<div>
|
|
||||||
<button id="create-button" class="default">Create</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Splash page -->
|
|
||||||
<div id = "splash">
|
|
||||||
<div id="splash-news">
|
|
||||||
<div id="latest-update">
|
|
||||||
<h1>Latest updates</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="splash-input">
|
|
||||||
<div id="editor-logo">
|
|
||||||
<div id="black">
|
|
||||||
<div id="sp-coverdata">
|
|
||||||
<img src="https://lospec.com/brand/lospec_logo_3x.png"/> pixel editor
|
|
||||||
<p>Version 1.4.0</p>
|
|
||||||
<a href="https://cdn.discordapp.com/attachments/506277390050131978/795660870221955082/final.png">Art by Unsettled</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="splash-menu">
|
|
||||||
<div id="sp-newpixel">
|
|
||||||
<h1>New Custom Pixel</h1>
|
|
||||||
<!-- Editor mode-->
|
|
||||||
<h2>Editor mode</h2>
|
|
||||||
<div class="sp-np-entry" id="sp-mode-palette">
|
|
||||||
<div class="button-menu">
|
|
||||||
<div class="bm-left" onclick="splashMode(event,'Basic')"><p>Basic</p></div>
|
|
||||||
<div class="sp-interface-selected bm-right" onclick="splashMode(event,'Advanced')"><p>Advanced</p></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Size</h2>
|
|
||||||
<div class="sp-np-entry">
|
|
||||||
<input id="size-width-splash" value="{{#if width}}{{width}}{{else}}64{{/if}}" autocomplete="off" />{{svg "x.svg" width="16" height="16" class="dimentions-x"}}<input id="size-height-splash" value="{{#if height}}{{height}}{{else}}64{{/if}}" autocomplete="off" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Palette</h2>
|
|
||||||
<button id="palette-button-splash" class="dropdown-button">Choose a palette...</button>
|
|
||||||
<div id="palette-menu-splash" class="dropdown-menu"><button id="load-palette-button-splash">Load palette...</button></div>
|
|
||||||
|
|
||||||
<div id="new-pixel-warning">Creating a new pixel will discard your current one.</div>
|
|
||||||
<div class="sp-np-entry">
|
|
||||||
<button id="create-button-splash" class="default">Create</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id = "sp-quickstart-container">
|
|
||||||
<div id="sp-quickstart-title">
|
|
||||||
Quickstart
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="sp-quickstart">
|
|
||||||
<div class="sp-template" onclick="document.getElementById('open-image-browse-holder').click()"><p>Load</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('Gameboy Color')"><p><span>New</span> Gameboy</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('Commodore 64')"><p><span>New</span> C64</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('PICO-8')"><p><span>New</span> Pico8</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('',16,16)"><p><span>New</span> 16x16</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('',32,32)"><p><span>New</span> 32x32</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('',64,64)"><p><span>New</span> 64x64</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('',128,128)"><p><span>New</span> 128x128</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('',256,256)"><p><span>New</span> 256x256</p></div>
|
|
||||||
<div class="sp-template" onclick="newFromTemplate('',512,512)"><p><span>New</span> 512x512</p></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--SPRITE RESIZE-->
|
|
||||||
<div class="update" id = "resize-sprite">
|
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
|
||||||
<h1>Scale sprite</h1>
|
|
||||||
<!-- SIZE-->
|
|
||||||
<h2>New size</h2>
|
|
||||||
<span id = "rs-size-menu">
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
Width: <input id="rs-width" type="number" default="0" step="1"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
Height: <input id="rs-height" default="0" step="1" type="number"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
<!--BORDERS-->
|
|
||||||
<h2>Resize percentages</h2>
|
|
||||||
<span id = "rs-percentage-menu">
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
Width <input id="rs-width-percentage" type="number" default="0" step="1"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/> %
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
Height <input id="rs-height-percentage" type="number" default="0" step="1"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/> %
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div id = "rs-ratio-div">
|
|
||||||
<span>
|
|
||||||
Keep current ratio <input type = "checkbox" id = "rs-keep-ratio"/>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
Scaling algorithm:
|
|
||||||
<select name = "resize-algorithm" id = "resize-algorithm-combobox">
|
|
||||||
<option value = "nearest-neighbor">Nearest neighbour</option>
|
|
||||||
<option value = "bilinear-interpolation">Bilinear</option>
|
|
||||||
</select>
|
|
||||||
</span>
|
|
||||||
</br>
|
|
||||||
<button id = "resize-sprite-confirm">Scale sprite</button>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--CANVAS RESIZE-->
|
|
||||||
<div class="update" id = "resize-canvas">
|
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
|
||||||
<h1>Resize canvas</h1>
|
|
||||||
|
|
||||||
<!--PIVOTS-->
|
|
||||||
<span id = "pivot-menu">
|
|
||||||
<button class="pivot-button" value="topleft">{{svg "arrows/topleft.svg" width="20" height="20"}}</button>
|
|
||||||
<button class="pivot-button" value="top">{{svg "arrows/top.svg" width="20" height="20"}}</button>
|
|
||||||
<button class="pivot-button" value="topright">{{svg "arrows/topright.svg" width="20" height="20"}}</button>
|
|
||||||
<button class="pivot-button" value="left">{{svg "arrows/left.svg" width="20" height="20"}}</button>
|
|
||||||
<button class="pivot-button rc-selected-pivot" value="middle">{{svg "arrows/middle.svg" width="20" height="20"}}</button>
|
|
||||||
<button class="pivot-button" value="right">{{svg "arrows/right.svg" width="20" height="20"}}</button>
|
|
||||||
<button class="pivot-button" value="bottomleft">{{svg "arrows/bottomleft.svg" width="20" height="20"}}</button>
|
|
||||||
<button class="pivot-button" value="bottom">{{svg "arrows/bottom.svg" width="20" height="20"}}</button>
|
|
||||||
<button class="pivot-button" value="bottomright">{{svg "arrows/bottomright.svg" width="20" height="20"}}</button>
|
|
||||||
</span>
|
|
||||||
<!-- SIZE-->
|
|
||||||
<span id = "rc-size-menu">
|
|
||||||
<h2>Size</h2>
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
Width: <input id="rc-width" type="number" default="0" step="1"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
Height: <input id="rc-height" default="0" step="1" type="number"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
<!--BORDERS-->
|
|
||||||
<span id = "borders-menu">
|
|
||||||
<h2>Borders offsets</h2>
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
Left: <input id="rc-border-left" type="number" default="0" step="1"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
Right: <input id="rc-border-right" type="number" default="0" step="1"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
Top: <input id="rc-border-top" type="number" default="0" step="1"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
Bottom: <input id="rc-border-bottom" default="0" step="1" type="number"
|
|
||||||
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<button id = "resize-canvas-confirm">Resize canvas</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- PALETTE -->
|
|
||||||
<div id = "palette-block">
|
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
|
||||||
|
|
||||||
<h1>Edit palette</h1>
|
|
||||||
|
|
||||||
<div id = "colour-picker">
|
|
||||||
<div id = "cp-modes">
|
|
||||||
<button id="cp-rgb" class="cp-selected-mode" onclick="changePickerMode(this, 'rgb')">RGB</button>
|
|
||||||
<button id="cp-hsv" onclick="changePickerMode(this, 'hsv')">HSV</button>
|
|
||||||
<button id="cp-hsl" onclick="changePickerMode(this, 'hsl')">HSL</button>
|
|
||||||
|
|
||||||
<div id="cp-colour-preview" class="cp-colour-preview"></div>
|
|
||||||
<input id="cp-hex" type="text" value="#123456" onchange="hexUpdated()"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id = "sliders-container">
|
|
||||||
<div class = "cp-slider-entry">
|
|
||||||
<label for = "first-slider">R</label>
|
|
||||||
<input type="range" min="0" max="255" class="colour-picker-slider" id="first-slider" onmousemove="updateSliderValue(1)" onclick="updateSliderValue(1)"/>
|
|
||||||
<input type = "text" value = "128" onchange="inputChanged(this,1)"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class = "cp-slider-entry">
|
|
||||||
<label for = "second-slider">G</label>
|
|
||||||
<input type="range" min="0" max ="255" class="colour-picker-slider" id="second-slider" onmousemove="updateSliderValue(2)" onclick="updateSliderValue(2)"/>
|
|
||||||
<input type = "text" value = "128" onchange="inputChanged(this,2)"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class = "cp-slider-entry">
|
|
||||||
<label for = "third-slider">B</label>
|
|
||||||
<input type="range" min = "0" max = "255" class = "colour-picker-slider" id = "third-slider" onmousemove="updateSliderValue(3)" onclick="updateSliderValue(3)"/>
|
|
||||||
<input type = "text" value = "128" onchange="inputChanged(this,3)"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id = "cp-minipicker">
|
|
||||||
<input type = "range" min = "0" max = "100" id = "cp-minipicker-slider" onmousemove="miniSliderInput(event)" onclick="miniSliderInput(event)"/>
|
|
||||||
<div id="cp-canvas-container" onmousemove="movePickerIcon(event)">
|
|
||||||
<canvas id = "cp-spectrum"></canvas>
|
|
||||||
<div id="cp-active-icon" class="cp-picker-icon"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id = "cp-colours-previews">
|
|
||||||
<div class = "cp-colour-preview">
|
|
||||||
#123456
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id = "cp-colour-picking-modes">
|
|
||||||
<button class="cp-selected-mode" onclick="changePickingMode(event,'mono')">Mono</button>
|
|
||||||
<button onclick="changePickingMode(event,'analog')">Nlgs</button>
|
|
||||||
<button onclick="changePickingMode(event,'cmpt')">Cmpt</button>
|
|
||||||
<button onclick="changePickingMode(event,'tri')">Tri</button>
|
|
||||||
<button onclick="changePickingMode(event,'scmpt')">Scm</button>
|
|
||||||
<button onclick="changePickingMode(event,'tetra')">Tetra</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id = "palette-container">
|
|
||||||
<ul id = "palette-list">
|
|
||||||
<li style = "background-color:rgb(255,0,0);width:40px;height:40px;" onmousedown="startRampSelection(event)"
|
|
||||||
onmousemove="updateRampSelection(event)" onmouseup="endRampSelection(event)"></li>
|
|
||||||
<li style = "background-color:rgb(0,255,0);width:40px;height:40px;"onmousedown="startRampSelection(event)"
|
|
||||||
onmousemove="updateRampSelection(event)" onmouseup="endRampSelection(event)"></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="pb-options">
|
|
||||||
<button title="Add colours to palette" onclick="pbAddColours()">Add colours</button>
|
|
||||||
<button title="Remove colours from palette" onclick="pbRemoveColours()">Remove colours</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="help">
|
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
|
||||||
<h1>Help</h1>
|
|
||||||
<h2>Palette</h2>
|
|
||||||
<ul>
|
|
||||||
<li>Left Click - Choose Color</li>
|
|
||||||
<li>Right Click - Edit Color</li>
|
|
||||||
</ul>
|
|
||||||
<h2>Hotkeys</h2>
|
|
||||||
<ul>
|
|
||||||
<li><strong>Pencil:</strong> <span class="keyboard-key">B</span> or <span class="keyboard-key">1</span></li>
|
|
||||||
<li><strong>Eraser:</strong> <span class="keyboard-key">R</span></li>
|
|
||||||
<li><strong>Rectangle:</strong> <span class="keyboard-key">U</span></li>
|
|
||||||
<li><strong>Line:</strong> <span class="keyboard-key">L</span></li>
|
|
||||||
<li><strong>Fill:</strong> <span class="keyboard-key">F</span> or <span class="keyboard-key">2</span></li>
|
|
||||||
<li><strong>Eyedropper:</strong> <span class="keyboard-key">E</span> or <span class="keyboard-key">3</span></li>
|
|
||||||
<li><strong>Pan:</strong> <span class="keyboard-key">P</span> or <span class="keyboard-key">M</span> or <span class="keyboard-key">4</span></li>
|
|
||||||
<li><strong>Zoom:</strong> <span class="keyboard-key">Z</span> or <span class="keyboard-key">5</span></li>
|
|
||||||
<li><strong>Undo:</strong> Ctrl + <span class="keyboard-key">Z</span></li>
|
|
||||||
<li><strong>Redo:</strong> Ctrl + <span class="keyboard-key">Y</span> or Ctrl + Alt + <span class="keyboard-key">Z</span></li>
|
|
||||||
<li><strong>Rectangular selection:</strong> <span class="keyboard-key">M</span></li>
|
|
||||||
</ul>
|
|
||||||
<h2>Mouse Shortcuts</h2>
|
|
||||||
<ul>
|
|
||||||
<li><strong>Eyedropper: </strong>Alt + Click</li>
|
|
||||||
<li><strong>Pan: </strong>Space + Click</li>
|
|
||||||
<li><strong>Zoom: </strong>Alt + Scroll Wheel</li>
|
|
||||||
</ul>
|
|
||||||
<h2>Layers</h2>
|
|
||||||
<ul>
|
|
||||||
<li>{{svg "visible.svg" width="15" height="15" class = "default-icon"}}: show / hide layer</li>
|
|
||||||
<li>{{svg "lockedpadlock.svg" width="15" height="15" class = "default-icon"}}: lock / unlock layer, when a layer is locked it's not possible to draw on it</li>
|
|
||||||
<li>Right click on a layer to open the <strong>menu</strong>:
|
|
||||||
<ul>
|
|
||||||
<li><strong>Rename:</strong> change the name of the layer</li>
|
|
||||||
<li><strong>Duplicate:</strong> duplicate the layer</li>
|
|
||||||
<li><strong>Delete:</strong> delete the layer (doesn't work if there's only one layer)</li>
|
|
||||||
<li><strong>Merge below:</strong> merges the selected the layer with the one below it</li>
|
|
||||||
<li><strong>Flatten visible:</strong> merges all the visible layers</li>
|
|
||||||
<li></strong>Flatten all:</strong> merges all the layers</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="about">
|
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
|
||||||
<h1>About Lospec Pixel Editor</h1>
|
|
||||||
<div>version 1.1.0</div>
|
|
||||||
<p>This is a web-based tool for creating and editing pixel art.</p>
|
|
||||||
<p>The goal of this tool is to be an accessible and intuitive tool that's simple enough for a first time pixel artist while still being usable enough for a veteran. </p>
|
|
||||||
<p>In the future I hope to add enough features to become a full fledged pixel art editor, with everything an artist could need.</p>
|
|
||||||
<h1>About Lospec</h1>
|
|
||||||
<p>Lospec is a website created to host tools for pixel artists. To see more of our tools, visit our <a href="/">homepage</a>. To hear about any updates or new tools, follow us on <a href="http://twitter.com/lospecofficial">Twitter</a>.</p>
|
|
||||||
</div>
|
|
||||||
<div id="changelog">
|
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
|
||||||
|
|
||||||
<h1>Changelog</h1>
|
|
||||||
{{#each changelog}}
|
|
||||||
<h2>Version {{@key}}</h2>
|
|
||||||
<ul>{{#each this}}
|
|
||||||
<li>{{change}} <span class="weak">- {{author}}</span></li>
|
|
||||||
{{/each}}</ul>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
<div id="credits">
|
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
|
||||||
<h1>Credits</h1>
|
|
||||||
<h2>Icons</h2>
|
|
||||||
<ul>
|
|
||||||
<li><div>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div></li>
|
|
||||||
<li><div>Font Awesome by Dave Gandy - <a href="http://fontawesome.io">http://fontawesome.io</a></div></li>
|
|
||||||
<li><div>Icons made by <a href="http://www.flaticon.com/authors/those-icons" title="Those Icons">Those Icons</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="settings">
|
|
||||||
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
|
||||||
<h1>Settings</h1>
|
|
||||||
|
|
||||||
<div id="settings-container">
|
|
||||||
<h2>History</h2>
|
|
||||||
<div class = "settings-entry">
|
|
||||||
<label for="setting-numberOfHistoryStates">Number of History States</label> <input id="setting-numberOfHistoryStates" value="20" autocomplete="off" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Pixel grid</h2>
|
|
||||||
<div class = "settings-entry">
|
|
||||||
<label for="setting-pixelGridColour">Colour of the pixel grid</label><input id="setting-pixelGridColour" value = "#0000FF" autocomplete="off"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p id="cookies-disabled-warning">Your browsers cookies are disabled, settings will be lost upon closing this page.</p>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button id="save-settings" class="default">Save</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script src="/pixel-editor/pixel-editor.js"></script>
|
||||||
palettes = { {{#palettes}}
|
|
||||||
'{{title}}': {
|
|
||||||
colors: '{{colors}}'.split(',')
|
|
||||||
},
|
|
||||||
{{/palettes}}
|
|
||||||
{{#specifiedPalette}}
|
|
||||||
'{{title}}': {
|
|
||||||
colors: '{{colors}}'.split(','),
|
|
||||||
specified: true
|
|
||||||
}
|
|
||||||
{{/specifiedPalette}}
|
|
||||||
}
|
|
||||||
{{#if width}}
|
|
||||||
var specifiedDimentions = true;
|
|
||||||
{{else}}
|
|
||||||
var specifiedDimentions = false;
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#specifiedPalette}}
|
|
||||||
var keepUrl = true;
|
|
||||||
{{/specifiedPalette}}
|
|
||||||
|
|
||||||
// Set the default palettes
|
|
||||||
palettes["Commodore 64"] = {"name":"Commodore 64","author":"","colors":["000000","626262","898989","adadad","ffffff","9f4e44","cb7e75","6d5412","a1683c","c9d487","9ae29b","5cab5e","6abfc6","887ecb","50459b","a057a3"]}
|
|
||||||
palettes["PICO-8"] = {"name":"PICO-8","author":"","colors":["000000","1D2B53","7E2553","008751","AB5236","5F574F","C2C3C7","FFF1E8","FF004D","FFA300","FFEC27","00E436","29ADFF","83769C","FF77A8","FFCCAA"]}
|
|
||||||
palettes["Gameboy Color"] = {"name":"Nintendo Gameboy (Black Zero)","author":"","colors":["2e463d","385d49","577b46","7e8416"]}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<script src="pixel-editor.js"></script>
|
|
||||||
<script src="/reload/reload.js"></script>
|
<script src="/reload/reload.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,4 +1,3 @@
|
|||||||
<h1>Latest update</h1>
|
|
||||||
Hello there, welcome to the latest version of the Lospec Pixel Editor. As you can see, we changed
|
Hello there, welcome to the latest version of the Lospec Pixel Editor. As you can see, we changed
|
||||||
quite a lot of things. Let's go through all them, starting from this page.
|
quite a lot of things. Let's go through all them, starting from this page.
|
||||||
|
|
49
views/layers-menu.hbs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<!-- LAYER MENU -->
|
||||||
|
<ul id = "layers-menu">
|
||||||
|
<li class = "layers-menu-entry selected-layer">
|
||||||
|
<canvas class = "preview-canvas"></canvas>
|
||||||
|
<ul class="layer-buttons">
|
||||||
|
<li class = "layer-button">
|
||||||
|
<button title="Lock layer" class="lock-layer-button">
|
||||||
|
{{svg "unlockedpadlock.svg" width="15" height="15" class = "default-icon"}}
|
||||||
|
{{svg "lockedpadlock.svg" width="15" height="15" class = "edited-icon" display = "none"}}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class = "layer-button">
|
||||||
|
<button title="Show / hide layer" class="hide-layer-button">
|
||||||
|
{{svg "visible.svg" width="15" height="15" class = "default-icon"}}
|
||||||
|
{{svg "invisible.svg" width="15" height="15" class = "edited-icon" display = "none"}}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Layer 0<div class = "gradient"></div></p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<button id = "add-layer-button">
|
||||||
|
{{svg "plus.svg" width="20" height="20"}} Add layer
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul id = "layer-properties-menu">
|
||||||
|
<li>
|
||||||
|
<button onclick = "renameLayer()">Rename</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button onclick = "duplicateLayer()">Duplicate</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button onclick = "deleteLayer()">Delete</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button onclick = "merge()">Merge below</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button onclick = "flatten(true)">Flatten visible</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button onclick = "flatten(false)">Flatten all</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
68
views/main-menu.hbs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<ul id="main-menu">
|
||||||
|
<li class="logo">Lospec Pixel Editor</li>
|
||||||
|
<li>
|
||||||
|
<button>File</button>
|
||||||
|
<ul>
|
||||||
|
<li><button>New</button></li>
|
||||||
|
<li><button>Save project</button></li>
|
||||||
|
<li><button>Open</button></li>
|
||||||
|
<li><button id="export-button" class="disabled">Export</button></li>
|
||||||
|
<li><a href="https://lospec.com/pixel-editor">Exit</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button>Edit</button>
|
||||||
|
<ul>
|
||||||
|
<li><button id="resize-canvas-button" onclick = "openResizeCanvasWindow()">Resize canvas</button></li>
|
||||||
|
<li><button id="resize-sprite-button" onclick = "openResizeSpriteWindow()">Scale sprite</button></li>
|
||||||
|
<li><button onclick = "trimCanvas()">Trim canvas</button></li>
|
||||||
|
<li><button id="undo-button" class="disabled">Undo</button></li>
|
||||||
|
<li><button id="redo-button" class="disabled">Redo</button></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button>View</button>
|
||||||
|
<ul>
|
||||||
|
<li><button id="toggle-pixelgrid-button" onclick="togglePixelGrid()">Show pixel grid</button></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button id = "layer-button">Layer</button>
|
||||||
|
<ul>
|
||||||
|
<li><button onclick = "addLayer()">New layer</button></li>
|
||||||
|
<li><button onclick = "duplicateLayer()">Duplicate</button></li>
|
||||||
|
<li><button onclick = "renameLayer()">Rename</button></li>
|
||||||
|
<li><button onclick = "deleteLayer()">Delete</button></li>
|
||||||
|
<li><button onclick = "merge()">Merge below</button></li>
|
||||||
|
<li><button onclick = "flatten(false)">Flatten all</button></li>
|
||||||
|
<li><button onclick = "flatten(true)">Flatten visible</button></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button>Selection</button>
|
||||||
|
<ul>
|
||||||
|
<li><button id="copy-button">Copy</button></li>
|
||||||
|
<li><button id="cut-button">Cut</button></li>
|
||||||
|
<li><button id="paste-button">Paste</button></li>
|
||||||
|
<li><button id="cancelSelection-button">Cancel</button></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button>Editor</button>
|
||||||
|
<ul>
|
||||||
|
<li><button id="switch-mode-button">Switch to basic mode</button></li>
|
||||||
|
<li><button onclick="showDialogue('splash', false)">Splash page</button></li>
|
||||||
|
<li><button>Settings</button></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<button>Help</button>
|
||||||
|
<ul>
|
||||||
|
<li><button>Help</button></li>
|
||||||
|
<li><button>About</button></li>
|
||||||
|
<li><button>Changelog</button></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
74
views/palette-popup.hbs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<!-- PALETTE -->
|
||||||
|
<div id = "palette-block">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
|
||||||
|
<h1>Edit palette</h1>
|
||||||
|
|
||||||
|
<div id = "colour-picker">
|
||||||
|
<div id = "cp-modes">
|
||||||
|
<button id="cp-rgb" class="cp-selected-mode" onclick="changePickerMode(this, 'rgb')">RGB</button>
|
||||||
|
<button id="cp-hsv" onclick="changePickerMode(this, 'hsv')">HSV</button>
|
||||||
|
<button id="cp-hsl" onclick="changePickerMode(this, 'hsl')">HSL</button>
|
||||||
|
|
||||||
|
<div id="cp-colour-preview" class="cp-colour-preview"></div>
|
||||||
|
<input id="cp-hex" type="text" value="#123456" onchange="hexUpdated()"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id = "sliders-container">
|
||||||
|
<div class = "cp-slider-entry">
|
||||||
|
<label for = "first-slider">R</label>
|
||||||
|
<input type="range" min="0" max="255" class="colour-picker-slider" id="first-slider" onmousemove="updateSliderValue(1)" onclick="updateSliderValue(1)"/>
|
||||||
|
<input type = "text" value = "128" onchange="inputChanged(this,1)"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class = "cp-slider-entry">
|
||||||
|
<label for = "second-slider">G</label>
|
||||||
|
<input type="range" min="0" max ="255" class="colour-picker-slider" id="second-slider" onmousemove="updateSliderValue(2)" onclick="updateSliderValue(2)"/>
|
||||||
|
<input type = "text" value = "128" onchange="inputChanged(this,2)"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class = "cp-slider-entry">
|
||||||
|
<label for = "third-slider">B</label>
|
||||||
|
<input type="range" min = "0" max = "255" class = "colour-picker-slider" id = "third-slider" onmousemove="updateSliderValue(3)" onclick="updateSliderValue(3)"/>
|
||||||
|
<input type = "text" value = "128" onchange="inputChanged(this,3)"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id = "cp-minipicker">
|
||||||
|
<input type = "range" min = "0" max = "100" id = "cp-minipicker-slider" onmousemove="miniSliderInput(event)" onclick="miniSliderInput(event)"/>
|
||||||
|
<div id="cp-canvas-container" onmousemove="movePickerIcon(event)">
|
||||||
|
<canvas id = "cp-spectrum"></canvas>
|
||||||
|
<div id="cp-active-icon" class="cp-picker-icon"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id = "cp-colours-previews">
|
||||||
|
<div class = "cp-colour-preview">
|
||||||
|
#123456
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id = "cp-colour-picking-modes">
|
||||||
|
<button class="cp-selected-mode" onclick="changePickingMode(event,'mono')">Mono</button>
|
||||||
|
<button onclick="changePickingMode(event,'analog')">Nlgs</button>
|
||||||
|
<button onclick="changePickingMode(event,'cmpt')">Cmpt</button>
|
||||||
|
<button onclick="changePickingMode(event,'tri')">Tri</button>
|
||||||
|
<button onclick="changePickingMode(event,'scmpt')">Scm</button>
|
||||||
|
<button onclick="changePickingMode(event,'tetra')">Tetra</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id = "palette-container">
|
||||||
|
<ul id = "palette-list">
|
||||||
|
<li style = "background-color:rgb(255,0,0);width:40px;height:40px;" onmousedown="startRampSelection(event)"
|
||||||
|
onmousemove="updateRampSelection(event)" onmouseup="endRampSelection(event)"></li>
|
||||||
|
<li style = "background-color:rgb(0,255,0);width:40px;height:40px;"onmousedown="startRampSelection(event)"
|
||||||
|
onmousemove="updateRampSelection(event)" onmouseup="endRampSelection(event)"></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="pb-options">
|
||||||
|
<button title="Add colours to palette" onclick="pbAddColours()">Add colours</button>
|
||||||
|
<button title="Remove colours from palette" onclick="pbRemoveColours()">Remove colours</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
14
views/preload.hbs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<div class="preload">
|
||||||
|
<img src="/pixel-editor/dropdown-arrow.png" />
|
||||||
|
<img src="/pixel-editor/dropdown-arrow-hover.png" />
|
||||||
|
<img src="/pixel-editor/eyedropper.png" />
|
||||||
|
<img src="/pixel-editor/fill.png" />
|
||||||
|
<img src="/pixel-editor/pan.png" />
|
||||||
|
<img src="/pixel-editor/pan-held.png" />
|
||||||
|
<img src="/pixel-editor/pencil.png" />
|
||||||
|
<img src="/pixel-editor/zoom-in.png" />
|
||||||
|
<img src = "/pixel-editor/eraser.png"/>
|
||||||
|
<img src = "/pixel-editor/rectselect.png"/>
|
||||||
|
<!-- TODO: [ELLIPSE] Where is this icon used? Do we need similar one for ellipsis? -->
|
||||||
|
<img src= "/pixel-editor/rectangle.png">
|
||||||
|
</div>
|
22
views/settings-popup.hbs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<div id="settings">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
<h1>Settings</h1>
|
||||||
|
|
||||||
|
<div id="settings-container">
|
||||||
|
<h2>History</h2>
|
||||||
|
<div class = "settings-entry">
|
||||||
|
<label for="setting-numberOfHistoryStates">Number of History States</label> <input id="setting-numberOfHistoryStates" value="20" autocomplete="off" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Pixel grid</h2>
|
||||||
|
<div class = "settings-entry">
|
||||||
|
<label for="setting-pixelGridColour">Colour of the pixel grid</label><input id="setting-pixelGridColour" value = "#0000FF" autocomplete="off"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p id="cookies-disabled-warning">Your browsers cookies are disabled, settings will be lost upon closing this page.</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button id="save-settings" class="default">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
69
views/splash-page-popup.hbs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<!-- Splash page -->
|
||||||
|
<div id = "splash">
|
||||||
|
<div id="splash-news">
|
||||||
|
<div id="latest-update">
|
||||||
|
<h1>Latest updates</h1>
|
||||||
|
|
||||||
|
{{> latestLog}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="splash-input">
|
||||||
|
<div id="editor-logo">
|
||||||
|
<div id="black">
|
||||||
|
<div id="sp-coverdata">
|
||||||
|
<img src="https://lospec.com/brand/lospec_logo_3x.png"/> pixel editor
|
||||||
|
<p>Version 1.4.0</p>
|
||||||
|
<a href="https://cdn.discordapp.com/attachments/506277390050131978/795660870221955082/final.png">Art by Unsettled</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="splash-menu">
|
||||||
|
<div id="sp-newpixel">
|
||||||
|
<h1>New Custom Pixel</h1>
|
||||||
|
<!-- Editor mode-->
|
||||||
|
<h2>Editor mode</h2>
|
||||||
|
<div class="sp-np-entry" id="sp-mode-palette">
|
||||||
|
<div class="button-menu">
|
||||||
|
<div class="bm-left" onclick="splashMode(event,'Basic')"><p>Basic</p></div>
|
||||||
|
<div class="sp-interface-selected bm-right" onclick="splashMode(event,'Advanced')"><p>Advanced</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Size</h2>
|
||||||
|
<div class="sp-np-entry">
|
||||||
|
<input id="size-width-splash" value="{{#if width}}{{width}}{{else}}64{{/if}}" autocomplete="off" />{{svg "x.svg" width="16" height="16" class="dimentions-x"}}<input id="size-height-splash" value="{{#if height}}{{height}}{{else}}64{{/if}}" autocomplete="off" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Palette</h2>
|
||||||
|
<button id="palette-button-splash" class="dropdown-button">Choose a palette...</button>
|
||||||
|
<div id="palette-menu-splash" class="dropdown-menu"><button id="load-palette-button-splash">Load palette...</button></div>
|
||||||
|
|
||||||
|
<div id="new-pixel-warning">Creating a new pixel will discard your current one.</div>
|
||||||
|
<div class="sp-np-entry">
|
||||||
|
<button id="create-button-splash" class="default">Create</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id = "sp-quickstart-container">
|
||||||
|
<div id="sp-quickstart-title">
|
||||||
|
Quickstart
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="sp-quickstart">
|
||||||
|
<div class="sp-template" onclick="document.getElementById('open-image-browse-holder').click()"><p>Load</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('Gameboy Color')"><p><span>New</span> Gameboy</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('Commodore 64')"><p><span>New</span> C64</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('PICO-8')"><p><span>New</span> Pico8</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('',16,16)"><p><span>New</span> 16x16</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('',32,32)"><p><span>New</span> 32x32</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('',64,64)"><p><span>New</span> 64x64</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('',128,128)"><p><span>New</span> 128x128</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('',256,256)"><p><span>New</span> 256x256</p></div>
|
||||||
|
<div class="sp-template" onclick="newFromTemplate('',512,512)"><p><span>New</span> 512x512</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
49
views/sprite-resize-popup.hbs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<!--SPRITE RESIZE-->
|
||||||
|
<div class="update" id = "resize-sprite">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
<h1>Scale sprite</h1>
|
||||||
|
<!-- SIZE-->
|
||||||
|
<h2>New size</h2>
|
||||||
|
<span id = "rs-size-menu">
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
Width: <input id="rs-width" type="number" default="0" step="1"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Height: <input id="rs-height" default="0" step="1" type="number"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<!--BORDERS-->
|
||||||
|
<h2>Resize percentages</h2>
|
||||||
|
<span id = "rs-percentage-menu">
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
Width <input id="rs-width-percentage" type="number" default="0" step="1"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/> %
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Height <input id="rs-height-percentage" type="number" default="0" step="1"
|
||||||
|
value="{{#if border}}{{border}}{{else}}0{{/if}}" autocomplete="off"/> %
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div id = "rs-ratio-div">
|
||||||
|
<span>
|
||||||
|
Keep current ratio <input type = "checkbox" id = "rs-keep-ratio"/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
Scaling algorithm:
|
||||||
|
<select name = "resize-algorithm" id = "resize-algorithm-combobox">
|
||||||
|
<option value = "nearest-neighbor">Nearest neighbour</option>
|
||||||
|
<option value = "bilinear-interpolation">Bilinear</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</br>
|
||||||
|
<button id = "resize-sprite-confirm">Scale sprite</button>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
28
views/start-pixel-popup.hbs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<!-- NEW PIXEL -->
|
||||||
|
<div id="new-pixel" class="update">
|
||||||
|
<button class="close-button">{{svg "x.svg" width="20" height="20"}}</button>
|
||||||
|
<h1>New Pixel</h1>
|
||||||
|
|
||||||
|
<!-- Editor mode-->
|
||||||
|
<h2>Editor mode</h2>
|
||||||
|
<button id = "editor-mode-button" class = "dropdown-button">Choose a mode...</button>
|
||||||
|
<div id = "editor-mode-menu" class = "dropdown-menu"></div>
|
||||||
|
<input id="editor-mode" value="{{#if mode}}{{mode}}{{else}}'Advanced'{{/if}}" autocomplete="off" />
|
||||||
|
<p id = "editor-mode-info"></p>
|
||||||
|
|
||||||
|
<!-- Preset-->
|
||||||
|
<h2>Preset</h2>
|
||||||
|
<button id="preset-button" class="dropdown-button">Choose a preset...</button>
|
||||||
|
<div id="preset-menu" class="dropdown-menu"></div>
|
||||||
|
|
||||||
|
<h2>Size</h2>
|
||||||
|
<input id="size-width" value="{{#if width}}{{width}}{{else}}64{{/if}}" autocomplete="off" />{{svg "x.svg" width="16" height="16" class="dimentions-x"}}<input id="size-height" value="{{#if height}}{{height}}{{else}}64{{/if}}" autocomplete="off" />
|
||||||
|
<h2>Palette</h2>
|
||||||
|
<button id="palette-button" class="dropdown-button">Choose a palette...</button>
|
||||||
|
<div id="palette-menu" class="dropdown-menu"><button id="no-palette-button">Empty Palette</button><button id="load-palette-button">Load palette...</button></div>
|
||||||
|
|
||||||
|
<div id="new-pixel-warning">Creating a new pixel will discard your current one.</div>
|
||||||
|
<div>
|
||||||
|
<button id="create-button" class="default">Create</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
3
views/tool-previews.hbs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<!-- TOOL PREVIEWS -->
|
||||||
|
<div id="eyedropper-preview"></div>
|
||||||
|
<div id="brush-preview"></div>
|
46
views/tools-menu.hbs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<ul id="tools-menu">
|
||||||
|
<li class="selected expanded">
|
||||||
|
<button title="Pencil Tool (B)" id="pencil-button">{{svg "pencil.svg" width="32" height="32"}}</button>
|
||||||
|
<button title="Increase Brush Size" id="pencil-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
||||||
|
<button title="Decrease Brush Size" id="pencil-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class = "expanded">
|
||||||
|
<button title="Eraser tool (R)" id="eraser-button">{{svg "eraser.svg" width="32" height="32"}}</button>
|
||||||
|
<button title="Increase Eraser Size" id="eraser-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
||||||
|
<button title="Decrease Eraser Size" id="eraser-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="expanded">
|
||||||
|
<button title="Rectangle Tool (U)" id="rectangle-button">{{svg "rectangle.svg" width="32" height="32" id = "rectangle-empty-button-svg"}}
|
||||||
|
{{svg "fullrect.svg" width="32" height="32" id = "rectangle-full-button-svg" display = "none"}}</button>
|
||||||
|
<button title="Increase Rectangle Size" id="rectangle-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
||||||
|
<button title="Decrease Rectangle Size" id="rectangle-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- TODO: [ELLIPSE] Once ellipse is ready for release make it visible by default -->
|
||||||
|
<li class="expanded" id="tools-menu--ellipse" style="display: none">
|
||||||
|
<!-- TODO: [ELLIPSE] Decide on a shortcut to use. "S" was chosen without any in-team consultation. -->
|
||||||
|
<!-- TODO: [ELLIPSE] Decide on icons to use. Current ones are quickly prepared drafts and display with incorrect color. -->
|
||||||
|
<button title="Ellipse Tool (S)" id="ellipse-button">
|
||||||
|
{{svg "ellipse.svg" width="32" height="32" id = "ellipse-empty-button-svg"}}
|
||||||
|
{{svg "filledellipse.svg" width="32" height="32" id = "ellipse-full-button-svg" display = "none"}}
|
||||||
|
</button>
|
||||||
|
<button title="Increase Ellipse Size" id="ellipse-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
||||||
|
<button title="Decrease Ellipse Size" id="ellipse-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="expanded">
|
||||||
|
<button title="Line Tool (L)" id="line-button">{{svg "line.svg" width="32" height="32"}}</button>
|
||||||
|
<button title="Increase Line Size" id="line-bigger-button" class="tools-menu-sub-button">{{svg "plus.svg" width="12" height="12"}}</button>
|
||||||
|
<button title="Decrease Line Size" id="line-smaller-button" class="tools-menu-sub-button">{{svg "minus.svg" width="12" height="12"}}</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><button title="Fill Tool (F)" id="fill-button">{{svg "fill.svg" width="32" height="32"}}</button></li>
|
||||||
|
|
||||||
|
<li><button title="Eyedropper Tool (E)" id="eyedropper-button">{{svg "eyedropper.svg" width="32" height="32"}}</button></li>
|
||||||
|
|
||||||
|
<li><button title="Pan Tool (P)" id="pan-button">{{svg "pan.svg" width="32" height="32"}}</button></li>
|
||||||
|
|
||||||
|
<li><button title = "Rectangular Selection Tool (M)" id = "rectselect-button">{{svg "rectselect.svg" width = "32" height = "32"}}</button><li>
|
||||||
|
</ul>
|