From 4d4878c4fab363c3d358b9102e1bd3ae058e4b1b Mon Sep 17 00:00:00 2001 From: Leamsi Escribano Date: Sun, 4 Jul 2021 13:55:49 -0400 Subject: [PATCH 01/91] Refactored addColor.js --- js/ColorModule.js | 207 ++++++++++++++++++++++++++++++++++++++ js/_addColor.js | 56 ----------- js/_addColorButton.js | 59 ----------- js/_colorChanged.js | 101 ------------------- js/_createColorPalette.js | 2 +- js/_dialogue.js | 2 +- js/_fileMenu.js | 6 +- js/_history.js | 4 +- js/_initColor.js | 25 ----- js/_newPixel.js | 6 +- js/_paletteBlock.js | 22 ---- js/pixel-editor.js | 5 +- 12 files changed, 218 insertions(+), 277 deletions(-) create mode 100644 js/ColorModule.js delete mode 100644 js/_addColor.js delete mode 100644 js/_addColorButton.js delete mode 100644 js/_colorChanged.js delete mode 100644 js/_initColor.js diff --git a/js/ColorModule.js b/js/ColorModule.js new file mode 100644 index 0000000..82a2054 --- /dev/null +++ b/js/ColorModule.js @@ -0,0 +1,207 @@ +/** Adds the given color to the palette + * + * @param {*} newColor the colour to add + * @return the list item containing the added colour + */ +const ColorModule = (() => { + const currentPalette = []; + const coloursList = document.getElementById("palette-list"); + + + console.info("Initialized Color Module.."); + document.getElementById('jscolor-hex-input').addEventListener('change',colorChanged, false); + document.getElementById('jscolor-hex-input').addEventListener('input', colorChanged, false); + document.getElementById('add-color-button').addEventListener('click', addColorButtonEvent, false); + + new Sortable(document.getElementById("colors-menu"), { + animation:100, + filter: ".noshrink", + draggable: ".draggable-colour", + onEnd: makeIsDraggingFalse + }); + + // Changes all of one color to another after being changed from color picker + function colorChanged(colorHexElement) { + // Get old and new colors from the element + const hexElement = colorHexElement.target; + const hexElementValue = hexElement.value; + const newColor = hexToRgb(hexElementValue); + const oldColor = hexElement.oldColor; + + //if the color is not a valid hex color, exit this function and do nothing + const newColorHex = hexElementValue.toLowerCase(); + if (/^[0-9a-f]{6}$/i.test(newColorHex) == false) return + + currentPalette.splice(currentPalette.indexOf("#" + newColor), 1); + newColor.a = 255; + + //save undo state + new HistoryStateEditColor(hexElementValue.toLowerCase(), rgbToHex(oldColor)); + + //get the currently selected color + const currentlyEditedColor = document.getElementsByClassName('jscolor-active')[0]; + const duplicateColorWarning = document.getElementById('duplicate-color-warning'); + + //check if selected color already matches another color + colors = document.getElementsByClassName('color-button'); + + //loop through all colors in palette + for (var i = 0; i < colors.length; i++) { + + //if generated color matches this color + if (newColorHex == colors[i].jscolor.toString()) { + //if the color isnt the one that has the picker currently open + if (!colors[i].parentElement.classList.contains('jscolor-active')) { + //console.log('%cColor is duplicate', colorCheckingStyle); + + //show the duplicate color warning + duplicateColorWarning.style.visibility = 'visible'; + + //shake warning icon + duplicateColorWarning.classList.remove('shake'); + void duplicateColorWarning.offsetWidth; + duplicateColorWarning.classList.add('shake'); + + //exit function without updating color + return; + } + } + } + + //if the color being edited has a duplicate color warning, remove it + duplicateColorWarning.style.visibility = 'hidden'; + + currentlyEditedColor.firstChild.jscolor.fromString(newColorHex); + + replaceAllOfColor(oldColor, newColor); + + //set new old color to changed color + hexElement.oldColor = newColor; + currentPalette.push('#' + newColorHex); + + //if this is the current color, update the drawing color + if (hexElement.colorElement.parentElement.classList.contains('selected')) { + for (let i=1; i Date: Sun, 4 Jul 2021 17:36:15 -0400 Subject: [PATCH 02/91] addColor Refactor --- js/ColorModule.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/js/ColorModule.js b/js/ColorModule.js index 82a2054..478ac9e 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -162,10 +162,10 @@ const ColorModule = (() => { newColor = '#' + newColor; currentPalette.push(newColor); //create list item - var listItem = document.createElement('li'); + const listItem = document.createElement('li'); //create button - var button = document.createElement('button'); + const button = document.createElement('button'); button.classList.add('color-button'); button.style.backgroundColor = newColor; button.addEventListener('mouseup', clickedColor); @@ -179,13 +179,11 @@ const ColorModule = (() => { initColor(button); //add edit button - var editButtonTemplate = document.getElementsByClassName('color-edit-button')[0]; + const editButtonTemplate = document.getElementsByClassName('color-edit-button')[0]; newEditButton = editButtonTemplate.cloneNode(true); listItem.appendChild(newEditButton); - - //when you click the edit button - on('click', newEditButton, function (event, button) { - + + newEditButton.addEventListener('click', (e,button) => { //hide edit button button.parentElement.lastChild.classList.add('hidden'); @@ -195,7 +193,7 @@ const ColorModule = (() => { else showDialogue("palette-block", false); }); - + return listItem; } From 3f2d67a36ed4391c8882eada38022ebbf231a7b1 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Fri, 9 Jul 2021 23:44:04 +0200 Subject: [PATCH 03/91] Tested get/set functions Found out every function that uses this has problems: when calling an object method as an input callback, this gets replaced with the element that triggered the event. --- css/_canvas.scss | 2 +- js/ColorModule.js | 4 +++- js/_createButton.js | 46 +++++++++++++++++++++++------------------- js/_fileMenu.js | 6 +++--- js/_loadPalette.js | 4 ++-- js/_mouseEvents.js | 2 -- js/_newPixel.js | 4 ++-- js/_palettes.js | 32 ++++++++++++++--------------- js/_presets.js | 8 ++++---- js/_settings.js | 6 +++--- js/pixel-editor.js | 2 -- js/util/getSetText.js | 10 --------- js/util/getSetValue.js | 12 ----------- 13 files changed, 59 insertions(+), 79 deletions(-) delete mode 100644 js/util/getSetText.js delete mode 100644 js/util/getSetValue.js diff --git a/css/_canvas.scss b/css/_canvas.scss index 40633fb..fbba685 100644 --- a/css/_canvas.scss +++ b/css/_canvas.scss @@ -70,7 +70,7 @@ #brush-preview { position: absolute; - border: solid 1px #fff; + border: solid 2px #fff; z-index: 1200; box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.5), inset 0 0 2px 0 rgba(0, 0, 0, 0.5); pointer-events: none; diff --git a/js/ColorModule.js b/js/ColorModule.js index 478ac9e..dceeb69 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -202,4 +202,6 @@ const ColorModule = (() => { addColor, AddToSimplePalette } -})(); \ No newline at end of file +})(); + +console.log("Color module: " + ColorModule); \ No newline at end of file diff --git a/js/_createButton.js b/js/_createButton.js index bda39d5..d0f516d 100644 --- a/js/_createButton.js +++ b/js/_createButton.js @@ -5,8 +5,8 @@ function create(isSplash) { splashPostfix = '-splash'; } - var width = getValue('size-width' + splashPostfix); - var height = getValue('size-height' + splashPostfix); + var width = Util.getValue('size-width' + splashPostfix); + var height = Util.getValue('size-height' + splashPostfix); // If I'm creating from the splash screen, I use the splashMode variable var mode = isSplash ? splashMode : pixelEditorMode; @@ -18,7 +18,7 @@ function create(isSplash) { document.getElementById('new-pixel-warning').style.display = 'block'; //get selected palette name - var selectedPalette = getText('palette-button' + splashPostfix); + var selectedPalette = Util.getText('palette-button' + splashPostfix); if (selectedPalette == 'Choose a palette...') selectedPalette = 'none'; @@ -27,27 +27,31 @@ function create(isSplash) { //reset new form - setValue('size-width', 64); - setValue('size-height', 64); + Util.setValue('size-width', 64); + Util.setValue('size-height', 64); - setText('palette-button', 'Choose a palette...'); - setText('preset-button', 'Choose a preset...'); + Util.setText('palette-button', 'Choose a palette...'); + Util.setText('preset-button', 'Choose a preset...'); } /** Triggered when the "Create" button in the new pixel dialogue is pressed * */ on('click', 'create-button', function (){ + console.log("Here"); // Getting the values of the form - var width = getValue('size-width'); - var height = getValue('size-height'); + var width = Util.getValue('size-width'); + var height = Util.getValue('size-height'); // Creating a new pixel with those properties - newPixel(width, height); + if(pixelEditorMode == "Basic") + newPixel(width, height, "Advanced"); + else + newPixel(width, height, "Basic"); document.getElementById('new-pixel-warning').style.display = 'block'; //get selected palette name - var selectedPalette = getText('palette-button'); + var selectedPalette = Util.getText('palette-button'); if (selectedPalette == 'Choose a palette...') selectedPalette = 'none'; @@ -56,11 +60,11 @@ on('click', 'create-button', function (){ //reset new form - setValue('size-width', 64); - setValue('size-height', 64); + Util.setValue('size-width', 64); + Util.setValue('size-height', 64); - setText('palette-button', 'Choose a palette...'); - setText('preset-button', 'Choose a preset...'); + Util.setText('palette-button', 'Choose a palette...'); + Util.setText('preset-button', 'Choose a preset...'); }); /** Triggered when the "Create" button in the new pixel dialogue is pressed @@ -68,8 +72,8 @@ on('click', 'create-button', function (){ */ on('click', 'create-button-splash', function (){ // Getting the values of the form - var width = getValue('size-width-splash'); - var height = getValue('size-height-splash'); + var width = Util.getValue('size-width-splash'); + var height = Util.getValue('size-height-splash'); var mode = pixelEditorMode; if (mode == 'Advanced') @@ -88,9 +92,9 @@ on('click', 'create-button-splash', function (){ selectedPalette = 'none'; //reset new pixel form - setValue('size-width-splash', 64); - setValue('size-height-splash', 64); + Util.setValue('size-width-splash', 64); + Util.setValue('size-height-splash', 64); - setText('palette-button', 'Choose a palette...'); - setText('preset-button', 'Choose a preset...'); + Util.setText('palette-button', 'Choose a palette...'); + Util.setText('preset-button', 'Choose a preset...'); }); diff --git a/js/_fileMenu.js b/js/_fileMenu.js index 93f81b0..a5a34c2 100644 --- a/js/_fileMenu.js +++ b/js/_fileMenu.js @@ -31,7 +31,7 @@ for (var i = 1; i < mainMenuItems.length; i++) { break; case 'Save project': //create name - var selectedPalette = getText('palette-button'); + var selectedPalette = Util.getText('palette-button'); if (selectedPalette != 'Choose a palette...'){ var paletteAbbreviation = palettes[selectedPalette].abbreviation; var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.lpe'; @@ -69,7 +69,7 @@ for (var i = 1; i < mainMenuItems.length; i++) { case 'Export': if (documentCreated) { //create name - var selectedPalette = getText('palette-button'); + var selectedPalette = Util.getText('palette-button'); if (selectedPalette != 'Choose a palette...'){ var paletteAbbreviation = palettes[selectedPalette].abbreviation; var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.png'; @@ -167,7 +167,7 @@ for (var i = 1; i < mainMenuItems.length; i++) { //Help Menu case 'Settings': //fill form with current settings values - setValue('setting-numberOfHistoryStates', settings.numberOfHistoryStates); + Util.setValue('setting-numberOfHistoryStates', settings.numberOfHistoryStates); showDialogue('settings'); break; diff --git a/js/_loadPalette.js b/js/_loadPalette.js index 035bd2a..d7bda53 100644 --- a/js/_loadPalette.js +++ b/js/_loadPalette.js @@ -37,8 +37,8 @@ document.getElementById('load-palette-browse-holder').addEventListener('change', //add to palettes so that it can be loaded when they click okay palettes['Loaded palette'] = {}; palettes['Loaded palette'].colors = colorPalette; - setText('palette-button', 'Loaded palette'); - setText('palette-button-splash', 'Loaded palette'); + Util.setText('palette-button', 'Loaded palette'); + Util.setText('palette-button-splash', 'Loaded palette'); toggle('palette-menu-splash'); }; img.src = e.target.result; diff --git a/js/_mouseEvents.js b/js/_mouseEvents.js index 82c5853..ef978b4 100644 --- a/js/_mouseEvents.js +++ b/js/_mouseEvents.js @@ -423,8 +423,6 @@ function draw (mouseEvent) { currentTool.updateCursor(); else canvasView.style.cursor = 'default'; - - console.log("Cursor: " + canvasView.style.cursor); } //mousewheel scroll diff --git a/js/_newPixel.js b/js/_newPixel.js index 326dbd2..592fdbd 100644 --- a/js/_newPixel.js +++ b/js/_newPixel.js @@ -97,9 +97,9 @@ function newPixel (width, height, editorMode, fileContent = null) { //add colors from selected palette var selectedPalette; if (!firstPixel) - var selectedPalette = getText('palette-button'); + var selectedPalette = Util.getText('palette-button'); else - var selectedPalette = getText('palette-button-splash'); + var selectedPalette = Util.getText('palette-button-splash'); // If the user selected a palette and isn't opening a file, I load the selected palette if (selectedPalette != 'Choose a palette...' && fileContent == null) { diff --git a/js/_palettes.js b/js/_palettes.js index 4f789f2..c0ff1b9 100644 --- a/js/_palettes.js +++ b/js/_palettes.js @@ -84,10 +84,10 @@ palettes["Gameboy Color"] = {"name":"Nintendo Gameboy (Black Zero)","author":"", const buttonEvent = () => { //hide the dropdown menu - Util.deselect('palette-menu'); - Util.deselect('palette-button'); - Util.deselect('palette-menu-splash'); - Util.deselect('palette-button-splash'); + deselect('palette-menu'); + deselect('palette-button'); + deselect('palette-menu-splash'); + deselect('palette-button-splash'); //show empty palette option noPaletteButton.style.display = 'block'; @@ -115,15 +115,15 @@ palettes["Gameboy Color"] = {"name":"Nintendo Gameboy (Black Zero)","author":"", document.getElementById('load-palette-browse-holder').click(); } const clickPaletteButtonEvent = (e) => { - Util.toggle('palette-button'); - Util.toggle('palette-menu'); + toggle('palette-button'); + toggle('palette-menu'); - Util.deselect('preset-button'); - Util.deselect('preset-menu'); + deselect('preset-button'); + deselect('preset-menu'); // Splash version - Util.toggle('palette-button-splash'); - Util.toggle('palette-menu-splash'); + toggle('palette-button-splash'); + toggle('palette-menu-splash'); e.stopPropagation(); } @@ -141,13 +141,13 @@ palettes["Gameboy Color"] = {"name":"Nintendo Gameboy (Black Zero)","author":"", }) newPixelElement.addEventListener('click', () => { - Util.deselect('preset-button'); - Util.deselect('preset-menu'); - Util.deselect('palette-button'); - Util.deselect('palette-menu'); + deselect('preset-button'); + deselect('preset-menu'); + deselect('palette-button'); + deselect('palette-menu'); // Splash version - Util.deselect('palette-button-splash'); - Util.deselect('palette-menu-splash'); + deselect('palette-button-splash'); + deselect('palette-menu-splash'); }) })(); \ No newline at end of file diff --git a/js/_presets.js b/js/_presets.js index 955f243..3858c76 100644 --- a/js/_presets.js +++ b/js/_presets.js @@ -25,8 +25,8 @@ const PresetModule = (() => { Util.setText('palette-button', presets[presetName].palette); //hide the dropdown menu - Util.deselect('preset-menu'); - Util.deselect('preset-button'); + deselect('preset-menu'); + deselect('preset-button'); //set the text of the dropdown to the newly selected preset Util.setText('preset-button', presetName); @@ -41,8 +41,8 @@ const PresetModule = (() => { Util.toggle('preset-menu'); //close the palette menu - Util.deselect('palette-button'); - Util.deselect('palette-menu'); + deselect('palette-button'); + deselect('palette-menu'); e.stopPropagation(); }); diff --git a/js/_settings.js b/js/_settings.js index 1c92a98..22df17d 100644 --- a/js/_settings.js +++ b/js/_settings.js @@ -30,14 +30,14 @@ on('click', 'save-settings', saveSettings); function saveSettings() { //check if values are valid - if (isNaN(getValue('setting-numberOfHistoryStates'))) { + if (isNaN(Util.getValue('setting-numberOfHistoryStates'))) { alert('Invalid value for numberOfHistoryStates'); return; } //save new settings to settings object - settings.numberOfHistoryStates = getValue('setting-numberOfHistoryStates'); - settings.pixelGridColour = getValue('setting-pixelGridColour'); + settings.numberOfHistoryStates = Util.getValue('setting-numberOfHistoryStates'); + settings.pixelGridColour = Util.getValue('setting-pixelGridColour'); // Filling pixel grid again if colour changed fillPixelGrid(); diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 79351e4..41ece01 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -4,8 +4,6 @@ //=include util/onClick.js //=include util/onClickChildren.js //=include util/select.js -//=include util/getSetText.js -//=include util/getSetValue.js //=include util/hexToRgb.js //=include util/rgbToHex.js //=include util/rgbToHsl.js diff --git a/js/util/getSetText.js b/js/util/getSetText.js deleted file mode 100644 index fbee0f9..0000000 --- a/js/util/getSetText.js +++ /dev/null @@ -1,10 +0,0 @@ -//get text of specified element -function getText(elementId) { - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - return element.textContent; -} - -function setText(elementId, text) { - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - element.textContent = text; -} \ No newline at end of file diff --git a/js/util/getSetValue.js b/js/util/getSetValue.js deleted file mode 100644 index f69e489..0000000 --- a/js/util/getSetValue.js +++ /dev/null @@ -1,12 +0,0 @@ - - -function getValue(elementId) { - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - console.log("setting: " + elementId + ": " + element.value); - return element.value; -} - -function setValue(elementId, value) { - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - element.value = value; -} \ No newline at end of file From f81019830bd7d964a5a6f3feac84ceecbba23ac2 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Fri, 9 Jul 2021 23:50:29 +0200 Subject: [PATCH 04/91] Edited brush preview to be a bit more visible --- css/_canvas.scss | 2 +- js/_mouseEvents.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/css/_canvas.scss b/css/_canvas.scss index fbba685..40633fb 100644 --- a/css/_canvas.scss +++ b/css/_canvas.scss @@ -70,7 +70,7 @@ #brush-preview { position: absolute; - border: solid 2px #fff; + border: solid 1px #fff; z-index: 1200; box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.5), inset 0 0 2px 0 rgba(0, 0, 0, 0.5); pointer-events: none; diff --git a/js/_mouseEvents.js b/js/_mouseEvents.js index ef978b4..33e6d66 100644 --- a/js/_mouseEvents.js +++ b/js/_mouseEvents.js @@ -243,8 +243,8 @@ function draw (mouseEvent) { var selectedColor = currentLayer.context.getImageData(Math.floor(cursorLocation[0]/zoom),Math.floor(cursorLocation[1]/zoom),1,1).data; var colorLightness = Math.max(selectedColor[0],selectedColor[1],selectedColor[2]) - //for the darkest 50% of colors, change the brush preview to dark mode - if (colorLightness>127) brushPreview.classList.remove('dark'); + //for the darkest 75% of colors, change the brush preview to dark mode + if (colorLightness>64) brushPreview.classList.remove('dark'); else brushPreview.classList.add('dark'); currentLayer.updateLayerPreview(); From dbffc0b9da42f84d3404d4144cb6dae39567fff0 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Sat, 10 Jul 2021 11:05:56 +0200 Subject: [PATCH 05/91] Fixed Util static method issue Also fixed bug in Util.getElement --- js/Util.js | 26 ++++++++++++++++---------- js/_fileMenu.js | 4 ++-- js/_palettes.js | 32 ++++++++++++++++---------------- js/_presets.js | 8 ++++---- js/pixel-editor.js | 1 - js/util/select.js | 20 -------------------- 6 files changed, 38 insertions(+), 53 deletions(-) delete mode 100644 js/util/select.js diff --git a/js/Util.js b/js/Util.js index 760ca03..7455937 100644 --- a/js/Util.js +++ b/js/Util.js @@ -1,35 +1,41 @@ // Acts as a public static class class Util { static getElement(elementOrElementId) { - return typeof elementOrElementId - ? document.getElementById(elementOrElementId) - : elementOrElementId; + if (typeof(elementOrElementId) == "object") { + return elementOrElementId; + } + else if (typeof(elementOrElementId) == "string") { + return document.getElementById(elementOrElementId); + } + else { + console.log("Type not supported: " + typeof(elementOrElementId)); + } } static getText(elementId) { - return this.getElement(elementId).textContent; + return Util.getElement(elementId).textContent; } static setText(elementId, text) { - this.getElement(elementId).textContent = text; + Util.getElement(elementId).textContent = text; } static getValue(elementId) { - return this.getElement(elementId).value; + return Util.getElement(elementId).value; } static setValue(elementId, value) { - this.getElement(elementId).value = value; + Util.getElement(elementId).value = value; } //add class .selected to specified element static select(elementId) { - this.getElement(elementId).classList.add('selected'); + Util.getElement(elementId).classList.add('selected'); } //remove .selected class from specified element static deselect(elementId) { - this.getElement(elementId).classList.remove('selected'); + Util.getElement(elementId).classList.remove('selected'); } //toggle the status of the .selected class on the specified element static toggle(elementId) { - this.getElement(elementId).classList.toggle('selected'); + Util.getElement(elementId).classList.toggle('selected'); } } \ No newline at end of file diff --git a/js/_fileMenu.js b/js/_fileMenu.js index a5a34c2..59ad06e 100644 --- a/js/_fileMenu.js +++ b/js/_fileMenu.js @@ -9,7 +9,7 @@ for (var i = 1; i < mainMenuItems.length; i++) { //when you click a main menu items button on('click', menuButton, function (e, button) { - select(button.parentElement); + Util.select(button.parentElement); }); var subMenu = menuItem.children[1]; @@ -191,7 +191,7 @@ for (var i = 1; i < mainMenuItems.length; i++) { function closeMenu () { //remove .selected class from all menu buttons for (var i = 0; i < mainMenuItems.length; i++) { - deselect(mainMenuItems[i]); + Util.deselect(mainMenuItems[i]); } } diff --git a/js/_palettes.js b/js/_palettes.js index c0ff1b9..4f789f2 100644 --- a/js/_palettes.js +++ b/js/_palettes.js @@ -84,10 +84,10 @@ palettes["Gameboy Color"] = {"name":"Nintendo Gameboy (Black Zero)","author":"", const buttonEvent = () => { //hide the dropdown menu - deselect('palette-menu'); - deselect('palette-button'); - deselect('palette-menu-splash'); - deselect('palette-button-splash'); + Util.deselect('palette-menu'); + Util.deselect('palette-button'); + Util.deselect('palette-menu-splash'); + Util.deselect('palette-button-splash'); //show empty palette option noPaletteButton.style.display = 'block'; @@ -115,15 +115,15 @@ palettes["Gameboy Color"] = {"name":"Nintendo Gameboy (Black Zero)","author":"", document.getElementById('load-palette-browse-holder').click(); } const clickPaletteButtonEvent = (e) => { - toggle('palette-button'); - toggle('palette-menu'); + Util.toggle('palette-button'); + Util.toggle('palette-menu'); - deselect('preset-button'); - deselect('preset-menu'); + Util.deselect('preset-button'); + Util.deselect('preset-menu'); // Splash version - toggle('palette-button-splash'); - toggle('palette-menu-splash'); + Util.toggle('palette-button-splash'); + Util.toggle('palette-menu-splash'); e.stopPropagation(); } @@ -141,13 +141,13 @@ palettes["Gameboy Color"] = {"name":"Nintendo Gameboy (Black Zero)","author":"", }) newPixelElement.addEventListener('click', () => { - deselect('preset-button'); - deselect('preset-menu'); - deselect('palette-button'); - deselect('palette-menu'); + Util.deselect('preset-button'); + Util.deselect('preset-menu'); + Util.deselect('palette-button'); + Util.deselect('palette-menu'); // Splash version - deselect('palette-button-splash'); - deselect('palette-menu-splash'); + Util.deselect('palette-button-splash'); + Util.deselect('palette-menu-splash'); }) })(); \ No newline at end of file diff --git a/js/_presets.js b/js/_presets.js index 3858c76..955f243 100644 --- a/js/_presets.js +++ b/js/_presets.js @@ -25,8 +25,8 @@ const PresetModule = (() => { Util.setText('palette-button', presets[presetName].palette); //hide the dropdown menu - deselect('preset-menu'); - deselect('preset-button'); + Util.deselect('preset-menu'); + Util.deselect('preset-button'); //set the text of the dropdown to the newly selected preset Util.setText('preset-button', presetName); @@ -41,8 +41,8 @@ const PresetModule = (() => { Util.toggle('preset-menu'); //close the palette menu - deselect('palette-button'); - deselect('palette-menu'); + Util.deselect('palette-button'); + Util.deselect('palette-menu'); e.stopPropagation(); }); diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 41ece01..d7f9f9a 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -3,7 +3,6 @@ //=include util/onChildren.js //=include util/onClick.js //=include util/onClickChildren.js -//=include util/select.js //=include util/hexToRgb.js //=include util/rgbToHex.js //=include util/rgbToHsl.js diff --git a/js/util/select.js b/js/util/select.js deleted file mode 100644 index e4b6664..0000000 --- a/js/util/select.js +++ /dev/null @@ -1,20 +0,0 @@ -//add class .selected to specified element -function select(elementId) { - //console.log(arguments.callee.caller.name, 'selected ', elementId); - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - element.classList.add('selected'); -} - -//remove .selected class from specified element -function deselect(elementId) { - //console.log('deselected ', elementId); - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - element.classList.remove('selected'); -} - -//toggle the status of the .selected class on the specified element -function toggle(elementId) { - //console.log('toggled ', elementId); - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - element.classList.toggle('selected'); -} \ No newline at end of file From f5807417ec0c137457682f8d7ad627757e3b0b49 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 11 Jul 2021 12:40:48 +0200 Subject: [PATCH 06/91] Added Color class - Added Color class to make color representation and convertions more uniform - Replaced standard convertions with Color.convertion - Removed _algorithms.js, _deleteColor.js, ajax.js and the other convertion files - Fixed bug in ColorModule, moved replaceAllOfColor to ColorModule as well as deleteColor --- js/Color.js | 169 ++++++++++++++++++++++++++++++++++ js/ColorModule.js | 114 ++++++++++++++++++++--- js/Util.js | 16 +++- js/_algorithms.js | 185 -------------------------------------- js/_colorPicker.js | 170 +++++++++++++---------------------- js/_createColorPalette.js | 27 +++--- js/_deleteColor.js | 84 ----------------- js/_history.js | 4 +- js/_jscolor.js | 9 +- js/_newPixel.js | 8 +- js/_replaceAllOfColor.js | 25 ------ js/pixel-editor.js | 8 +- js/util/ajax.js | 79 ---------------- js/util/hexToRgb.js | 21 ----- js/util/hslToRgb.js | 32 ------- js/util/rgbToHex.js | 23 ----- js/util/rgbToHsl.js | 36 -------- 17 files changed, 367 insertions(+), 643 deletions(-) create mode 100644 js/Color.js delete mode 100644 js/_algorithms.js delete mode 100644 js/_deleteColor.js delete mode 100644 js/util/ajax.js delete mode 100644 js/util/hexToRgb.js delete mode 100644 js/util/hslToRgb.js delete mode 100644 js/util/rgbToHex.js delete mode 100644 js/util/rgbToHsl.js diff --git a/js/Color.js b/js/Color.js new file mode 100644 index 0000000..9cf8c64 --- /dev/null +++ b/js/Color.js @@ -0,0 +1,169 @@ +// OPTIMIZABLE: add a normalize function that returns the normalized colour in the current +// format. +class Color { + constructor(fmt, v1, v2, v3, v4) { + this.fmt = fmt; + + switch (fmt) { + case 'hsv': + this.hsv = {h: v1, s: v2, v: v3}; + this.rgb = Color.hsvToRgb(this.hsv); + this.hsl = Color.rgbToHsl(this.rgb); + this.hex = Color.rgbToHex(this.rgb); + break; + case 'hsl': + this.hsl = {h: v1, s: v2, l: v3}; + this.rgb = Color.hslToRgb(this.hsl); + this.hsv = Color.rgbToHsv(this.rgb); + this.hex = Color.rgbToHex(this.rgb); + break; + case 'rgb': + this.rgb = {r: v1, g: v2, b: v3}; + this.hsl = Color.rgbToHsl(this.rgb); + this.hsv = Color.rgbToHsv(this.rgb); + this.hex = Color.rgbToHex(this.rgb); + break; + case 'hex': + this.hex = v1; + this.rgb = Color.hexToRgb(this.hex); + this.hsl = Color.rgbToHsl(this.rgb); + this.hsv = Color.rgbToHsv(this.rgb); + break; + default: + console.error("Unsupported color mode " + fmt); + break; + } + } + + static hexToRgb(hex, divisor) { + //if divisor isn't set, set it to one (so it has no effect) + divisor = divisor || 1; + //split given hex code into array of 3 values + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex.trim()); + + return result ? { + r: parseInt(result[1], 16)/divisor, + g: parseInt(result[2], 16)/divisor, + b: parseInt(result[3], 16)/divisor + } : null; + } + static rgbToHex(rgb) { + //convert a decimal number to 2-digit hex + function componentToHex (c) { + var hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; + } + + return componentToHex(rgb.r) + componentToHex(rgb.g) + componentToHex(rgb.b); + } + + static hslToRgb(hsl) { + var r, g, b; + var h = hsl.h, s = hsl.s, l = hsl.l; + + h /= 255; + s /= 255; + l /= 255; + + if(s == 0){ + r = g = b = l; // achromatic + }else{ + var hue2rgb = function hue2rgb(p, q, t){ + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return { + r:Math.round(r * 255), + g:Math.round(g * 255), + b:Math.round(b * 255) + }; + } + static rgbToHsl(rgb) { + var r, g, b; + r = rgb.r; g = rgb.g; b = rgb.b; + + r /= 255, g /= 255, b /= 255; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var hue, saturation, luminosity = (max + min) / 2; + + if(max == min){ + hue = saturation = 0; // achromatic + }else{ + var d = max - min; + saturation = luminosity > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max){ + case r: hue = (g - b) / d + (g < b ? 6 : 0); break; + case g: hue = (b - r) / d + 2; break; + case b: hue = (r - g) / d + 4; break; + } + hue /= 6; + } + + return {h:hue, s:saturation, l:luminosity}; + } + + static hsvToRgb(hsv) { + var r, g, b, h, s, v; + h = hsv.h; s = hsv.s; v = hsv.v; + + h /= 360; + s /= 100; + v /= 100; + + var i = Math.floor(h * 6); + var f = h * 6 - i; + var p = v * (1 - s); + var q = v * (1 - f * s); + var t = v * (1 - (1 - f) * s); + + switch (i % 6) { + case 0: r = v, g = t, b = p; break; + case 1: r = q, g = v, b = p; break; + case 2: r = p, g = v, b = t; break; + case 3: r = p, g = q, b = v; break; + case 4: r = t, g = p, b = v; break; + case 5: r = v, g = p, b = q; break; + } + + return {r: r * 255, g: g * 255, b: b * 255 }; + } + static rgbToHsv(rgb) { + let r = rgb.r, g = rgb.g, b = rgb.b; + r /= 255, g /= 255, b /= 255; + + let max = Math.max(r, g, b), min = Math.min(r, g, b); + let myH, myS, myV = max; + + let d = max - min; + myS = max == 0 ? 0 : d / max; + + if (max == min) { + myH = 0; // achromatic + } + else { + switch (max) { + case r: myH = (g - b) / d + (g < b ? 6 : 0); break; + case g: myH = (b - r) / d + 2; break; + case b: myH = (r - g) / d + 4; break; + } + + myH /= 6; + } + + return {h: myH * 360, s: myS * 100, v: myV * 100}; + } +} \ No newline at end of file diff --git a/js/ColorModule.js b/js/ColorModule.js index dceeb69..cd2f479 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -6,7 +6,6 @@ const ColorModule = (() => { const currentPalette = []; const coloursList = document.getElementById("palette-list"); - console.info("Initialized Color Module.."); document.getElementById('jscolor-hex-input').addEventListener('change',colorChanged, false); @@ -22,10 +21,12 @@ const ColorModule = (() => { // Changes all of one color to another after being changed from color picker function colorChanged(colorHexElement) { + console.log("Clicked:"); + console.log(colorHexElement); // Get old and new colors from the element const hexElement = colorHexElement.target; const hexElementValue = hexElement.value; - const newColor = hexToRgb(hexElementValue); + const newColor = Color.hexToRgb(hexElementValue); const oldColor = hexElement.oldColor; //if the color is not a valid hex color, exit this function and do nothing @@ -36,7 +37,7 @@ const ColorModule = (() => { newColor.a = 255; //save undo state - new HistoryStateEditColor(hexElementValue.toLowerCase(), rgbToHex(oldColor)); + new HistoryStateEditColor(hexElementValue.toLowerCase(), Color.rgbToHex(oldColor)); //get the currently selected color const currentlyEditedColor = document.getElementsByClassName('jscolor-active')[0]; @@ -73,7 +74,7 @@ const ColorModule = (() => { currentlyEditedColor.firstChild.jscolor.fromString(newColorHex); - replaceAllOfColor(oldColor, newColor); + ColorModule.replaceAllOfColor(oldColor, newColor); //set new old color to changed color hexElement.oldColor = newColor; @@ -82,7 +83,7 @@ const ColorModule = (() => { //if this is the current color, update the drawing color if (hexElement.colorElement.parentElement.classList.contains('selected')) { for (let i=1; i { function addColorButtonEvent() { //generate random color - const hue = Math.floor(Math.random()*255); - const sat = 130+Math.floor(Math.random()*100); - const lit = 70+Math.floor(Math.random()*100); - const newColorRgb = hslToRgb(hue,sat,lit); - const newColor = rgbToHex(newColorRgb.r,newColorRgb.g,newColorRgb.b); + const newColor = new Color("hsl", Math.floor(Math.random()*255), 130+Math.floor(Math.random()*100), 70+Math.floor(Math.random()*100)).hex; //remove current color selection document.querySelector('#colors-menu li.selected').classList.remove('selected'); @@ -183,13 +180,13 @@ const ColorModule = (() => { newEditButton = editButtonTemplate.cloneNode(true); listItem.appendChild(newEditButton); - newEditButton.addEventListener('click', (e,button) => { + newEditButton.addEventListener('click', () => { //hide edit button - button.parentElement.lastChild.classList.add('hidden'); + newEditButton.parentElement.lastChild.classList.add('hidden'); //show jscolor picker, if basic mode is enabled if (pixelEditorMode == 'Basic') - button.parentElement.firstChild.jscolor.show(); + newEditButton.parentElement.firstChild.jscolor.show(); else showDialogue("palette-block", false); }); @@ -197,9 +194,100 @@ const ColorModule = (() => { return listItem; } + function deleteColor (color) { + const logStyle = 'background: #913939; color: white; padding: 5px;'; + + //if color is a string, then find the corresponding button + if (typeof color === 'string') { + //console.log('trying to find ',color); + //get all colors in palette + colors = document.getElementsByClassName('color-button'); + + //loop through colors + for (var i = 0; i < colors.length; i++) { + //console.log(color,'=',colors[i].jscolor.toString()); + + if (color == colors[i].jscolor.toString()) { + //set color to the color button + color = colors[i]; + break; + } + } + + //if the color wasn't found + if (typeof color === 'string') { + //exit function + return; + } + } + + //hide color picker + color.jscolor.hide(); + + //find lightest color in palette + var colors = document.getElementsByClassName('color-button'); + var lightestColor = [0,null]; + for (var i = 0; i < colors.length; i++) { + + //get colors lightness + var lightness = Color.rgbToHsl(colors[i].jscolor.toRgb()).l; + + //if not the color we're deleting + if (colors[i] != color) { + + //if lighter than the current lightest, set as the new lightest + if (lightness > lightestColor[0]) { + lightestColor[0] = lightness; + lightestColor[1] = colors[i]; + } + } + } + + //replace deleted color with lightest color + ColorModule.replaceAllOfColor(color.jscolor.toString(),lightestColor[1].jscolor.toString()); + + //if the color you are deleting is the currently selected color + if (color.parentElement.classList.contains('selected')) { + //set current color TO LIGHTEST COLOR + lightestColor[1].parentElement.classList.add('selected'); + currentLayer.context.fillStyle = '#'+lightestColor[1].jscolor.toString(); + } + + //delete the element + colorsMenu.removeChild(color.parentElement); + } + + //replaces all of a single color on the canvas with a different color + //input two rgb color objects {r:0,g:0,b:0} + function replaceAllOfColor (oldColor, newColor) { + + //convert strings to objects if nessesary + if (typeof oldColor === 'string') oldColor = Color.hexToRgb(oldColor); + if (typeof newColor === 'string') newColor = Color.hexToRgb(newColor); + + //create temporary image from canvas to search through + var tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + + //loop through all pixels + for (var i=0;i 1) t -= 1; - if(t < 1/6) return p + (q - p) * 6 * t; - if(t < 1/2) return q; - if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; - return p; - } - - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1/3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1/3); - } - - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; -} - -function hsvToRgb(h, s, v) { - var r, g, b; - - h /= 360; - s /= 100; - v /= 100; - var i = Math.floor(h * 6); - var f = h * 6 - i; - var p = v * (1 - s); - var q = v * (1 - f * s); - var t = v * (1 - (1 - f) * s); - - switch (i % 6) { - case 0: r = v, g = t, b = p; break; - case 1: r = q, g = v, b = p; break; - case 2: r = p, g = v, b = t; break; - case 3: r = p, g = q, b = v; break; - case 4: r = t, g = p, b = v; break; - case 5: r = v, g = p, b = q; break; - } - - return [ r * 255, g * 255, b * 255 ]; -} - -function hslToHex(h, s, l) { - h /= 360; - s /= 100; - l /= 100; - let r, g, b; - if (s === 0) { - r = g = b = l; // achromatic - } else { - const hue2rgb = (p, q, t) => { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; - }; - const q = l < 0.5 ? l * (1 + s) : l + s - l * s; - const p = 2 * l - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - const toHex = x => { - const hex = Math.round(x * 255).toString(16); - return hex.length === 1 ? '0' + hex : hex; - }; - - return `${toHex(r)}${toHex(g)}${toHex(b)}`; -} - -function rgbToHsl(col) { - let r = col.r; - let g = col.g; - let b = col.b; - - r /= 255, g /= 255, b /= 255; - - let max = Math.max(r, g, b), min = Math.min(r, g, b); - let myH, myS, myL = (max + min) / 2; - - if (max == min) { - myH = myS = 0; // achromatic - } - else { - let d = max - min; - myS = myL > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: myH = (g - b) / d + (g < b ? 6 : 0); break; - case g: myH = (b - r) / d + 2; break; - case b: myH = (r - g) / d + 4; break; - } - - myH /= 6; - } - - return {h: myH, s: myS, l: myL }; -} - - function rgbToHsv(col) { - let r = col.r; - let g = col.g; - let b = col.b; - - r /= 255, g /= 255, b /= 255; - - let max = Math.max(r, g, b), min = Math.min(r, g, b); - let myH, myS, myV = max; - - let d = max - min; - myS = max == 0 ? 0 : d / max; - - if (max == min) { - myH = 0; // achromatic - } - else { - switch (max) { - case r: myH = (g - b) / d + (g < b ? 6 : 0); break; - case g: myH = (b - r) / d + 2; break; - case b: myH = (r - g) / d + 4; break; - } - - myH /= 6; - } - - return {h: myH, s: myS, v: myV}; - } - - function RGBtoCIELAB(rgbColour) { - // Convert to XYZ first via matrix transformation - let x = 0.412453 * rgbColour.r + 0.357580 * rgbColour.g + 0.180423 * rgbColour.b; - let y = 0.212671 * rgbColour.r + 0.715160 * rgbColour.g + 0.072169 * rgbColour.b; - let z = 0.019334 * rgbColour.r + 0.119193 * rgbColour.g + 0.950227 * rgbColour.b; - - let xFunc = CIELABconvF(x / referenceWhite.x); - let yFunc = CIELABconvF(y / referenceWhite.y); - let zFunc = CIELABconvF(z / referenceWhite.z); - - let myL = 116 * yFunc - 16; - let myA = 500 * (xFunc - yFunc); - let myB = 200 * (yFunc - zFunc); - - return {l: myL, a: myA, b: myB}; - -} -function CIELABconvF(value) { - if (value > Math.pow(6/29, 3)) { - return Math.cbrt(value); - } - - return 1/3 * Math.pow(6/29, 2) * value + 4/29; -} \ No newline at end of file diff --git a/js/_colorPicker.js b/js/_colorPicker.js index 007f204..8a4775d 100644 --- a/js/_colorPicker.js +++ b/js/_colorPicker.js @@ -71,26 +71,12 @@ function updateSliderValue (sliderIndex, updateMini = true) { // Update preview colour // get slider values sliderValues = getSlidersValues(); - // Generate preview colour - switch (currentPickerMode) { - case 'rgb': - hexColour = rgbToHex(sliderValues[0], sliderValues[1], sliderValues[2]); - break; - case 'hsv': - let tmpRgb = hsvToRgb(sliderValues[0], sliderValues[1], sliderValues[2]); - hexColour = rgbToHex(parseInt(tmpRgb[0]), parseInt(tmpRgb[1]), parseInt(tmpRgb[2])); - break; - case 'hsl': - hexColour = hslToHex(sliderValues[0], sliderValues[1], sliderValues[2]); - break; - default: - console.log("wtf select a decent picker mode"); - return; - } + hexColour = new Color(currentPickerMode, sliderValues[0], sliderValues[1], sliderValues[2]); + // Update preview colour div - colourPreview.style.backgroundColor = '#' + hexColour; - colourValue.value = '#' + hexColour; + colourPreview.style.backgroundColor = '#' + hexColour.hex; + colourValue.value = '#' + hexColour.hex; // Update sliders background // there's no other way than creating a custom css file, appending it to the head and @@ -270,6 +256,7 @@ function changePickerMode(target, newMode) { let colArray; let rgbTmp; let hexColour = colourValue.value.replace('#', ''); + let currColor = new Color("hex", hexColour); currentPickerMode = newMode; document.getElementsByClassName("cp-selected-mode")[0].classList.remove("cp-selected-mode"); @@ -309,30 +296,16 @@ function changePickerMode(target, newMode) { // Putting the current colour in the new slider switch(currentPickerMode) { case 'rgb': - colArray = hexToRgb(hexColour); + colArray = currColor.rgb; colArray = [colArray.r, colArray.g, colArray.b]; break; case 'hsv': - rgbTmp = hexToRgb(hexColour); - colArray = rgbToHsv(rgbTmp); - - colArray.h *= 360; - colArray.s *= 100; - colArray.v *= 100; - + colArray = currColor.hsv; colArray = [colArray.h, colArray.s, colArray.v]; - break; case 'hsl': - rgbTmp = hexToRgb(hexColour); - colArray = rgbToHsl(rgbTmp); - - colArray.h *= 360; - colArray.s *= 100; - colArray.l *= 100; - + colArray = currColor.hsl; colArray = [colArray.h, colArray.s, colArray.l]; - break; default: break; @@ -385,14 +358,14 @@ function movePickerIcon(event) { // Updates the main sliders given a hex value computed with the minipicker function updateSlidersByHex(hex, updateMini = true) { - let colour; + let colour = new Color("hex", hex); let mySliders = [sliders[0].getElementsByTagName("input")[0], sliders[1].getElementsByTagName("input")[0], sliders[2].getElementsByTagName("input")[0]]; switch (currentPickerMode) { case 'rgb': - colour = hexToRgb(hex); + colour = colour.rgb; mySliders[0].value = colour.r; mySliders[1].value = colour.g; @@ -400,7 +373,7 @@ function updateSlidersByHex(hex, updateMini = true) { break; case 'hsv': - colour = rgbToHsv(hexToRgb(hex)); + colour = colour.hsv; mySliders[0].value = colour.h * 360; mySliders[1].value = colour.s * 100; @@ -408,7 +381,7 @@ function updateSlidersByHex(hex, updateMini = true) { break; case 'hsl': - colour = rgbToHsl(hexToRgb(hex)); + colour = colour.hsl; mySliders[0].value = colour.h * 360; mySliders[1].value = colour.s * 100; @@ -445,7 +418,7 @@ function getCursorPosMinipicker(e) { // Updates the minipicker given a hex computed by the main sliders // Moves the cursor function updatePickerByHex(hex) { - let hsv = rgbToHsv(hexToRgb(hex)); + let hsv = new Color("hex", hex).hsv; let xPos = miniPickerCanvas.width * hsv.h - 8; let yPos = miniPickerCanvas.height * hsv.s + 8; @@ -471,15 +444,15 @@ function updatePickerByHex(hex) { // Fired when the value of the minislider changes: updates the spectrum gradient and the hex colour function miniSliderInput(event) { - let newHex; - let newHsv = rgbToHsv(hexToRgb(getMiniPickerColour())); + let currColor = new Color("hex", getMiniPickerColour()); + let newHex = currColor.hex; + let newHsv = currColor.hsv; let rgb; // Adding slider value to value newHsv.v = parseInt(event.target.value); // Updating hex - rgb = hsvToRgb(newHsv.h * 360, newHsv.s * 100, newHsv.v); - newHex = rgbToHex(Math.round(rgb[0]), Math.round(rgb[1]), Math.round(rgb[2])); + newHex = Color.rgbToHex(Color.hsvToRgb(newHsv)); colourValue.value = newHex; @@ -504,20 +477,17 @@ function updateMiniPickerColour() { // Returns the current colour of the minipicker function getMiniPickerColour() { - let hex; let pickedColour; pickedColour = miniPickerCanvas.getContext('2d').getImageData(currPickerIconPos[0][0] + 8, currPickerIconPos[0][1] + 8, 1, 1).data; - hex = rgbToHex(pickedColour[0], pickedColour[1], pickedColour[2]); - - return hex; + return new Color("rgb", pickedColour[0], pickedColour[1], pickedColour[2]).hex; } // Update the background gradient of the slider in the minipicker function updateMiniSlider(hex) { - let rgb = hexToRgb(hex); + let rgb = Color.hexToRgb(hex); styles[1] = "input[type=range]#cp-minipicker-slider::-webkit-slider-runnable-track { background: rgb(2,0,36);"; styles[1] += "background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(0,0,0,1) 0%, " + @@ -530,11 +500,9 @@ function updateMiniSlider(hex) { // Updates the gradient of the spectrum canvas in the minipicker function updateMiniPickerSpectrum() { let ctx = miniPickerCanvas.getContext('2d'); - let hsv = rgbToHsv(hexToRgb(colourValue.value)); + let hsv = new Color("hex", colourValue.value).hsv; let tmp; - let white = {h:hsv.h * 360, s:0, v: parseInt(miniPickerSlider.value)}; - - white = hsvToRgb(white.h, white.s, white.v); + let white = new Color("hsv", hsv.h, 0, parseInt(miniPickerSlider.value)).rgb; ctx.clearRect(0, 0, miniPickerCanvas.width, miniPickerCanvas.height); @@ -542,20 +510,16 @@ function updateMiniPickerSpectrum() { var hGrad = ctx.createLinearGradient(0, 0, miniPickerCanvas.width, 0); for (let i=0; i<7; i++) { - tmp = hsvToRgb(60 * i, 100, hsv.v * 100); - hGrad.addColorStop(i / 6, '#' + rgbToHex(Math.round(tmp[0]), Math.round(tmp[1]), Math.round(tmp[2]))); + let stopHex = new Color("hsv", 60*i, 100, hsv.v); + hGrad.addColorStop(i / 6, '#' + stopHex.hex); } ctx.fillStyle = hGrad; ctx.fillRect(0, 0, miniPickerCanvas.width, miniPickerCanvas.height); // Drawing sat / lum var vGrad = ctx.createLinearGradient(0, 0, 0, miniPickerCanvas.height); - vGrad.addColorStop(0, 'rgba(' + white[0] +',' + white[1] + ',' + white[2] + ',0)'); - /* - vGrad.addColorStop(0.1, 'rgba(255,255,255,0)'); - vGrad.addColorStop(0.9, 'rgba(255,255,255,1)'); - */ - vGrad.addColorStop(1, 'rgba(' + white[0] +',' + white[1] + ',' + white[2] + ',1)'); + vGrad.addColorStop(0, 'rgba(' + white.r +',' + white.g + ',' + white.b + ',0)'); + vGrad.addColorStop(1, 'rgba(' + white.r +',' + white.g + ',' + white.b + ',1)'); ctx.fillStyle = vGrad; ctx.fillRect(0, 0, miniPickerCanvas.width, miniPickerCanvas.height); @@ -649,89 +613,77 @@ function changePickingMode(event, newMode) { } function updateOtherIcons() { - let currentColorHex = colourValue.value; - let currentColourHsv = rgbToHsv(hexToRgb(currentColorHex)); - let newColourHsv = {h:currentColourHsv.h, s:currentColourHsv.s, v:currentColourHsv.v}; + let currentColorHex = new Color("hex", colourValue.value).hex; + let currentColourHsv = new Color("hex", currentColorHex).hsv; + let newColourHsv; let newColourHexes = ['', '', '']; let tmpRgb; - // Salvo tutti i - switch (currentPickingMode) { case 'mono': break; case 'analog': // First colour - newColourHsv.h = (((currentColourHsv.h*360 + 40) % 360) / 360); + newColourHsv = new Color("hsv", ((currentColourHsv.h + 40) % 360), currentColourHsv.s, currentColourHsv.v); - currPickerIconPos[1][0] = miniPickerCanvas.width * newColourHsv.h - 8; - currPickerIconPos[1][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.s + 8); + currPickerIconPos[1][0] = miniPickerCanvas.width * newColourHsv.hsv.h/360 - 8; + currPickerIconPos[1][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.hsv.s/100 + 8); - tmpRgb = hsvToRgb(newColourHsv.h*360, newColourHsv.s*100, newColourHsv.v*100); - newColourHexes[0] = rgbToHex(Math.round(tmpRgb[0]), Math.round(tmpRgb[1]), Math.round(tmpRgb[2])); + newColourHexes[0] = newColourHsv.hex; // Second colour - newColourHsv.h = (((currentColourHsv.h*360 - 40) % 360) / 360); - if (newColourHsv.h < 0) { - newColourHsv.h += 1; - } + newColourHsv.h = new Color("hsv", ((currentColourHsv.h + 320) % 360), currentColourHsv.s, currentColourHsv.v); - currPickerIconPos[2][0] = miniPickerCanvas.width * newColourHsv.h - 8; + currPickerIconPos[2][0] = miniPickerCanvas.width * newColourHsv.hsv.h/360 - 8; currPickerIconPos[2][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.s + 8); - - tmpRgb = hsvToRgb(newColourHsv.h*360, newColourHsv.s*100, newColourHsv.v*100); - newColourHexes[1] = rgbToHex(Math.round(tmpRgb[0]), Math.round(tmpRgb[1]), Math.round(tmpRgb[2])); + + newColourHexes[1] = newColourHsv.hex; break; case 'cmpt': - newColourHsv.h = (((currentColourHsv.h*360 + 180) % 360) / 360); + newColourHsv = new Color("hsv", ((currentColourHsv.h + 180) % 360), currentColourHsv.s, currentColourHsv.v); - currPickerIconPos[1][0] = miniPickerCanvas.width * newColourHsv.h - 8; - currPickerIconPos[1][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.s + 8); - - tmpRgb = hsvToRgb(newColourHsv.h*360, newColourHsv.s*100, newColourHsv.v*100); - newColourHexes[0] = rgbToHex(Math.round(tmpRgb[0]), Math.round(tmpRgb[1]), Math.round(tmpRgb[2])); + currPickerIconPos[1][0] = miniPickerCanvas.width * newColourHsv.hsv.h/360 - 8; + currPickerIconPos[1][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.hsv.s/100 + 8); + + newColourHexes[0] = newColourHsv.hex; break; case 'tri': for (let i=1; i< 3; i++) { - newColourHsv.h = (((currentColourHsv.h*360 + 120*i) % 360) / 360); + newColourHsv = new Color("hsv", (currentColourHsv.h + 120*i) % 360, currentColourHsv.s, currentColourHsv.v); - currPickerIconPos[i][0] = miniPickerCanvas.width * newColourHsv.h - 8; - currPickerIconPos[i][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.s + 8); - - tmpRgb = hsvToRgb(newColourHsv.h*360, newColourHsv.s*100, newColourHsv.v*100); - newColourHexes[i - 1] = rgbToHex(Math.round(tmpRgb[0]), Math.round(tmpRgb[1]), Math.round(tmpRgb[2])); + currPickerIconPos[i][0] = miniPickerCanvas.width * newColourHsv.hsv.h/360 - 8; + currPickerIconPos[i][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.hsv.s/100 + 8); + + newColourHexes[i - 1] = newColourHsv.hex; } break case 'scmpt': // First colour - newColourHsv.h = (((currentColourHsv.h*360 + 210) % 360) / 360); + newColourHsv = new Color("hsv", (currentColourHsv.h + 210) % 360, currentColourHsv.s, currentColourHsv.v); - currPickerIconPos[1][0] = miniPickerCanvas.width * newColourHsv.h - 8; - currPickerIconPos[1][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.s + 8); - - tmpRgb = hsvToRgb(newColourHsv.h*360, newColourHsv.s*100, newColourHsv.v*100); - newColourHexes[0] = rgbToHex(Math.round(tmpRgb[0]), Math.round(tmpRgb[1]), Math.round(tmpRgb[2])); + currPickerIconPos[1][0] = miniPickerCanvas.width * newColourHsv.hsv.h/360 - 8; + currPickerIconPos[1][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.hsv.s/100 + 8); + + newColourHexes[0] = newColourHsv.hex; // Second colour - newColourHsv.h = (((currentColourHsv.h*360 + 150) % 360) / 360); + newColourHsv = new Color("hsv", (currentColourHsv.h + 150) % 360, currentColourHsv.s, currentColourHsv.v); - currPickerIconPos[2][0] = miniPickerCanvas.width * newColourHsv.h - 8; - currPickerIconPos[2][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.s + 8); - - tmpRgb = hsvToRgb(newColourHsv.h*360, newColourHsv.s*100, newColourHsv.v*100); - newColourHexes[1] = rgbToHex(Math.round(tmpRgb[0]), Math.round(tmpRgb[1]), Math.round(tmpRgb[2])); + currPickerIconPos[2][0] = miniPickerCanvas.width * newColourHsv.hsv.h/360 - 8; + currPickerIconPos[2][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.hsv.s/100 + 8); + + newColourHexes[1] = newColourHsv.hex; break; case 'tetra': for (let i=1; i< 4; i++) { - newColourHsv.h = (((currentColourHsv.h*360 + 90*i) % 360) / 360); + newColourHsv = new Color("hsv", (currentColourHsv.h + 90*i) % 360, currentColourHsv.s, currentColourHsv.v); - currPickerIconPos[i][0] = miniPickerCanvas.width * newColourHsv.h - 8; - currPickerIconPos[i][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.s + 8); - - tmpRgb = hsvToRgb(newColourHsv.h*360, newColourHsv.s*100, newColourHsv.v*100); - newColourHexes[i - 1] = rgbToHex(Math.round(tmpRgb[0]), Math.round(tmpRgb[1]), Math.round(tmpRgb[2])); + currPickerIconPos[i][0] = miniPickerCanvas.width * newColourHsv.hsv.h/360 - 8; + currPickerIconPos[i][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.hsv.s/100 + 8); + + newColourHexes[i - 1] = newColourHsv.hex; } break; default: diff --git a/js/_createColorPalette.js b/js/_createColorPalette.js index b6ac473..e0303fb 100644 --- a/js/_createColorPalette.js +++ b/js/_createColorPalette.js @@ -14,22 +14,22 @@ function createColorPalette(paletteColors, deletePreviousPalette = true) { } } - var lightestColor = '#000000'; - var darkestColor = '#ffffff'; + var lightestColor = new Color("hex", '#000000'); + var darkestColor = new Color("hex", '#ffffff'); // Adding all the colours in the array for (var i = 0; i < paletteColors.length; i++) { - var newColor = paletteColors[i]; - var newColorElement = ColorModule.addColor(newColor); + var newColor = new Color("hex", paletteColors[i]); + var newColorElement = ColorModule.addColor(newColor.hex); - var newColorHex = hexToRgb(newColor); + var newColRgb = newColor.rgb; - var lightestColorHex = hexToRgb(lightestColor); - if (newColorHex.r + newColorHex.g + newColorHex.b > lightestColorHex.r + lightestColorHex.g + lightestColorHex.b) + var lightestColorRgb = lightestColor.rgb; + if (newColRgb.r + newColRgb.g + newColRgb.b > lightestColorRgb.r + lightestColorRgb.g + lightestColorRgb.b) lightestColor = newColor; - var darkestColorHex = hexToRgb(darkestColor); - if (newColorHex.r + newColorHex.g + newColorHex.b < darkestColorHex.r + darkestColorHex.g + darkestColorHex.b) { + var darkestColorRgb = darkestColor.rgb; + if (newColRgb.r + newColRgb.g + newColRgb.b < darkestColorRgb.r + darkestColorRgb.g + darkestColorRgb.b) { //remove current color selection var selectedColor = document.querySelector('#colors-menu li.selected'); @@ -37,16 +37,15 @@ function createColorPalette(paletteColors, deletePreviousPalette = true) { //set as current color newColorElement.classList.add('selected'); - darkestColor = newColor; } } //prepend # if not present - if (!darkestColor.includes('#')) darkestColor = '#' + darkestColor; + if (!darkestColor.hex.includes('#')) darkestColor.hex = '#' + darkestColor.hex; //set as current color - currentLayer.context.fillStyle = darkestColor; + currentLayer.context.fillStyle = darkestColor.hex; } /** Creates the palette with the colours used in all the layers @@ -65,7 +64,7 @@ function createPaletteFromLayers() { let color = imageData[j]+','+imageData[j + 1]+','+imageData[j + 2]; if (!colors[color]) { - colors[color] = {r:imageData[j],g:imageData[j + 1],b:imageData[j + 2]}; + colors[color] = new Color("rgb", imageData[j], imageData[j + 1], imageData[j + 2]).rgb; //don't allow more than 256 colors to be added if (Object.keys(colors).length >= settings.maxColorsOnImportedImage) { @@ -82,7 +81,7 @@ function createPaletteFromLayers() { let colorPaletteArray = []; for (let color in colors) { if (colors.hasOwnProperty(color)) { - colorPaletteArray.push('#'+rgbToHex(colors[color])); + colorPaletteArray.push('#'+Color.rgbToHex(colors[color])); } } diff --git a/js/_deleteColor.js b/js/_deleteColor.js deleted file mode 100644 index 7656d30..0000000 --- a/js/_deleteColor.js +++ /dev/null @@ -1,84 +0,0 @@ - - -//called when the delete button is pressed on color picker -//input color button or hex string -function deleteColor (color) { - const logStyle = 'background: #913939; color: white; padding: 5px;'; - - //console.log('%c'+'deleting color', logStyle); - - //if color is a string, then find the corresponding button - if (typeof color === 'string') { - //console.log('trying to find ',color); - //get all colors in palette - colors = document.getElementsByClassName('color-button'); - - //loop through colors - for (var i = 0; i < colors.length; i++) { - //console.log(color,'=',colors[i].jscolor.toString()); - - if (color == colors[i].jscolor.toString()) { - //console.log('match'); - //set color to the color button - color = colors[i]; - //console.log('found color', color); - - //exit loop - break; - } - } - - //if the color wasn't found - if (typeof color === 'string') { - //console.log('color not found'); - //exit function - return; - } - - } - - //hide color picker - color.jscolor.hide(); - - - //find lightest color in palette - var colors = document.getElementsByClassName('color-button'); - var lightestColor = [0,null]; - for (var i = 0; i < colors.length; i++) { - - //get colors lightness - var lightness = rgbToHsl(colors[i].jscolor.toRgb()).l; - //console.log('%c'+lightness, logStyle) - - //if not the color we're deleting - if (colors[i] != color) { - - //if lighter than the current lightest, set as the new lightest - if (lightness > lightestColor[0]) { - lightestColor[0] = lightness; - lightestColor[1] = colors[i]; - } - } - } - - //console.log('%c'+'replacing with lightest color: '+lightestColor[1].jscolor.toString(), logStyle) - - //replace deleted color with lightest color - replaceAllOfColor(color.jscolor.toString(),lightestColor[1].jscolor.toString()); - - - //if the color you are deleting is the currently selected color - if (color.parentElement.classList.contains('selected')) { - //console.log('%c'+'deleted color is currently selected', logStyle); - - //set current color TO LIGHTEST COLOR - lightestColor[1].parentElement.classList.add('selected'); - currentLayer.context.fillStyle = '#'+lightestColor[1].jscolor.toString(); - } - - //delete the element - colorsMenu.removeChild(color.parentElement); - - - -} diff --git a/js/_history.js b/js/_history.js index 6898080..52d6bfb 100644 --- a/js/_history.js +++ b/js/_history.js @@ -379,7 +379,7 @@ function HistoryStateAddColor (colorValue) { this.undo = function () { redoStates.push(this); - deleteColor(this.colorValue); + ColorModule.deleteColor(this.colorValue); }; this.redo = function () { @@ -410,7 +410,7 @@ function HistoryStateDeleteColor (colorValue) { var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); currentLayer.context.putImageData(this.canvas, 0, 0); - deleteColor(this.colorValue); + ColorModule.deleteColor(this.colorValue); this.canvas = currentCanvas; undoStates.push(this); diff --git a/js/_jscolor.js b/js/_jscolor.js index 2cbf910..e201f0a 100644 --- a/js/_jscolor.js +++ b/js/_jscolor.js @@ -553,7 +553,7 @@ if (!window.jscolor) { window.jscolor = (function () { //saveHistoryState({type: 'deletecolor', colorValue: jsc.picker.owner.toString(), canvas: canvas.context.getImageData(0, 0, canvasSize[0], canvasSize[1])}); new HistoryStateDeleteColor(jsc.picker.owner.toString()); - deleteColor(jsc.picker.owner.styleElement); + ColorModule.deleteColor(jsc.picker.owner.styleElement); } else if (e.target.className == 'jscolor-picker-bottom') { //console.log('clicked color picker bottom') @@ -1071,12 +1071,9 @@ if (!window.jscolor) { window.jscolor = (function () { this.hide = function () { ///console.log(this.styleElement) if (isPickerOwner()) { - - //console.log('color picker hidden') - //set the color to old color, in case the color is a duplicate that hasn't been resolved yet [lospec] var hexInput = document.getElementById('jscolor-hex-input'); - var oldColor = '#'+rgbToHex(hexInput.oldColor); + var oldColor = '#'+Color.rgbToHex(hexInput.oldColor); this.fromString(oldColor); document.getElementById('duplicate-color-warning').style.visibility = 'hidden'; @@ -1105,7 +1102,7 @@ if (!window.jscolor) { window.jscolor = (function () { this.exportColor(); //set old color for updating colors on canvas - hexInput.oldColor = hexToRgb(hexInput.value); + hexInput.oldColor = Color.hexToRgb(hexInput.value); //set the color element to the clicked button hexInput.colorElement = this.styleElement; diff --git a/js/_newPixel.js b/js/_newPixel.js index 592fdbd..e28eca4 100644 --- a/js/_newPixel.js +++ b/js/_newPixel.js @@ -117,12 +117,12 @@ function newPixel (width, height, editorMode, fileContent = null) { history.pushState(null, null, '/pixel-editor'); //generate default colors - var fg = hslToRgb(Math.floor(Math.random()*255), 230,70); - var bg = hslToRgb(Math.floor(Math.random()*255), 230,170); + var fg = new Color("hsl", Math.floor(Math.random()*255), 230,70).rgb; + var bg = new Color("hsl", Math.floor(Math.random()*255), 230,170).rgb; //convert colors to hex - var defaultForegroundColor = rgbToHex(fg.r,fg.g,fg.b); - var defaultBackgroundColor = rgbToHex(bg.r,bg.g,bg.b); + var defaultForegroundColor = Color.rgbToHex(fg); + var defaultBackgroundColor = Color.rgbToHex(bg); //add colors to palette ColorModule.addColor(defaultForegroundColor).classList.add('selected'); diff --git a/js/_replaceAllOfColor.js b/js/_replaceAllOfColor.js index 4ae8c44..e69de29 100644 --- a/js/_replaceAllOfColor.js +++ b/js/_replaceAllOfColor.js @@ -1,25 +0,0 @@ -//replaces all of a single color on the canvas with a different color -//input two rgb color objects {r:0,g:0,b:0} -function replaceAllOfColor (oldColor, newColor) { - - //convert strings to objects if nessesary - if (typeof oldColor === 'string') oldColor = hexToRgb(oldColor); - if (typeof newColor === 'string') newColor = hexToRgb(newColor); - - //create temporary image from canvas to search through - var tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - - //loop through all pixels - for (var i=0;i 1) t -= 1; - if(t < 1/6) return p + (q - p) * 6 * t; - if(t < 1/2) return q; - if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; - return p; - } - - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1/3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1/3); - } - - return { - r:Math.round(r * 255), - g:Math.round(g * 255), - b:Math.round(b * 255) - }; -} \ No newline at end of file diff --git a/js/util/rgbToHex.js b/js/util/rgbToHex.js deleted file mode 100644 index 2ef8f73..0000000 --- a/js/util/rgbToHex.js +++ /dev/null @@ -1,23 +0,0 @@ -//convert rgb values to a hex string for html -function rgbToHex (argument0,g,b) { - var r; - - //if the first argument is an object - if (typeof argument0 === 'object'){ - r = argument0.r; - g = argument0.g; - b = argument0.b; - } - else - r = argument0; - - //console.log('converting rgb('+r+','+g+','+b+') to hex'); - - //convert a decimal number to 2-digit hex - function componentToHex (c) { - var hex = c.toString(16); - return hex.length == 1 ? "0" + hex : hex; - } - - return componentToHex(r) + componentToHex(g) + componentToHex(b); -} diff --git a/js/util/rgbToHsl.js b/js/util/rgbToHsl.js deleted file mode 100644 index c915732..0000000 --- a/js/util/rgbToHsl.js +++ /dev/null @@ -1,36 +0,0 @@ -//put in red green blue values and get out hue saturation luminosity values - -function rgbToHsl(argument0, g, b){ - var r; - - //if the first argument is an object - if (typeof argument0 === 'object'){ - r = argument0.r; - g = argument0.g; - b = argument0.b; - } - else - r = argument0; - - - - r /= 255, g /= 255, b /= 255; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var hue, saturation, luminosity = (max + min) / 2; - - if(max == min){ - hue = saturation = 0; // achromatic - }else{ - var d = max - min; - saturation = luminosity > 0.5 ? d / (2 - max - min) : d / (max + min); - switch(max){ - case r: hue = (g - b) / d + (g < b ? 6 : 0); break; - case g: hue = (b - r) / d + 2; break; - case b: hue = (r - g) / d + 4; break; - } - hue /= 6; - } - - return {h:hue, s:saturation, l:luminosity}; -} From 1daeb81ef4ba884ee1a00d8396207aa099beb5a7 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 11 Jul 2021 12:53:50 +0200 Subject: [PATCH 07/91] Fixed bug that caused the wrong colour to be modified with jscolor --- js/ColorModule.js | 10 +++++----- js/_layer.js | 3 --- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/js/ColorModule.js b/js/ColorModule.js index cd2f479..16e99a7 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -22,7 +22,7 @@ const ColorModule = (() => { // Changes all of one color to another after being changed from color picker function colorChanged(colorHexElement) { console.log("Clicked:"); - console.log(colorHexElement); + console.log(colorHexElement.target); // Get old and new colors from the element const hexElement = colorHexElement.target; const hexElementValue = hexElement.value; @@ -31,7 +31,7 @@ const ColorModule = (() => { //if the color is not a valid hex color, exit this function and do nothing const newColorHex = hexElementValue.toLowerCase(); - if (/^[0-9a-f]{6}$/i.test(newColorHex) == false) return + if (/^[0-9a-f]{6}$/i.test(newColorHex) == false) return; currentPalette.splice(currentPalette.indexOf("#" + newColor), 1); newColor.a = 255; @@ -180,13 +180,13 @@ const ColorModule = (() => { newEditButton = editButtonTemplate.cloneNode(true); listItem.appendChild(newEditButton); - newEditButton.addEventListener('click', () => { + newEditButton.addEventListener('click', (event) => { //hide edit button - newEditButton.parentElement.lastChild.classList.add('hidden'); + event.target.parentElement.lastChild.classList.add('hidden'); //show jscolor picker, if basic mode is enabled if (pixelEditorMode == 'Basic') - newEditButton.parentElement.firstChild.jscolor.show(); + event.target.parentElement.firstChild.jscolor.show(); else showDialogue("palette-block", false); }); diff --git a/js/_layer.js b/js/_layer.js index d18a8e8..7ad32ca 100644 --- a/js/_layer.js +++ b/js/_layer.js @@ -318,14 +318,11 @@ function flatten(onlyVisible) { let nToFlatten = 0; for (let i=0; i (a.canvas.style.zIndex > b.canvas.style.zIndex) ? -1 : 1); // Selecting the last visible layer (the only one that won't get deleted) From 84f6493bf6c338c56e3eb1edf2c76d28d511ec6a Mon Sep 17 00:00:00 2001 From: Leamsi Escribano Date: Sun, 11 Jul 2021 11:32:49 -0400 Subject: [PATCH 08/91] Fixed Color Picker preview not showing --- js/Color.js | 47 ++++++++++++++++++++++++---------------------- js/_loadPalette.js | 3 ++- js/_mouseEvents.js | 11 +++++++---- js/_tools.js | 5 ----- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/js/Color.js b/js/Color.js index 9cf8c64..2c9e3df 100644 --- a/js/Color.js +++ b/js/Color.js @@ -39,7 +39,7 @@ class Color { //if divisor isn't set, set it to one (so it has no effect) divisor = divisor || 1; //split given hex code into array of 3 values - var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex.trim()); + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex.trim()); return result ? { r: parseInt(result[1], 16)/divisor, @@ -49,17 +49,20 @@ class Color { } static rgbToHex(rgb) { //convert a decimal number to 2-digit hex - function componentToHex (c) { - var hex = c.toString(16); - return hex.length == 1 ? "0" + hex : hex; - } - - return componentToHex(rgb.r) + componentToHex(rgb.g) + componentToHex(rgb.b); + let hex = ""; + Object.values(rgb).forEach((color) => { + let colorToString = color.toString(16); + if (colorToString.length === 1) { + colorToString = "0" + colorToString; + } + hex += colorToString; + }); + return hex; } static hslToRgb(hsl) { - var r, g, b; - var h = hsl.h, s = hsl.s, l = hsl.l; + let r, g, b; + let h = hsl.h, s = hsl.s, l = hsl.l; h /= 255; s /= 255; @@ -68,7 +71,7 @@ class Color { if(s == 0){ r = g = b = l; // achromatic }else{ - var hue2rgb = function hue2rgb(p, q, t){ + const hue2rgb = function hue2rgb(p, q, t){ if(t < 0) t += 1; if(t > 1) t -= 1; if(t < 1/6) return p + (q - p) * 6 * t; @@ -77,8 +80,8 @@ class Color { return p; } - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; r = hue2rgb(p, q, h + 1/3); g = hue2rgb(p, q, h); @@ -92,18 +95,18 @@ class Color { }; } static rgbToHsl(rgb) { - var r, g, b; + let r, g, b; r = rgb.r; g = rgb.g; b = rgb.b; r /= 255, g /= 255, b /= 255; - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var hue, saturation, luminosity = (max + min) / 2; + const max = Math.max(r, g, b), min = Math.min(r, g, b); + let hue, saturation, luminosity = (max + min) / 2; if(max == min){ hue = saturation = 0; // achromatic }else{ - var d = max - min; + const d = max - min; saturation = luminosity > 0.5 ? d / (2 - max - min) : d / (max + min); switch(max){ case r: hue = (g - b) / d + (g < b ? 6 : 0); break; @@ -117,18 +120,18 @@ class Color { } static hsvToRgb(hsv) { - var r, g, b, h, s, v; + let r, g, b, h, s, v; h = hsv.h; s = hsv.s; v = hsv.v; h /= 360; s /= 100; v /= 100; - var i = Math.floor(h * 6); - var f = h * 6 - i; - var p = v * (1 - s); - var q = v * (1 - f * s); - var t = v * (1 - (1 - f) * s); + const i = Math.floor(h * 6); + const f = h * 6 - i; + const p = v * (1 - s); + const q = v * (1 - f * s); + const t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; diff --git a/js/_loadPalette.js b/js/_loadPalette.js index d7bda53..e7534e1 100644 --- a/js/_loadPalette.js +++ b/js/_loadPalette.js @@ -28,7 +28,8 @@ document.getElementById('load-palette-browse-holder').addEventListener('change', //loop through pixels looking for colors to add to palette for (var i = 0; i < imagePixelData.length; i += 4) { - var color = '#'+rgbToHex(imagePixelData[i],imagePixelData[i + 1],imagePixelData[i + 2]); + const newColor = {r:imagePixelData[i],g:imagePixelData[i + 1],b:imagePixelData[i + 2]}; + var color = '#' + Color.rgbToHex(newColor); if (colorPalette.indexOf(color) == -1) { colorPalette.push(color); } diff --git a/js/_mouseEvents.js b/js/_mouseEvents.js index 33e6d66..cb019ae 100644 --- a/js/_mouseEvents.js +++ b/js/_mouseEvents.js @@ -90,7 +90,8 @@ window.addEventListener("mouseup", function (mouseEvent) { if (currentTool.name == 'eyedropper' && mouseEvent.target.className == 'drawingCanvas') { var cursorLocation = getCursorPosition(mouseEvent); var selectedColor = getEyedropperColor(cursorLocation); - var newColor = rgbToHex(selectedColor[0],selectedColor[1],selectedColor[2]); + const rgbColor = {r:selectedColor[0],g:selectedColor[1],b:selectedColor[2]}; + var newColor = Color.rgbToHex(rgbColor); currentGlobalColor = "#" + newColor; @@ -306,15 +307,17 @@ function draw (mouseEvent) { } } else if (currentTool.name == 'eyedropper' && dragging && mouseEvent.target.className == 'drawingCanvas') { - let selectedColor = getEyedropperColor(cursorLocation); - eyedropperPreview.style.borderColor = '#'+rgbToHex(selectedColor[0],selectedColor[1],selectedColor[2]); + const selectedColor = getEyedropperColor(cursorLocation); + const rgbColor = {r:selectedColor[0],g:selectedColor[1],b:selectedColor[2]}; + + eyedropperPreview.style.borderColor = '#' + Color.rgbToHex(rgbColor); eyedropperPreview.style.display = 'block'; eyedropperPreview.style.left = cursorLocation[0] + currentLayer.canvas.offsetLeft - 30 + 'px'; eyedropperPreview.style.top = cursorLocation[1] + currentLayer.canvas.offsetTop - 30 + 'px'; - var colorLightness = Math.max(selectedColor[0],selectedColor[1],selectedColor[2]); + const colorLightness = Math.max(selectedColor[0],selectedColor[1],selectedColor[2]); //for the darkest 50% of colors, change the eyedropper preview to dark mode if (colorLightness>127) eyedropperPreview.classList.remove('dark'); diff --git a/js/_tools.js b/js/_tools.js index a6d374d..5ea2d0c 100644 --- a/js/_tools.js +++ b/js/_tools.js @@ -76,11 +76,6 @@ class Tool { brushPreview.style.width = this.currentBrushSize * zoom + 'px'; brushPreview.style.height = this.currentBrushSize * zoom + 'px'; } - - //show / hide eyedropper color preview - if (this.eyedropperPreview) eyedropperPreview.style.display = 'block'; - else eyedropperPreview.style.display = 'none'; - //moveSelection if (currentTool.name == 'moveselection') { if (cursorInSelectedArea()) { From 6072528ad239025f8ea266ad9f7dbab5b61aa549 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 11 Jul 2021 23:27:48 +0200 Subject: [PATCH 09/91] Fixed advanced colour picker bugs --- js/Color.js | 24 ++++++++++-------------- js/_colorPicker.js | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/js/Color.js b/js/Color.js index 2c9e3df..e2ee851 100644 --- a/js/Color.js +++ b/js/Color.js @@ -48,25 +48,21 @@ class Color { } : null; } static rgbToHex(rgb) { - //convert a decimal number to 2-digit hex - let hex = ""; - Object.values(rgb).forEach((color) => { - let colorToString = color.toString(16); - if (colorToString.length === 1) { - colorToString = "0" + colorToString; - } - hex += colorToString; - }); - return hex; + function componentToHex (c) { + var hex = Math.round(c).toString(16); + return hex.length == 1 ? "0" + hex : hex.substring(0, 2); + } + + return componentToHex(rgb.r) + componentToHex(rgb.g) + componentToHex(rgb.b); } static hslToRgb(hsl) { let r, g, b; let h = hsl.h, s = hsl.s, l = hsl.l; - h /= 255; - s /= 255; - l /= 255; + h /= 360; + s /= 100; + l /= 100; if(s == 0){ r = g = b = l; // achromatic @@ -116,7 +112,7 @@ class Color { hue /= 6; } - return {h:hue, s:saturation, l:luminosity}; + return {h:hue*360, s:saturation*100, l:luminosity*100}; } static hsvToRgb(hsv) { diff --git a/js/_colorPicker.js b/js/_colorPicker.js index 8a4775d..9bad37a 100644 --- a/js/_colorPicker.js +++ b/js/_colorPicker.js @@ -419,10 +419,10 @@ function getCursorPosMinipicker(e) { // Moves the cursor function updatePickerByHex(hex) { let hsv = new Color("hex", hex).hsv; - let xPos = miniPickerCanvas.width * hsv.h - 8; - let yPos = miniPickerCanvas.height * hsv.s + 8; + let xPos = miniPickerCanvas.width * hsv.h/360 - 8; + let yPos = miniPickerCanvas.height * hsv.s/100 + 8; - miniPickerSlider.value = hsv.v * 100; + miniPickerSlider.value = hsv.v; currPickerIconPos[0][0] = xPos; currPickerIconPos[0][1] = miniPickerCanvas.height - yPos; @@ -445,14 +445,13 @@ function updatePickerByHex(hex) { // Fired when the value of the minislider changes: updates the spectrum gradient and the hex colour function miniSliderInput(event) { let currColor = new Color("hex", getMiniPickerColour()); - let newHex = currColor.hex; let newHsv = currColor.hsv; - let rgb; + let newHex; // Adding slider value to value - newHsv.v = parseInt(event.target.value); + newHsv = new Color("hsv", newHsv.h, newHsv.s, parseInt(event.target.value)); // Updating hex - newHex = Color.rgbToHex(Color.hsvToRgb(newHsv)); + newHex = newHsv.hex; colourValue.value = newHex; @@ -465,6 +464,7 @@ function updateMiniPickerColour() { let hex = getMiniPickerColour(); activePickerIcon.style.backgroundColor = '#' + hex; + console.log("Mini picker col: #" + hex); // Update hex and sliders based on hex colourValue.value = '#' + hex; @@ -482,7 +482,7 @@ function getMiniPickerColour() { pickedColour = miniPickerCanvas.getContext('2d').getImageData(currPickerIconPos[0][0] + 8, currPickerIconPos[0][1] + 8, 1, 1).data; - return new Color("rgb", pickedColour[0], pickedColour[1], pickedColour[2]).hex; + return new Color("rgb", Math.round(pickedColour[0]), Math.round(pickedColour[1]), Math.round(pickedColour[2])).hex; } // Update the background gradient of the slider in the minipicker @@ -501,7 +501,7 @@ function updateMiniSlider(hex) { function updateMiniPickerSpectrum() { let ctx = miniPickerCanvas.getContext('2d'); let hsv = new Color("hex", colourValue.value).hsv; - let tmp; + console.log("Spectrum hex: " + new Color("hex", colourValue.value).hex); let white = new Color("hsv", hsv.h, 0, parseInt(miniPickerSlider.value)).rgb; ctx.clearRect(0, 0, miniPickerCanvas.width, miniPickerCanvas.height); @@ -633,10 +633,10 @@ function updateOtherIcons() { newColourHexes[0] = newColourHsv.hex; // Second colour - newColourHsv.h = new Color("hsv", ((currentColourHsv.h + 320) % 360), currentColourHsv.s, currentColourHsv.v); + newColourHsv = new Color("hsv", ((currentColourHsv.h + 320) % 360), currentColourHsv.s, currentColourHsv.v); currPickerIconPos[2][0] = miniPickerCanvas.width * newColourHsv.hsv.h/360 - 8; - currPickerIconPos[2][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.s + 8); + currPickerIconPos[2][1] = miniPickerCanvas.height - (miniPickerCanvas.height * newColourHsv.hsv.s/100 + 8); newColourHexes[1] = newColourHsv.hex; break; From 4457d2178cdf1ebbb83c79e8621f49aaddc93b4f Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Mon, 12 Jul 2021 11:36:30 +0200 Subject: [PATCH 10/91] Added Input.js Got rid of the "on" files, refactored the rest of the code to use the functions declared in Input.js --- js/Input.js | 26 +++++++++++++++++++++++ js/_createButton.js | 4 ++-- js/_editorMode.js | 4 ++-- js/_fileMenu.js | 2 +- js/_layer.js | 2 +- js/_settings.js | 2 +- js/_toolButtons.js | 43 ++++++++++++++++++-------------------- js/pixel-editor.js | 5 +---- js/util/on.js | 22 ------------------- js/util/onChildren.js | 14 ------------- js/util/onClick.js | 9 -------- js/util/onClickChildren.js | 13 ------------ 12 files changed, 54 insertions(+), 92 deletions(-) create mode 100644 js/Input.js delete mode 100644 js/util/on.js delete mode 100644 js/util/onChildren.js delete mode 100644 js/util/onClick.js delete mode 100644 js/util/onClickChildren.js diff --git a/js/Input.js b/js/Input.js new file mode 100644 index 0000000..3725b3d --- /dev/null +++ b/js/Input.js @@ -0,0 +1,26 @@ +class Input { + static on(event, elementId, functionCallback, ...args) { + //if element provided is string, get the actual element + const element = Util.getElement(elementId); + + element.addEventListener(event, + function (e) { + // e = event + //this = element clicked + functionCallback(e, this, args); + //if you need to access the event or this variable, you need to add them + //when you define the callback, but you cant use the word this, eg: + //on('click', menuButton, function (e, button) {}); + }); + } + + static onChildren(event, parentElement, functionCallback, ...args) { + parentElement = Util.getElement(parentElement); + const children = parentElement.children; + + //loop through children and add onClick listener + for (var i = 0; i < children.length; i++) { + on(event, children[i], functionCallback, args); + } + } +} \ No newline at end of file diff --git a/js/_createButton.js b/js/_createButton.js index d0f516d..c7b92d2 100644 --- a/js/_createButton.js +++ b/js/_createButton.js @@ -37,7 +37,7 @@ function create(isSplash) { /** Triggered when the "Create" button in the new pixel dialogue is pressed * */ -on('click', 'create-button', function (){ +Input.on('click', 'create-button', function (){ console.log("Here"); // Getting the values of the form var width = Util.getValue('size-width'); @@ -70,7 +70,7 @@ on('click', 'create-button', function (){ /** Triggered when the "Create" button in the new pixel dialogue is pressed * */ -on('click', 'create-button-splash', function (){ + Input.on('click', 'create-button-splash', function (){ // Getting the values of the form var width = Util.getValue('size-width-splash'); var height = Util.getValue('size-height-splash'); diff --git a/js/_editorMode.js b/js/_editorMode.js index 9d98cf2..6fab5b3 100644 --- a/js/_editorMode.js +++ b/js/_editorMode.js @@ -7,7 +7,7 @@ let modes = { } } -on('click', 'switch-editor-mode-splash', function (e) { +Input.on('click', 'switch-editor-mode-splash', function (e) { console.log('switching mode') switchMode(); }); @@ -69,6 +69,6 @@ function switchMode(mustConfirm = true) { } } -on('click', 'switch-mode-button', function (e) { +Input.on('click', 'switch-mode-button', function (e) { switchMode(); }); diff --git a/js/_fileMenu.js b/js/_fileMenu.js index 59ad06e..301c14a 100644 --- a/js/_fileMenu.js +++ b/js/_fileMenu.js @@ -8,7 +8,7 @@ for (var i = 1; i < mainMenuItems.length; i++) { var menuButton = menuItem.children[0]; //when you click a main menu items button - on('click', menuButton, function (e, button) { + Input.on('click', menuButton, function (e, button) { Util.select(button.parentElement); }); diff --git a/js/_layer.js b/js/_layer.js index 7ad32ca..0787620 100644 --- a/js/_layer.js +++ b/js/_layer.js @@ -24,7 +24,7 @@ let oldLayerName = null; let dragStartLayer; // Binding the add layer button to the function -on('click',"add-layer-button", addLayer, false); +Input.on('click',"add-layer-button", addLayer, false); /** Handler class for a single canvas (a single layer) * diff --git a/js/_settings.js b/js/_settings.js index 22df17d..0b61465 100644 --- a/js/_settings.js +++ b/js/_settings.js @@ -26,7 +26,7 @@ else{ console.log(settings); //on clicking the save button in the settings dialog -on('click', 'save-settings', saveSettings); +Input.on('click', 'save-settings', saveSettings); function saveSettings() { //check if values are valid diff --git a/js/_toolButtons.js b/js/_toolButtons.js index 32faf91..fe726a2 100644 --- a/js/_toolButtons.js +++ b/js/_toolButtons.js @@ -1,38 +1,38 @@ //pencil -on('click',"pencil-button", function(){ +Input.on('click',"pencil-button", function(){ tool.pencil.switchTo(); }, false); //pencil bigger -on('click',"pencil-bigger-button", function(){ +Input.on('click',"pencil-bigger-button", function(){ tool.pencil.brushSize++; }, false); //pencil smaller -on('click',"pencil-smaller-button", function(){ +Input.on('click',"pencil-smaller-button", function(){ if(tool.pencil.brushSize > 1) tool.pencil.brushSize--; }, false); //eraser -on('click',"eraser-button", function(){ +Input.on('click',"eraser-button", function(){ console.log("selecting eraser"); tool.eraser.switchTo(); }, false); //eraser bigger -on('click',"eraser-bigger-button", function(){ +Input.on('click',"eraser-bigger-button", function(){ tool.eraser.brushSize++; }, false); //eraser smaller -on('click',"eraser-smaller-button", function(e){ +Input.on('click',"eraser-smaller-button", function(e){ if(tool.eraser.brushSize > 1) tool.eraser.brushSize--; }, false); // rectangle -on('click','rectangle-button', function(e){ +Input.on('click','rectangle-button', function(e){ // If the user clicks twice on the button, they change the draw mode if (currentTool.name == 'rectangle') { if (rectangleDrawMode == 'empty') { @@ -50,7 +50,7 @@ on('click','rectangle-button', function(e){ }, false); // ellipse -on('click','ellipse-button', function(e){ +Input.on('click','ellipse-button', function(e){ // If the user clicks twice on the button, they change the draw mode if (currentTool.name == 'ellipse') { if (ellipseDrawMode == 'empty') { @@ -68,60 +68,57 @@ on('click','ellipse-button', function(e){ }, false); // rectangle bigger -on('click',"rectangle-bigger-button", function(){ +Input.on('click',"rectangle-bigger-button", function(){ tool.rectangle.brushSize++; }, false); // rectangle smaller -on('click',"rectangle-smaller-button", function(e){ +Input.on('click',"rectangle-smaller-button", function(e){ if(tool.rectangle.brushSize > 1) tool.rectangle.brushSize--; }, false); // ellipse bigger -on('click',"ellipse-bigger-button", function(){ +Input.on('click',"ellipse-bigger-button", function(){ tool.ellipse.brushSize++; }, false); // ellipse smaller -on('click',"ellipse-smaller-button", function(e){ +Input.on('click',"ellipse-smaller-button", function(e){ if(tool.ellipse.brushSize > 1) tool.ellipse.brushSize--; }, false); //fill -on('click',"fill-button", function(){ +Input.on('click',"fill-button", function(){ tool.fill.switchTo(); }, false); //pan -on('click',"pan-button", function(){ +Input.on('click',"pan-button", function(){ tool.pan.switchTo(); }, false); //eyedropper -on('click',"eyedropper-button", function(){ +Input.on('click',"eyedropper-button", function(){ tool.eyedropper.switchTo(); }, false); //rectangular selection button -on('click', "rectselect-button", function(){ +Input.on('click', "rectselect-button", function(){ tool.rectselect.switchTo(); }, false); //line -on('click',"line-button", function(){ +Input.on('click',"line-button", function(){ tool.line.switchTo(); }, false); -on('click',"line-bigger-button", function(){ +Input.on('click',"line-bigger-button", function(){ tool.line.brushSize++; }, false); -on('click',"line-smaller-button", function(){ +Input.on('click',"line-smaller-button", function(){ if(tool.line.brushSize > 1) tool.line.brushSize--; -}, false); - - -/*global on */ +}, false); \ No newline at end of file diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 383bb3f..a5176ad 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -1,12 +1,9 @@ /**utilities**/ -//=include util/on.js -//=include util/onChildren.js -//=include util/onClick.js -//=include util/onClickChildren.js //=include lib/cookies.js //=include _pixelEditorUtility.js //=include lib/sortable.js //=include Util.js +//=include Input.js //=include Color.js /**init**/ diff --git a/js/util/on.js b/js/util/on.js deleted file mode 100644 index 8eba088..0000000 --- a/js/util/on.js +++ /dev/null @@ -1,22 +0,0 @@ -//add event listener for any element which calls a function -//element can be provided as a direct reference or with just a string of the name - -function on(event, elementId, functionCallback) { - - - - //if element provided is string, get the actual element - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - - //console.log('added '+event+' event listener on '+element) - - element.addEventListener(event, - function (e) { - // e = event - //this = element clicked - functionCallback(e, this); - //if you need to access the event or this variable, you need to add them - //when you define the callback, but you cant use the word this, eg: - //on('click', menuButton, function (e, button) {}); - }); -} \ No newline at end of file diff --git a/js/util/onChildren.js b/js/util/onChildren.js deleted file mode 100644 index 4ad6f16..0000000 --- a/js/util/onChildren.js +++ /dev/null @@ -1,14 +0,0 @@ -//add event listener to each of specified element's children - -function onChildren(event, parentElement, functionCallback) { - console.log('onChildren()'); - - var parentElement = (typeof parentElement == 'string' ? document.getElementById(parentElement) : parentElement); - - var children = parentElement.children; - - //loop through children and add onClick listener - for (var i = 0; i < children.length; i++) { - on(event, children[i],functionCallback); - } -} \ No newline at end of file diff --git a/js/util/onClick.js b/js/util/onClick.js deleted file mode 100644 index f70c671..0000000 --- a/js/util/onClick.js +++ /dev/null @@ -1,9 +0,0 @@ -//DEPRECATED - USE on('click') - - -//add click event listener for any element which calls a function -//element can be provided as a direct reference or with just a string of the name -function onClick(elementId, functionCallback) { - var element = (typeof elementId == 'string' ? document.getElementById(elementId) : elementId); - element.addEventListener('click',functionCallback); -} \ No newline at end of file diff --git a/js/util/onClickChildren.js b/js/util/onClickChildren.js deleted file mode 100644 index a4b073a..0000000 --- a/js/util/onClickChildren.js +++ /dev/null @@ -1,13 +0,0 @@ -//add click listener to each of specified element's children - -function onClickChildren(parentElement, functionCallback) { - - var parentElement = (typeof parentElement == 'string' ? document.getElementById(parentElement) : parentElement); - - var children = parentElement.children; - - //loop through children and add onClick listener - for (var i = 0; i < children.length; i++) { - onClick(children[i],functionCallback); - } -} \ No newline at end of file From 53d51c4567e3d11d9dbe97215c9155b8fa23baba Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Tue, 13 Jul 2021 22:23:05 +0200 Subject: [PATCH 11/91] Fixed colour generation when creating a new pixel --- js/_newPixel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/_newPixel.js b/js/_newPixel.js index e28eca4..a9283e4 100644 --- a/js/_newPixel.js +++ b/js/_newPixel.js @@ -117,8 +117,8 @@ function newPixel (width, height, editorMode, fileContent = null) { history.pushState(null, null, '/pixel-editor'); //generate default colors - var fg = new Color("hsl", Math.floor(Math.random()*255), 230,70).rgb; - var bg = new Color("hsl", Math.floor(Math.random()*255), 230,170).rgb; + var fg = new Color("hsv", Math.floor(Math.random()*360), 50, 50).rgb; + var bg = new Color("hsv", Math.floor(Math.random()*360), 80, 100).rgb; //convert colors to hex var defaultForegroundColor = Color.rgbToHex(fg); From 85db99a7c1e4d49936cd59fc812848f6f8112df4 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Tue, 13 Jul 2021 22:27:29 +0200 Subject: [PATCH 12/91] Moved clickedColor to ColorModule --- js/ColorModule.js | 30 +++++++++++++++++++++++++++++- js/_clickedColor.js | 29 ----------------------------- js/pixel-editor.js | 1 - 3 files changed, 29 insertions(+), 31 deletions(-) delete mode 100644 js/_clickedColor.js diff --git a/js/ColorModule.js b/js/ColorModule.js index 16e99a7..62c409f 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -89,9 +89,37 @@ const ColorModule = (() => { } } + function clickedColor (e){ + + //left clicked color + if (e.which == 1) { + // remove current color selection + var selectedColor = document.querySelector('#colors-menu li.selected'); + if (selectedColor) selectedColor.classList.remove('selected'); + + //set current color + for (let i=1; i Date: Tue, 13 Jul 2021 22:35:06 +0200 Subject: [PATCH 13/91] Fixed colour generation when adding a new one --- js/ColorModule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ColorModule.js b/js/ColorModule.js index 62c409f..f197056 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -119,7 +119,7 @@ const ColorModule = (() => { function addColorButtonEvent() { //generate random color - const newColor = new Color("hsl", Math.floor(Math.random()*360), 50+Math.floor(Math.random()*50), 50+Math.floor(Math.random()*50)).hex; + const newColor = new Color("hsv", Math.floor(Math.random()*360), Math.floor(Math.random()*100), Math.floor(Math.random()*100)).hex; //remove current color selection document.querySelector('#colors-menu li.selected').classList.remove('selected'); From 87ab2da6b5198adb7e96768bdb5e39f61673b0ce Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Tue, 13 Jul 2021 22:59:05 +0200 Subject: [PATCH 14/91] Commented ColorModule --- js/ColorModule.js | 69 +++++++++++++++++++++++++++------------- js/_dialogue.js | 2 +- views/settings-popup.hbs | 2 +- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/js/ColorModule.js b/js/ColorModule.js index f197056..884c24e 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -1,17 +1,19 @@ -/** Adds the given color to the palette +/** ColorModule holds the functions used to implement the basic-mode palette. * - * @param {*} newColor the colour to add - * @return the list item containing the added colour */ const ColorModule = (() => { + // Array containing the colours of the current palette const currentPalette = []; + // Reference to the HTML palette const coloursList = document.getElementById("palette-list"); + // Binding events to callbacks console.info("Initialized Color Module.."); document.getElementById('jscolor-hex-input').addEventListener('change',colorChanged, false); document.getElementById('jscolor-hex-input').addEventListener('input', colorChanged, false); document.getElementById('add-color-button').addEventListener('click', addColorButtonEvent, false); + // Making the colours in the HTML menu sortable new Sortable(document.getElementById("colors-menu"), { animation:100, filter: ".noshrink", @@ -19,10 +21,12 @@ const ColorModule = (() => { onEnd: makeIsDraggingFalse }); - // Changes all of one color to another after being changed from color picker + /** Changes all of one color to another after being changed from the color picker + * + * @param {*} colorHexElement The element that has been changed + * @returns + */ function colorChanged(colorHexElement) { - console.log("Clicked:"); - console.log(colorHexElement.target); // Get old and new colors from the element const hexElement = colorHexElement.target; const hexElementValue = hexElement.value; @@ -48,7 +52,6 @@ const ColorModule = (() => { //loop through all colors in palette for (var i = 0; i < colors.length; i++) { - //if generated color matches this color if (newColorHex == colors[i].jscolor.toString()) { //if the color isnt the one that has the picker currently open @@ -89,8 +92,11 @@ const ColorModule = (() => { } } + /** Callback triggered when the user clicks on a colour in the palette menu on the right + * + * @param {*} e The event that triggered the callback + */ function clickedColor (e){ - //left clicked color if (e.which == 1) { // remove current color selection @@ -106,17 +112,19 @@ const ColorModule = (() => { //make color selected e.target.parentElement.classList.add('selected'); - } else if (e.which == 3) { //right clicked color - //console.log('right clicked color button'); - + } + //right clicked color + else if (e.which == 3) { //hide edit color button (to prevent it from showing) e.target.parentElement.lastChild.classList.add('hidden'); - //show color picker e.target.jscolor.show(); } } + /** Called whenever the user presses the button used to add a new colour to the palette + * + */ function addColorButtonEvent() { //generate random color const newColor = new Color("hsv", Math.floor(Math.random()*360), Math.floor(Math.random()*100), Math.floor(Math.random()*100)).hex; @@ -130,7 +138,6 @@ const ColorModule = (() => { currentLayer.context.fillStyle = '#' + newColor; //add history state - //saveHistoryState({type: 'addcolor', colorValue: addedColor.firstElementChild.jscolor.toString()}); new HistoryStateAddColor(addedColor.firstElementChild.jscolor.toString()); //show color picker @@ -141,7 +148,11 @@ const ColorModule = (() => { addedColor.lastChild.classList.add('hidden'); } - function AddToSimplePalette() { + /** Adds the colors that have been added through the advanced-mode color picker to the + * basic-mode palette. + * + */ + function addToSimplePalette() { const simplePalette = document.getElementById("colors-menu"); const childCount = simplePalette.childElementCount; @@ -162,7 +173,11 @@ const ColorModule = (() => { } } } - //formats a color button + + /** Initializes jscolor for the element passed as a parameter + * + * @param {*} colorElement The element of which we need to setup jscolor + */ function initColor (colorElement) { //add jscolor picker for this color colorElement.jscolor = new jscolor(colorElement.parentElement, { @@ -181,6 +196,11 @@ const ColorModule = (() => { } + /** Adds a color to the palette + * + * @param {*} newColor The color to add in hex format + * @returns The HTML palette item that has been created + */ function addColor (newColor) { //add # at beginning if not present if (newColor.charAt(0) != '#') @@ -222,12 +242,16 @@ const ColorModule = (() => { return listItem; } + /** Deletes a color from the palette + * + * @param {*} color A string in hex format or the HTML element corresponding to the color + * that should be removed. + */ function deleteColor (color) { const logStyle = 'background: #913939; color: white; padding: 5px;'; //if color is a string, then find the corresponding button if (typeof color === 'string') { - //console.log('trying to find ',color); //get all colors in palette colors = document.getElementsByClassName('color-button'); @@ -285,8 +309,11 @@ const ColorModule = (() => { colorsMenu.removeChild(color.parentElement); } - //replaces all of a single color on the canvas with a different color - //input two rgb color objects {r:0,g:0,b:0} + /** Replaces all of a single color on the canvas with a different color + * + * @param {*} oldColor Old colour in {r,g,b} object format + * @param {*} newColor New colour in {r,g,b} object format + */ function replaceAllOfColor (oldColor, newColor) { //convert strings to objects if nessesary @@ -316,8 +343,6 @@ const ColorModule = (() => { addColor, deleteColor, replaceAllOfColor, - AddToSimplePalette + addToSimplePalette } -})(); - -console.log("Color module: " + ColorModule); \ No newline at end of file +})(); \ No newline at end of file diff --git a/js/_dialogue.js b/js/_dialogue.js index 5b183b9..e0f23d0 100644 --- a/js/_dialogue.js +++ b/js/_dialogue.js @@ -43,7 +43,7 @@ function closeDialogue () { dialogueOpen = false; if (currentOpenDialogue == "palette-block") { - ColorModule.AddToSimplePalette(); + ColorModule.addToSimplePalette(); } } diff --git a/views/settings-popup.hbs b/views/settings-popup.hbs index a283ec3..159e64c 100644 --- a/views/settings-popup.hbs +++ b/views/settings-popup.hbs @@ -5,7 +5,7 @@

History

- +

Pixel grid

From e4ecc3d6077c8e5ecb2a9fe47eab06b1d0874304 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Tue, 13 Jul 2021 23:40:23 +0200 Subject: [PATCH 15/91] Moved dialogue related things to their own IIFE Refactored all calls to showDialogue and closeDialogue to use the IIFE version --- js/Dialogue.js | 77 +++++++++++++++++++++++++++++++++++++++ js/_createButton.js | 2 +- js/_createColorPalette.js | 2 +- js/_dialogue.js | 64 -------------------------------- js/_featuresLog.js | 2 +- js/_fileMenu.js | 10 ++--- js/_newPixel.js | 2 +- js/_onLoad.js | 6 +-- js/_resizeCanvas.js | 4 +- js/_resizeSprite.js | 4 +- js/_settings.js | 2 +- js/_variables.js | 1 - js/pixel-editor.js | 2 +- views/main-menu.hbs | 2 +- 14 files changed, 96 insertions(+), 84 deletions(-) create mode 100644 js/Dialogue.js delete mode 100644 js/_dialogue.js diff --git a/js/Dialogue.js b/js/Dialogue.js new file mode 100644 index 0000000..98a89cf --- /dev/null +++ b/js/Dialogue.js @@ -0,0 +1,77 @@ +/** Handles the pop up windows (NewPixel, ResizeCanvas ecc) + * + */ +const Dialogue = (() => { + let currentOpenDialogue = ""; + const popUpContainer = document.getElementById("pop-up-container"); + const cancelButtons = popUpContainer.getElementsByClassName('close-button'); + + // Add click handlers for all cancel buttons + for (var i = 0; i < cancelButtons.length; i++) { + cancelButtons[i].addEventListener('click', function () { + closeDialogue(); + }); + } + + /** Closes a dialogue window if the user clicks everywhere but in the current window + * + */ + popUpContainer.addEventListener('click', function (e) { + if (e.target == popUpContainer) + closeDialogue(); + }); + + /** Shows the dialogue window called dialogueName, which is a child of pop-up-container in pixel-editor.hbs + * + * @param {*} dialogueName The name of the window to show + * @param {*} trackEvent Should I track the GA event? + */ + function showDialogue (dialogueName, trackEvent) { + if (typeof trackEvent === 'undefined') trackEvent = true; + + // Updating currently open dialogue + currentOpenDialogue = dialogueName; + // The pop up window is open + dialogueOpen = true; + // Showing the pop up container + popUpContainer.style.display = 'block'; + + // Showing the window + document.getElementById(dialogueName).style.display = 'block'; + + // If I'm opening the palette window, I initialize the colour picker + if (dialogueName == 'palette-block' && documentCreated) { + cpInit(); + pbInit(); + } + + //track google event + if (trackEvent) + ga('send', 'event', 'Palette Editor Dialogue', dialogueName); /*global ga*/ + } + + /** Closes the current dialogue by hiding the window and the pop-up-container + * + */ + function closeDialogue () { + popUpContainer.style.display = 'none'; + var popups = popUpContainer.children; + + for (var i = 0; i < popups.length; i++) { + popups[i].style.display = 'none'; + } + + dialogueOpen = false; + + if (currentOpenDialogue == "palette-block") { + ColorModule.addToSimplePalette(); + } + } + + return { + showDialogue, + closeDialogue + } +})(); + +console.log("Dialog: " + Dialogue); \ No newline at end of file diff --git a/js/_createButton.js b/js/_createButton.js index c7b92d2..59c25a4 100644 --- a/js/_createButton.js +++ b/js/_createButton.js @@ -67,7 +67,7 @@ Input.on('click', 'create-button', function (){ Util.setText('preset-button', 'Choose a preset...'); }); -/** Triggered when the "Create" button in the new pixel dialogue is pressed +/** Triggered when the "Create" button in the splash page is pressed * */ Input.on('click', 'create-button-splash', function (){ diff --git a/js/_createColorPalette.js b/js/_createColorPalette.js index e0303fb..6e65755 100644 --- a/js/_createColorPalette.js +++ b/js/_createColorPalette.js @@ -1,5 +1,5 @@ -/** Creates the colour palette +/** Creates the colour palette when starting up the editor from _newPixel.js * * @param {*} paletteColors The colours of the palette * @param {*} deletePreviousPalette Tells if the app should delete the previous palette or not diff --git a/js/_dialogue.js b/js/_dialogue.js deleted file mode 100644 index e0f23d0..0000000 --- a/js/_dialogue.js +++ /dev/null @@ -1,64 +0,0 @@ -let currentOpenDialogue = ""; - -/** Shows the dialogue window called dialogueName, which is a child of pop-up-container in pixel-editor.hbs - * - * @param {*} dialogueName The name of the window to show - * @param {*} trackEvent Should I track the GA event? - */ -function showDialogue (dialogueName, trackEvent) { - if (typeof trackEvent === 'undefined') trackEvent = true; - - // Updating currently open dialogue - currentOpenDialogue = dialogueName; - // The pop up window is open - dialogueOpen = true; - // Showing the pop up container - popUpContainer.style.display = 'block'; - - // Showing the window - document.getElementById(dialogueName).style.display = 'block'; - - // If I'm opening the palette window, I initialize the colour picker - if (dialogueName == 'palette-block' && documentCreated) { - cpInit(); - pbInit(); - } - - //track google event - if (trackEvent) - ga('send', 'event', 'Palette Editor Dialogue', dialogueName); /*global ga*/ -} - -/** Closes the current dialogue by hiding the window and the pop-up-container - * - */ -function closeDialogue () { - popUpContainer.style.display = 'none'; - var popups = popUpContainer.children; - - for (var i = 0; i < popups.length; i++) { - popups[i].style.display = 'none'; - } - - dialogueOpen = false; - - if (currentOpenDialogue == "palette-block") { - ColorModule.addToSimplePalette(); - } -} - -/** Closes a dialogue window if the user clicks everywhere but in the current window - * - */ -popUpContainer.addEventListener('click', function (e) { - if (e.target == popUpContainer) - closeDialogue(); -}); - -//add click handlers for all cancel buttons -var cancelButtons = popUpContainer.getElementsByClassName('close-button'); -for (var i = 0; i < cancelButtons.length; i++) { - cancelButtons[i].addEventListener('click', function () { - closeDialogue(); - }); -} diff --git a/js/_featuresLog.js b/js/_featuresLog.js index 5fd6b89..a1a18e4 100644 --- a/js/_featuresLog.js +++ b/js/_featuresLog.js @@ -1 +1 @@ -showDialogue("splash", false); \ No newline at end of file +Dialogue.showDialogue("splash", false); \ No newline at end of file diff --git a/js/_fileMenu.js b/js/_fileMenu.js index 301c14a..912c917 100644 --- a/js/_fileMenu.js +++ b/js/_fileMenu.js @@ -27,7 +27,7 @@ for (var i = 1; i < mainMenuItems.length; i++) { //File Menu case 'New': - showDialogue('new-pixel'); + Dialogue.showDialogue('new-pixel'); break; case 'Save project': //create name @@ -169,17 +169,17 @@ for (var i = 1; i < mainMenuItems.length; i++) { //fill form with current settings values Util.setValue('setting-numberOfHistoryStates', settings.numberOfHistoryStates); - showDialogue('settings'); + Dialogue.showDialogue('settings'); break; //Help Menu case 'Help': - showDialogue('help'); + Dialogue.showDialogue('help'); break; case 'About': - showDialogue('about'); + Dialogue.showDialogue('about'); break; case 'Changelog': - showDialogue('changelog'); + Dialogue.showDialogue('changelog'); break; } diff --git a/js/_newPixel.js b/js/_newPixel.js index a9283e4..fd43952 100644 --- a/js/_newPixel.js +++ b/js/_newPixel.js @@ -143,7 +143,7 @@ function newPixel (width, height, editorMode, fileContent = null) { redoStates = []; // Closing the "New Pixel dialogue" - closeDialogue(); + Dialogue.closeDialogue(); // Updating the cursor of the current tool currentTool.updateCursor(); diff --git a/js/_onLoad.js b/js/_onLoad.js index 90d8367..b0acdc2 100644 --- a/js/_onLoad.js +++ b/js/_onLoad.js @@ -14,7 +14,7 @@ window.onload = function () { console.log('no url parameters were found'); //show splash screen - showDialogue('splash', false); + Dialogue.showDialogue('splash', false); } //url parameters were specified @@ -53,7 +53,7 @@ window.onload = function () { //dimentions were not specified -- show splash screen with palette preselected else { //show splash - showDialogue('new-pixel', false); + Dialogue.showDialogue('new-pixel', false); } }) @@ -62,7 +62,7 @@ window.onload = function () { console.warn('failed to load palette "'+paletteSlug+'"', error); //proceed to splash screen - showDialogue('splash', false); + Dialogue.showDialogue('splash', false); }); } }; \ No newline at end of file diff --git a/js/_resizeCanvas.js b/js/_resizeCanvas.js index faa6641..8880450 100644 --- a/js/_resizeCanvas.js +++ b/js/_resizeCanvas.js @@ -15,7 +15,7 @@ let rcBorders = {left: 0, right: 0, top: 0, bottom: 0}; function openResizeCanvasWindow() { // Initializes the inputs initResizeCanvasInputs(); - showDialogue('resize-canvas'); + Dialogue.showDialogue('resize-canvas'); } /** Initializes the canvas resizing input @@ -201,7 +201,7 @@ function resizeCanvas(event, size, customData, saveHistory = true) { } } - closeDialogue(); + Dialogue.closeDialogue(); } /** Trims the canvas so tat the sprite is perfectly contained in it diff --git a/js/_resizeSprite.js b/js/_resizeSprite.js index 93067b4..20d4b97 100644 --- a/js/_resizeSprite.js +++ b/js/_resizeSprite.js @@ -32,7 +32,7 @@ function openResizeSpriteWindow() { startData.widthPercentage = 100; // Opening the pop up now that it's ready - showDialogue('resize-sprite'); + Dialogue.showDialogue('resize-sprite'); } /** Initalizes the input values and binds the elements to their events @@ -152,7 +152,7 @@ function resizeSprite(event, ratio) { startData.widthPercentage = 100; startData.heightPercentage = 100; - closeDialogue(); + Dialogue.closeDialogue(); } /* Trust me, the math for the functions below works. If you want to optimize them feel free to have a look, though */ diff --git a/js/_settings.js b/js/_settings.js index 0b61465..a8ca87a 100644 --- a/js/_settings.js +++ b/js/_settings.js @@ -46,5 +46,5 @@ function saveSettings() { Cookies.set('pixelEditorSettings', cookieValue, { expires: Infinity }); //close window - closeDialogue(); + Dialogue.closeDialogue(); } \ No newline at end of file diff --git a/js/_variables.js b/js/_variables.js index 41bf84b..d837f0a 100644 --- a/js/_variables.js +++ b/js/_variables.js @@ -13,7 +13,6 @@ var eyedropperPreview = document.getElementById("eyedropper-preview"); var canvasView = document.getElementById("canvas-view"); var colors = document.getElementsByClassName("color-button"); var colorsMenu = document.getElementById("colors-menu"); -var popUpContainer = document.getElementById("pop-up-container"); // main canvas var canvas = document.getElementById('pixel-canvas'); diff --git a/js/pixel-editor.js b/js/pixel-editor.js index a868817..43fefe3 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -5,6 +5,7 @@ //=include Util.js //=include Input.js //=include Color.js +//=include Dialogue.js /**init**/ //=include _consts.js @@ -23,7 +24,6 @@ //=include _createColorPalette.js //=include _changeZoom.js //=include ColorModule.js -//=include _dialogue.js //!=include _featuresLog.js //=include _drawLine.js //=include _getCursorPosition.js diff --git a/views/main-menu.hbs b/views/main-menu.hbs index 0b31a8a..60013c3 100644 --- a/views/main-menu.hbs +++ b/views/main-menu.hbs @@ -52,7 +52,7 @@
  • -
  • +
From 6c8ec8e7a9208ae2ddcd579756a4e0d89bccfbc1 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Wed, 14 Jul 2021 22:20:55 +0200 Subject: [PATCH 16/91] Refactored History into an IIFE Divided History states and actual History management, refactored all occurrences of history-related functions to use the new version. --- js/ColorModule.js | 4 +- js/History.js | 484 ++++++++++++++++++++++++++++++++++++++ js/_fileMenu.js | 4 +- js/_fill.js | 2 +- js/_history.js | 529 ------------------------------------------ js/_hotkeyListener.js | 10 +- js/_jscolor.js | 2 +- js/_layer.js | 14 +- js/_mouseEvents.js | 2 +- js/_move.js | 2 +- js/_rectSelect.js | 2 +- js/_resizeCanvas.js | 2 +- js/_resizeSprite.js | 2 +- js/pixel-editor.js | 2 +- 14 files changed, 508 insertions(+), 553 deletions(-) create mode 100644 js/History.js delete mode 100644 js/_history.js diff --git a/js/ColorModule.js b/js/ColorModule.js index 884c24e..80fdfb3 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -41,7 +41,7 @@ const ColorModule = (() => { newColor.a = 255; //save undo state - new HistoryStateEditColor(hexElementValue.toLowerCase(), Color.rgbToHex(oldColor)); + new HistoryStates.EditColor(hexElementValue.toLowerCase(), Color.rgbToHex(oldColor)); //get the currently selected color const currentlyEditedColor = document.getElementsByClassName('jscolor-active')[0]; @@ -138,7 +138,7 @@ const ColorModule = (() => { currentLayer.context.fillStyle = '#' + newColor; //add history state - new HistoryStateAddColor(addedColor.firstElementChild.jscolor.toString()); + new HistoryStates.AddColor(addedColor.firstElementChild.jscolor.toString()); //show color picker addedColor.firstElementChild.jscolor.show(); diff --git a/js/History.js b/js/History.js new file mode 100644 index 0000000..2fd6dd6 --- /dev/null +++ b/js/History.js @@ -0,0 +1,484 @@ +/** How the history works + * - undoStates stores the states that can be undone + * - redoStates stores the states that can be redone + * - undo() undoes an action and adds it to the redoStates + * - redo() redoes an action and adds it to the undoStates + * - Each HistoryState must implement an undo() and redo() function + * Those functions actually implement the undo and redo mechanism for that action, + * so you'll need to save the data you need as attributes in the constructor. For example, + * for the HistoryStateAddColour, the added colour is saved so that it can be removed in + * undo() or added back in redo(). + * - Each HistoryState must call saveHistoryState(this) so that it gets added to the stack + * + */ + +const History = (() => { + + const undoLogStyle = 'background: #87ff1c; color: black; padding: 5px;'; + let undoStates = []; + let redoStates = []; + + //rename to add undo state + function saveHistoryState (state) { + //get current canvas data and save to undoStates array + undoStates.push(state); + + //limit the number of states to settings.numberOfHistoryStates + if (undoStates.length > settings.numberOfHistoryStates) { + undoStates = undoStates.splice(-settings.numberOfHistoryStates, settings.numberOfHistoryStates); + } + + //there is now definitely at least 1 undo state, so the button shouldnt be disabled + document.getElementById('undo-button').classList.remove('disabled'); + + //there should be no redoStates after an undoState is saved + redoStates = []; + } + + function undo () { + //if there are any states saved to undo + if (undoStates.length > 0) { + document.getElementById('redo-button').classList.remove('disabled'); + + // get state + var undoState = undoStates[undoStates.length-1]; + // add it to redo states + redoStates.push(undoState); + + //remove from the undo list + undoStates.splice(undoStates.length-1,1); + + //restore the state + undoState.undo(); + + //if theres none left to undo, disable the option + if (undoStates.length == 0) + document.getElementById('undo-button').classList.add('disabled'); + } + } + + function redo () { + console.log("Redo"); + if (redoStates.length > 0) { + + //enable undo button + document.getElementById('undo-button').classList.remove('disabled'); + + //get state + var redoState = redoStates[redoStates.length-1]; + // Add it to undo states + undoStates.push(redoState); + + //remove from redo array (do this before restoring the state, else the flatten state will break) + redoStates.splice(redoStates.length-1,1); + + //restore the state + redoState.redo(); + + //if theres none left to redo, disable the option + if (redoStates.length == 0) + document.getElementById('redo-button').classList.add('disabled'); + } + } + + return { + redo, + undo, + saveHistoryState + } +})(); + +const HistoryStates = { + ResizeSprite: function(xRatio, yRatio, algo, oldData) { + this.xRatio = xRatio; + this.yRatio = yRatio; + this.algo = algo; + this.oldData = oldData; + + this.undo = function() { + let layerIndex = 0; + + currentAlgo = algo; + resizeSprite(null, [1 / this.xRatio, 1 / this.yRatio]); + + // Also putting the old data + for (let i=0; i this.index + 1) { + layers[this.index + 1].selectLayer(); + } + else { + layers[this.index - 1].selectLayer(); + } + + this.added.canvas.remove(); + this.added.menuEntry.remove(); + + layers.splice(index, 1); + }; + + this.redo = function() { + canvasView.append(this.added.canvas); + layerList.prepend(this.added.menuEntry); + layers.splice(this.index, 0, this.added); + }; + + History.saveHistoryState(this); + }, + + //prototype for undoing canvas changes + EditCanvas: function() { + this.canvasState = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + this.layerID = currentLayer.id; + + this.undo = function () { + var stateLayer = getLayerByID(this.layerID); + var currentCanvas = stateLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + stateLayer.context.putImageData(this.canvasState, 0, 0); + + this.canvasState = currentCanvas; + + stateLayer.updateLayerPreview(); + }; + + this.redo = function () { + var stateLayer = getLayerByID(this.layerID); + var currentCanvas = stateLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + + stateLayer.context.putImageData(this.canvasState, 0, 0); + + this.canvasState = currentCanvas; + + stateLayer.updateLayerPreview(); + }; + + //add self to undo array + History.saveHistoryState(this); + }, + + //prototype for undoing added colors + AddColor: function(colorValue) { + this.colorValue = colorValue; + + this.undo = function () { + ColorModule.deleteColor(this.colorValue); + }; + + this.redo = function () { + ColorModule.addColor(this.colorValue); + }; + + //add self to undo array + History.saveHistoryState(this); + }, + + //prototype for undoing deleted colors + DeleteColor: function(colorValue) { + this.colorValue = colorValue; + this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + + this.undo = function () { + var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + currentLayer.context.putImageData(this.canvas, 0, 0); + + ColorModule.addColor(this.colorValue); + + this.canvas = currentCanvas; + }; + + this.redo = function () { + var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + currentLayer.context.putImageData(this.canvas, 0, 0); + + ColorModule.deleteColor(this.colorValue); + + this.canvas = currentCanvas; + }; + + //add self to undo array + History.saveHistoryState(this); + }, + + //prototype for undoing colors edits + EditColor: function(newColorValue, oldColorValue) { + this.newColorValue = newColorValue; + this.oldColorValue = oldColorValue; + this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + + this.undo = function () { + var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + currentLayer.context.putImageData(this.canvas, 0, 0); + + //find new color in palette and change it back to old color + var colors = document.getElementsByClassName('color-button'); + for (var i = 0; i < colors.length; i++) { + //console.log(newColorValue, '==', colors[i].jscolor.toString()); + if (newColorValue == colors[i].jscolor.toString()) { + colors[i].jscolor.fromString(oldColorValue); + break; + } + } + + this.canvas = currentCanvas; + }; + + this.redo = function () { + var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + currentLayer.context.putImageData(this.canvas, 0, 0); + + //find old color in palette and change it back to new color + var colors = document.getElementsByClassName('color-button'); + for (var i = 0; i < colors.length; i++) { + //console.log(oldColorValue, '==', colors[i].jscolor.toString()); + if (oldColorValue == colors[i].jscolor.toString()) { + colors[i].jscolor.fromString(newColorValue); + break; + } + } + + this.canvas = currentCanvas; + }; + + //add self to undo array + History.saveHistoryState(this); + } +} \ No newline at end of file diff --git a/js/_fileMenu.js b/js/_fileMenu.js index 912c917..144b15d 100644 --- a/js/_fileMenu.js +++ b/js/_fileMenu.js @@ -139,10 +139,10 @@ for (var i = 1; i < mainMenuItems.length; i++) { break; //Edit Menu case 'Undo': - undo(); + History.undo(); break; case 'Redo': - redo(); + History.redo(); break; //Palette Menu diff --git a/js/_fill.js b/js/_fill.js index 266c364..e46a89b 100644 --- a/js/_fill.js +++ b/js/_fill.js @@ -22,7 +22,7 @@ function fill(cursorLocation) { } //save history state - new HistoryStateEditCanvas(); + new HistoryStates.EditCanvas(); //saveHistoryState({type: 'canvas', canvas: context.getImageData(0, 0, canvasSize[0], canvasSize[1])}); //console.log('filling at '+ Math.floor(cursorLocation[0]/zoom) + ','+ Math.floor(cursorLocation[1]/zoom)); diff --git a/js/_history.js b/js/_history.js deleted file mode 100644 index 52d6bfb..0000000 --- a/js/_history.js +++ /dev/null @@ -1,529 +0,0 @@ -/** How the history works - * - undoStates stores the states that can be undone - * - redoStates stores the states that can be redone - * - undo() undoes an action and adds it to the redoStates - * - redo() redoes an action and adds it to the undoStates - * - Each HistoryState must implement an undo() and redo() function - * Those functions actually implement the undo and redo mechanism for that action, - * so you'll need to save the data you need as attributes in the constructor. For example, - * for the HistoryStateAddColour, the added colour is saved so that it can be removed in - * undo() or added back in redo(). - * - Each HistoryState must call saveHistoryState(this) so that it gets added to the stack - * - */ - -var undoStates = []; -var redoStates = []; - -const undoLogStyle = 'background: #87ff1c; color: black; padding: 5px;'; - -function HistoryStateResizeSprite(xRatio, yRatio, algo, oldData) { - this.xRatio = xRatio; - this.yRatio = yRatio; - this.algo = algo; - this.oldData = oldData; - - this.undo = function() { - let layerIndex = 0; - - currentAlgo = algo; - resizeSprite(null, [1 / this.xRatio, 1 / this.yRatio]); - - // Also putting the old data - for (let i=0; i this.index + 1) { - layers[this.index + 1].selectLayer(); - } - else { - layers[this.index - 1].selectLayer(); - } - - - this.added.canvas.remove(); - this.added.menuEntry.remove(); - - layers.splice(index, 1); - }; - - this.redo = function() { - undoStates.push(this); - - canvasView.append(this.added.canvas); - layerList.prepend(this.added.menuEntry); - layers.splice(this.index, 0, this.added); - }; - - saveHistoryState(this); -} - -//prototype for undoing canvas changes -function HistoryStateEditCanvas () { - this.canvasState = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - this.layerID = currentLayer.id; - - this.undo = function () { - var stateLayer = getLayerByID(this.layerID); - var currentCanvas = stateLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - stateLayer.context.putImageData(this.canvasState, 0, 0); - - this.canvasState = currentCanvas; - redoStates.push(this); - - stateLayer.updateLayerPreview(); - }; - - this.redo = function () { - console.log("YEET"); - var stateLayer = getLayerByID(this.layerID); - var currentCanvas = stateLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - - stateLayer.context.putImageData(this.canvasState, 0, 0); - - this.canvasState = currentCanvas; - undoStates.push(this); - - stateLayer.updateLayerPreview(); - }; - - //add self to undo array - saveHistoryState(this); -} - -//prototype for undoing added colors -function HistoryStateAddColor (colorValue) { - this.colorValue = colorValue; - - this.undo = function () { - redoStates.push(this); - ColorModule.deleteColor(this.colorValue); - }; - - this.redo = function () { - ColorModule.addColor(this.colorValue); - undoStates.push(this); - }; - - //add self to undo array - saveHistoryState(this); -} - -//prototype for undoing deleted colors -function HistoryStateDeleteColor (colorValue) { - this.colorValue = colorValue; - this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - - this.undo = function () { - var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - currentLayer.context.putImageData(this.canvas, 0, 0); - - ColorModule.addColor(this.colorValue); - - this.canvas = currentCanvas; - redoStates.push(this); - }; - - this.redo = function () { - var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - currentLayer.context.putImageData(this.canvas, 0, 0); - - ColorModule.deleteColor(this.colorValue); - - this.canvas = currentCanvas; - undoStates.push(this); - }; - - //add self to undo array - saveHistoryState(this); -} - -//prototype for undoing colors edits -function HistoryStateEditColor (newColorValue, oldColorValue) { - this.newColorValue = newColorValue; - this.oldColorValue = oldColorValue; - this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - - this.undo = function () { - var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - currentLayer.context.putImageData(this.canvas, 0, 0); - - //find new color in palette and change it back to old color - var colors = document.getElementsByClassName('color-button'); - for (var i = 0; i < colors.length; i++) { - //console.log(newColorValue, '==', colors[i].jscolor.toString()); - if (newColorValue == colors[i].jscolor.toString()) { - colors[i].jscolor.fromString(oldColorValue); - break; - } - } - - this.canvas = currentCanvas; - redoStates.push(this); - }; - - this.redo = function () { - var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - currentLayer.context.putImageData(this.canvas, 0, 0); - - //find old color in palette and change it back to new color - var colors = document.getElementsByClassName('color-button'); - for (var i = 0; i < colors.length; i++) { - //console.log(oldColorValue, '==', colors[i].jscolor.toString()); - if (oldColorValue == colors[i].jscolor.toString()) { - colors[i].jscolor.fromString(newColorValue); - break; - } - } - - this.canvas = currentCanvas; - undoStates.push(this); - }; - - //add self to undo array - saveHistoryState(this); -} - - -//rename to add undo state -function saveHistoryState (state) { - //get current canvas data and save to undoStates array - undoStates.push(state); - - //limit the number of states to settings.numberOfHistoryStates - if (undoStates.length > settings.numberOfHistoryStates) { - undoStates = undoStates.splice(-settings.numberOfHistoryStates, settings.numberOfHistoryStates); - } - - //there is now definitely at least 1 undo state, so the button shouldnt be disabled - document.getElementById('undo-button').classList.remove('disabled'); - - //there should be no redoStates after an undoState is saved - redoStates = []; -} - -function undo () { - //if there are any states saved to undo - if (undoStates.length > 0) { - document.getElementById('redo-button').classList.remove('disabled'); - - //get state - var undoState = undoStates[undoStates.length-1]; - //console.log(undoState); - - //remove from the undo list - undoStates.splice(undoStates.length-1,1); - - //restore the state - undoState.undo(); - - //if theres none left to undo, disable the option - if (undoStates.length == 0) - document.getElementById('undo-button').classList.add('disabled'); - } -} - -function redo () { - if (redoStates.length > 0) { - - //enable undo button - document.getElementById('undo-button').classList.remove('disabled'); - - //get state - var redoState = redoStates[redoStates.length-1]; - - //remove from redo array (do this before restoring the state, else the flatten state will break) - redoStates.splice(redoStates.length-1,1); - - //restore the state - redoState.redo(); - - //if theres none left to redo, disable the option - if (redoStates.length == 0) - document.getElementById('redo-button').classList.add('disabled'); - } - //console.log(undoStates); - //console.log(redoStates); -} diff --git a/js/_hotkeyListener.js b/js/_hotkeyListener.js index ecb74b8..8331ce2 100644 --- a/js/_hotkeyListener.js +++ b/js/_hotkeyListener.js @@ -90,13 +90,13 @@ function KeyPress(e) { case 90: //CTRL+ALT+Z redo if (keyboardEvent.altKey && keyboardEvent.ctrlKey) - redo(); + History.redo(); if (!selectionCanceled) { tool.pencil.switchTo() } //CTRL+Z undo else if (keyboardEvent.ctrlKey) { - undo(); + History.undo(); if (!selectionCanceled) { tool.pencil.switchTo() } @@ -107,9 +107,9 @@ function KeyPress(e) { break; //redo - ctrl y case 89: - if (keyboardEvent.ctrlKey) - redo(); - break; + if (keyboardEvent.ctrlKey) + History.redo(); + break; case 32: spacePressed=true; break; diff --git a/js/_jscolor.js b/js/_jscolor.js index e201f0a..7bcf99a 100644 --- a/js/_jscolor.js +++ b/js/_jscolor.js @@ -551,7 +551,7 @@ if (!window.jscolor) { window.jscolor = (function () { //if they clicked on the delete button [lospec] if (e.target.className == 'delete-color-button') { //saveHistoryState({type: 'deletecolor', colorValue: jsc.picker.owner.toString(), canvas: canvas.context.getImageData(0, 0, canvasSize[0], canvasSize[1])}); - new HistoryStateDeleteColor(jsc.picker.owner.toString()); + new HistoryStates.DeleteColor(jsc.picker.owner.toString()); ColorModule.deleteColor(jsc.picker.owner.styleElement); } diff --git a/js/_layer.js b/js/_layer.js index 0787620..b08e0d3 100644 --- a/js/_layer.js +++ b/js/_layer.js @@ -189,7 +189,7 @@ class Layer { let name = this.menuEntry.getElementsByTagName("p")[0].innerHTML; this.name = name; - new HistoryStateRenameLayer(oldLayerName, name, currentLayer); + new HistoryStates.RenameLayer(oldLayerName, name, currentLayer); oldLayerName = null; } } @@ -310,7 +310,7 @@ function flatten(onlyVisible) { merge(); } - new HistoryStateFlattenAll(nToFlatten); + new HistoryStates.FlattenAll(nToFlatten); } else { // Getting all the visible layers @@ -332,7 +332,7 @@ function flatten(onlyVisible) { for (let i=0; i Date: Wed, 14 Jul 2021 22:48:53 +0200 Subject: [PATCH 17/91] Fixed mode switching, started SplashPage IIFE --- js/Dialogue.js | 9 ++++++++- js/SplashPage.js | 39 +++++++++++++++++++++++++++++++++++++++ js/_createButton.js | 1 - js/_editorMode.js | 31 +++++++++++++++++-------------- js/_featuresLog.js | 1 - js/_hotkeyListener.js | 2 +- js/_jscolor.js | 6 ------ js/_mouseEvents.js | 4 ++-- js/_newPixel.js | 8 -------- js/_splashPage.js | 23 ----------------------- js/_variables.js | 1 - js/pixel-editor.js | 3 +-- 12 files changed, 68 insertions(+), 60 deletions(-) create mode 100644 js/SplashPage.js delete mode 100644 js/_featuresLog.js delete mode 100644 js/_splashPage.js diff --git a/js/Dialogue.js b/js/Dialogue.js index 98a89cf..56cd2c6 100644 --- a/js/Dialogue.js +++ b/js/Dialogue.js @@ -3,6 +3,8 @@ */ const Dialogue = (() => { let currentOpenDialogue = ""; + let dialogueOpen = true; + const popUpContainer = document.getElementById("pop-up-container"); const cancelButtons = popUpContainer.getElementsByClassName('close-button'); @@ -68,9 +70,14 @@ const Dialogue = (() => { } } + function isOpen() { + return dialogueOpen; + } + return { showDialogue, - closeDialogue + closeDialogue, + isOpen } })(); diff --git a/js/SplashPage.js b/js/SplashPage.js new file mode 100644 index 0000000..e1737ba --- /dev/null +++ b/js/SplashPage.js @@ -0,0 +1,39 @@ +const SplashPage = (() => { + const images = [ + new SplashCoverImage('Rayquaza', 'Unsettled', 'https://lospec.com/unsettled'), + new SplashCoverImage('Mountains', 'Skeddles', 'https://lospec.com/skeddles'), + new SplashCoverImage('Sweetie', 'GrafxKid', 'https://twitter.com/GrafxKid'), + new SplashCoverImage('Glacier', 'WindfallApples', 'https://lospec.com/windfallapples'), + new SplashCoverImage('Polyphorge1', 'Polyphorge', 'https://lospec.com/poly-phorge'), + new SplashCoverImage('Fusionnist', 'Fusionnist', 'https://lospec.com/fusionnist') + ]; + const coverImage = document.getElementById('editor-logo'); + const authorLink = coverImage.getElementsByTagName('a')[0]; + const chosenImage = images[Math.round(Math.random() * (images.length - 1))]; + + initSplashPage(); + + function initSplashPage() { + coverImage.style.backgroundImage = 'url("' + chosenImage.path + '.png")'; + authorLink.setAttribute('href', chosenImage.link); + authorLink.innerHTML = 'Art by ' + chosenImage.author; + + Dialogue.showDialogue("splash", false); + } + + function SplashCoverImage(path, author, link) { + this.path = path; + this.author = author; + this.link = link; + } + + return { + + } +})(); + + + + + + diff --git a/js/_createButton.js b/js/_createButton.js index 59c25a4..10cbebd 100644 --- a/js/_createButton.js +++ b/js/_createButton.js @@ -38,7 +38,6 @@ function create(isSplash) { * */ Input.on('click', 'create-button', function (){ - console.log("Here"); // Getting the values of the form var width = Util.getValue('size-width'); var height = Util.getValue('size-height'); diff --git a/js/_editorMode.js b/js/_editorMode.js index 6fab5b3..81ae8fc 100644 --- a/js/_editorMode.js +++ b/js/_editorMode.js @@ -3,19 +3,17 @@ let modes = { description: 'Basic mode is perfect if you want to create simple sprites or try out palettes.' }, 'Advanced' : { - description: 'Choose advanced mode to gain access to more advanced features such as layers.' + description: 'Choose advanced mode to gain access to more advanced features such as layers and advanced palette editing.' } } Input.on('click', 'switch-editor-mode-splash', function (e) { - console.log('switching mode') - switchMode(); + toggleMode(); }); -function switchMode(mustConfirm = true) { - console.log('switching mode', 'current:',pixelEditorMode) +function switchMode(newMode) { //switch to advanced mode - if (pixelEditorMode == 'Basic') { + if (newMode == 'Advanced') { // Switch to advanced ez pez lemon squez document.getElementById('switch-mode-button').innerHTML = 'Switch to basic mode'; // Show the layer menus @@ -36,12 +34,9 @@ function switchMode(mustConfirm = true) { else { //if there is a current layer (a document is active) if (currentLayer) { - //confirm with user before flattening image - if (mustConfirm ) { - if (!confirm('Switching to basic mode will flatten all the visible layers. Are you sure you want to continue?')) { - return; - } - } + if (!confirm('Switching to basic mode will flatten all the visible layers. Are you sure you want to continue?')) { + return; + } // Selecting the current layer currentLayer.selectLayer(); @@ -60,7 +55,6 @@ function switchMode(mustConfirm = true) { // Move the palette menu document.getElementById('colors-menu').style.right = '0px'; - //change splash text document.querySelector('#sp-quickstart-container .mode-switcher').classList.remove('advanced-mode'); @@ -69,6 +63,15 @@ function switchMode(mustConfirm = true) { } } +function toggleMode() { + console.log("From " + pixelEditorMode); + + if (pixelEditorMode == 'Advanced') + switchMode('Basic'); + else + switchMode('Advanced'); +} + Input.on('click', 'switch-mode-button', function (e) { - switchMode(); + toggleMode(); }); diff --git a/js/_featuresLog.js b/js/_featuresLog.js deleted file mode 100644 index a1a18e4..0000000 --- a/js/_featuresLog.js +++ /dev/null @@ -1 +0,0 @@ -Dialogue.showDialogue("splash", false); \ No newline at end of file diff --git a/js/_hotkeyListener.js b/js/_hotkeyListener.js index 8331ce2..6acc376 100644 --- a/js/_hotkeyListener.js +++ b/js/_hotkeyListener.js @@ -18,7 +18,7 @@ function KeyPress(e) { //if no document has been created yet, //orthere is a dialog box open //ignore hotkeys - if (!documentCreated || dialogueOpen) return; + if (!documentCreated || Dialogue.isOpen()) return; // if (e.key === "Escape") { diff --git a/js/_jscolor.js b/js/_jscolor.js index 7bcf99a..852d41c 100644 --- a/js/_jscolor.js +++ b/js/_jscolor.js @@ -1077,9 +1077,6 @@ if (!window.jscolor) { window.jscolor = (function () { this.fromString(oldColor); document.getElementById('duplicate-color-warning').style.visibility = 'hidden'; - //dialog is closed - dialogueOpen = false; - detachPicker(); } }; @@ -1088,9 +1085,6 @@ if (!window.jscolor) { window.jscolor = (function () { this.show = function () { drawPicker(); - //a dialog is open - dialogueOpen = true; - //[lospec] //find the hex input element var hexInput = document.getElementById('jscolor-hex-input'); diff --git a/js/_mouseEvents.js b/js/_mouseEvents.js index a261c8f..f9ee578 100644 --- a/js/_mouseEvents.js +++ b/js/_mouseEvents.js @@ -8,7 +8,7 @@ window.addEventListener("mousedown", function (mouseEvent) { canDraw = true; //if no document has been created yet, or this is a dialog open, or the currentLayer is locked - if (!documentCreated || dialogueOpen || currentLayer.isLocked || !currentLayer.isVisible) return; + if (!documentCreated || Dialogue.isOpen() || currentLayer.isLocked || !currentLayer.isVisible) return; //prevent right mouse clicks and such, which will open unwanted menus //mouseEvent.preventDefault(); @@ -204,7 +204,7 @@ window.addEventListener("mousemove", draw, false); window.addEventListener("mousedown", draw, false); function draw (mouseEvent) { - if (!dialogueOpen) + if (!Dialogue.isOpen()) { lastMouseMovePos = getCursorPosition(mouseEvent); // Saving the event in case something else needs it diff --git a/js/_newPixel.js b/js/_newPixel.js index fd43952..3d4e09b 100644 --- a/js/_newPixel.js +++ b/js/_newPixel.js @@ -194,14 +194,6 @@ function newPixel (width, height, editorMode, fileContent = null) { deleteLayer(false); } - // Applying the correct editor mode - if (pixelEditorMode == 'Basic') { - switchMode(false); - } - else { - switchMode(false); - } - // Resetting history undoStates = []; redoStates = []; diff --git a/js/_splashPage.js b/js/_splashPage.js deleted file mode 100644 index 278e70d..0000000 --- a/js/_splashPage.js +++ /dev/null @@ -1,23 +0,0 @@ -function SplashCoverImage(path, author, link) { - this.path = path; - this.author = author; - this.link = link; -} - -let images = [ - new SplashCoverImage('Rayquaza', 'Unsettled', 'https://lospec.com/unsettled'), - new SplashCoverImage('Mountains', 'Skeddles', 'https://lospec.com/skeddles'), - new SplashCoverImage('Sweetie', 'GrafxKid', 'https://twitter.com/GrafxKid'), - new SplashCoverImage('Glacier', 'WindfallApples', 'https://lospec.com/windfallapples'), - new SplashCoverImage('Polyphorge1', 'Polyphorge', 'https://lospec.com/poly-phorge'), - new SplashCoverImage('Fusionnist', 'Fusionnist', 'https://lospec.com/fusionnist') -]; - - -let coverImage = document.getElementById('editor-logo'); -let authorLink = coverImage.getElementsByTagName('a')[0]; -let chosenImage = images[Math.round(Math.random() * (images.length - 1))]; - -coverImage.style.backgroundImage = 'url("' + chosenImage.path + '.png")'; -authorLink.setAttribute('href', chosenImage.link); -authorLink.innerHTML = 'Art by ' + chosenImage.author; \ No newline at end of file diff --git a/js/_variables.js b/js/_variables.js index d837f0a..a130d55 100644 --- a/js/_variables.js +++ b/js/_variables.js @@ -3,7 +3,6 @@ var canvasSize; var zoom = 7; var dragging = false; var lastMouseClickPos = [0,0]; -var dialogueOpen = true; var documentCreated = false; var pixelEditorMode = "Basic"; diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 76b7c03..25ec3bd 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -25,7 +25,6 @@ //=include _createColorPalette.js //=include _changeZoom.js //=include ColorModule.js -//!=include _featuresLog.js //=include _drawLine.js //=include _getCursorPosition.js //=include _fill.js @@ -38,7 +37,7 @@ //=include _resizeSprite.js //=include _colorPicker.js //=include _paletteBlock.js -//=include _splashPage.js +//=include SplashPage.js /**load file**/ //=include _loadImage.js From eada155375131725df132437f260a0b7a80535c7 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Wed, 14 Jul 2021 23:00:12 +0200 Subject: [PATCH 18/91] Fixed Dialogue bug --- js/ColorModule.js | 2 +- js/_mouseEvents.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/ColorModule.js b/js/ColorModule.js index 80fdfb3..afdbdf3 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -236,7 +236,7 @@ const ColorModule = (() => { if (pixelEditorMode == 'Basic') event.target.parentElement.firstChild.jscolor.show(); else - showDialogue("palette-block", false); + Dialogue.showDialogue("palette-block", false); }); return listItem; diff --git a/js/_mouseEvents.js b/js/_mouseEvents.js index f9ee578..4257f0a 100644 --- a/js/_mouseEvents.js +++ b/js/_mouseEvents.js @@ -85,7 +85,7 @@ window.addEventListener("mouseup", function (mouseEvent) { tmpContext.clearRect(0, 0, tmpCanvas.width, tmpCanvas.height); } - if (!documentCreated || dialogueOpen || !currentLayer.isVisible || currentLayer.isLocked) return; + if (!documentCreated || Dialogue.isOpen() || !currentLayer.isVisible || currentLayer.isLocked) return; if (currentTool.name == 'eyedropper' && mouseEvent.target.className == 'drawingCanvas') { var cursorLocation = getCursorPosition(mouseEvent); @@ -213,7 +213,7 @@ function draw (mouseEvent) { var cursorLocation = lastMouseMovePos; //if a document hasnt yet been created or the current layer is locked, exit this function - if (!documentCreated || dialogueOpen || !currentLayer.isVisible || currentLayer.isLocked) return; + if (!documentCreated || Dialogue.isOpen() || !currentLayer.isVisible || currentLayer.isLocked) return; // Moving brush preview currentTool.moveBrushPreview(cursorLocation); From 4f4091ebb3c028d8cc18e17b14193482ef0154cf Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Thu, 15 Jul 2021 16:33:26 +0200 Subject: [PATCH 19/91] Merged the two create functions --- js/Dialogue.js | 2 +- js/_createButton.js | 67 ++++----------------------------------------- js/_editorMode.js | 7 +++-- js/_fileMenu.js | 6 ++-- js/_loadImage.js | 3 +- js/_newPixel.js | 8 ++---- js/_variables.js | 1 - js/pixel-editor.js | 6 ++-- 8 files changed, 20 insertions(+), 80 deletions(-) diff --git a/js/Dialogue.js b/js/Dialogue.js index 56cd2c6..726d7f8 100644 --- a/js/Dialogue.js +++ b/js/Dialogue.js @@ -48,7 +48,7 @@ const Dialogue = (() => { } //track google event - if (trackEvent) + if (trackEvent && typeof ga !== 'undefined') ga('send', 'event', 'Palette Editor Dialogue', dialogueName); /*global ga*/ } diff --git a/js/_createButton.js b/js/_createButton.js index 10cbebd..8b03d7f 100644 --- a/js/_createButton.js +++ b/js/_createButton.js @@ -8,10 +8,7 @@ function create(isSplash) { var width = Util.getValue('size-width' + splashPostfix); var height = Util.getValue('size-height' + splashPostfix); - // If I'm creating from the splash screen, I use the splashMode variable - var mode = isSplash ? splashMode : pixelEditorMode; - - newPixel(width, height, mode); + newPixel(width, height); // If I'm not creating from the splash page, then this is not the first project I've created if (!isSplash) @@ -23,8 +20,8 @@ function create(isSplash) { selectedPalette = 'none'; //track google event - ga('send', 'event', 'Pixel Editor New', selectedPalette, width+'/'+height); /*global ga*/ - + if (typeof ga !== 'undefined') + ga('send', 'event', 'Pixel Editor New', selectedPalette, width+'/'+height); /*global ga*/ //reset new form Util.setValue('size-width', 64); @@ -37,63 +34,9 @@ function create(isSplash) { /** Triggered when the "Create" button in the new pixel dialogue is pressed * */ -Input.on('click', 'create-button', function (){ - // Getting the values of the form - var width = Util.getValue('size-width'); - var height = Util.getValue('size-height'); - - // Creating a new pixel with those properties - if(pixelEditorMode == "Basic") - newPixel(width, height, "Advanced"); - else - newPixel(width, height, "Basic"); - document.getElementById('new-pixel-warning').style.display = 'block'; - - //get selected palette name - var selectedPalette = Util.getText('palette-button'); - if (selectedPalette == 'Choose a palette...') - selectedPalette = 'none'; - - //track google event - ga('send', 'event', 'Pixel Editor New', selectedPalette, width+'/'+height); /*global ga*/ - - - //reset new form - Util.setValue('size-width', 64); - Util.setValue('size-height', 64); - - Util.setText('palette-button', 'Choose a palette...'); - Util.setText('preset-button', 'Choose a preset...'); -}); +Input.on('click', 'create-button', create, false); /** Triggered when the "Create" button in the splash page is pressed * */ - Input.on('click', 'create-button-splash', function (){ - // Getting the values of the form - var width = Util.getValue('size-width-splash'); - var height = Util.getValue('size-height-splash'); - var mode = pixelEditorMode; - - if (mode == 'Advanced') - mode = "Basic"; - else - mode = "Advanced"; - - // Creating a new pixel with those properties - newPixel(width, height, mode); - - //track google event - ga('send', 'event', 'Pixel Editor New', selectedPalette, width+'/'+height); /*global ga*/ - document.getElementById('new-pixel-warning').style.display = 'block'; - - // Resetting the new pixel values - selectedPalette = 'none'; - - //reset new pixel form - Util.setValue('size-width-splash', 64); - Util.setValue('size-height-splash', 64); - - Util.setText('palette-button', 'Choose a palette...'); - Util.setText('preset-button', 'Choose a preset...'); -}); + Input.on('click', 'create-button-splash', create, true); diff --git a/js/_editorMode.js b/js/_editorMode.js index 81ae8fc..6816727 100644 --- a/js/_editorMode.js +++ b/js/_editorMode.js @@ -1,3 +1,6 @@ +var pixelEditorMode = "Basic"; +switchMode(pixelEditorMode); + let modes = { 'Basic' : { description: 'Basic mode is perfect if you want to create simple sprites or try out palettes.' @@ -13,7 +16,7 @@ Input.on('click', 'switch-editor-mode-splash', function (e) { function switchMode(newMode) { //switch to advanced mode - if (newMode == 'Advanced') { + if (newMode == 'Advanced' && pixelEditorMode == 'Basic') { // Switch to advanced ez pez lemon squez document.getElementById('switch-mode-button').innerHTML = 'Switch to basic mode'; // Show the layer menus @@ -64,8 +67,6 @@ function switchMode(newMode) { } function toggleMode() { - console.log("From " + pixelEditorMode); - if (pixelEditorMode == 'Advanced') switchMode('Basic'); else diff --git a/js/_fileMenu.js b/js/_fileMenu.js index 144b15d..b97a8e7 100644 --- a/js/_fileMenu.js +++ b/js/_fileMenu.js @@ -49,7 +49,8 @@ for (var i = 1; i < mainMenuItems.length; i++) { linkHolder.download = fileName; linkHolder.click(); - ga('send', 'event', 'Pixel Editor Save', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/ + if (typeof ga !== 'undefined') + ga('send', 'event', 'Pixel Editor Save', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/ break; case 'Open': @@ -117,7 +118,8 @@ for (var i = 1; i < mainMenuItems.length; i++) { exportCanvas.remove(); //track google event - ga('send', 'event', 'Pixel Editor Export', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/ + if (typeof ga !== 'undefined') + ga('send', 'event', 'Pixel Editor Export', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/ } break; diff --git a/js/_loadImage.js b/js/_loadImage.js index a9897b6..f1a0565 100644 --- a/js/_loadImage.js +++ b/js/_loadImage.js @@ -38,7 +38,8 @@ document.getElementById('open-image-browse-holder').addEventListener('change', f createPaletteFromLayers(); //track google event - ga('send', 'event', 'Pixel Editor Load', colorPalette.length, this.width+'/'+this.height); /*global ga*/ + if (typeof ga !== 'undefined') + ga('send', 'event', 'Pixel Editor Load', colorPalette.length, this.width+'/'+this.height); /*global ga*/ }; img.src = e.target.result; diff --git a/js/_newPixel.js b/js/_newPixel.js index 3d4e09b..5b2dd3e 100644 --- a/js/_newPixel.js +++ b/js/_newPixel.js @@ -4,13 +4,9 @@ let firstPixel = true; * * @param {*} width Start width of the canvas * @param {*} height Start height of the canvas - * @param {*} editorMode The editor mode chosen by the user (advanced or basic) * @param {*} fileContent If fileContent != null, then the newPixel is being called from the open menu */ -function newPixel (width, height, editorMode, fileContent = null) { - // Saving the editor mode - pixelEditorMode = editorMode; - +function newPixel (width, height, fileContent = null) { // The palette is empty, at the beginning ColorModule.currentPalette.length = 0; @@ -208,5 +204,5 @@ function newFromTemplate(preset, x, y) { x = presetProperties.width; y = presetProperties.height; } - newPixel(x, y, pixelEditorMode == 'Advanced' ? 'Basic' : 'Advanced'); + newPixel(x, y); } \ No newline at end of file diff --git a/js/_variables.js b/js/_variables.js index a130d55..9d6eb81 100644 --- a/js/_variables.js +++ b/js/_variables.js @@ -4,7 +4,6 @@ var zoom = 7; var dragging = false; var lastMouseClickPos = [0,0]; var documentCreated = false; -var pixelEditorMode = "Basic"; //common elements var brushPreview = document.getElementById("brush-preview"); diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 25ec3bd..75d5e59 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -1,5 +1,6 @@ /**utilities**/ //=include lib/cookies.js +//=include _jscolor.js //=include _pixelEditorUtility.js //=include lib/sortable.js //=include Util.js @@ -14,7 +15,6 @@ //=include _settings.js /**dropdown formatting**/ -//=include _editorMode.js //=include _presets.js //=include _palettes.js @@ -38,6 +38,7 @@ //=include _colorPicker.js //=include _paletteBlock.js //=include SplashPage.js +//=include _editorMode.js /**load file**/ //=include _loadImage.js @@ -60,9 +61,6 @@ //=include _onLoad.js //=include _onbeforeunload.js -/**libraries**/ -//=include _jscolor.js - /**feature toggles**/ //=include _featureToggles.js From 7c80e8f342f7e7257a3b76810ea068c25a21efb9 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Thu, 15 Jul 2021 17:10:07 +0200 Subject: [PATCH 20/91] Finished refactoring History, added Startup IIFE --- js/ColorModule.js | 19 +++-- js/History.js | 164 ++++++++++++++++---------------------------- js/Startup.js | 3 + js/_fill.js | 2 +- js/_jscolor.js | 2 +- js/_layer.js | 14 ++-- js/_mouseEvents.js | 2 +- js/_move.js | 2 +- js/_newPixel.js | 3 +- js/_rectSelect.js | 2 +- js/_resizeCanvas.js | 2 +- js/_resizeSprite.js | 2 +- 12 files changed, 92 insertions(+), 125 deletions(-) create mode 100644 js/Startup.js diff --git a/js/ColorModule.js b/js/ColorModule.js index afdbdf3..7f513e8 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -3,7 +3,7 @@ */ const ColorModule = (() => { // Array containing the colours of the current palette - const currentPalette = []; + let currentPalette = []; // Reference to the HTML palette const coloursList = document.getElementById("palette-list"); @@ -41,7 +41,7 @@ const ColorModule = (() => { newColor.a = 255; //save undo state - new HistoryStates.EditColor(hexElementValue.toLowerCase(), Color.rgbToHex(oldColor)); + new HistoryState().EditColor(hexElementValue.toLowerCase(), Color.rgbToHex(oldColor)); //get the currently selected color const currentlyEditedColor = document.getElementsByClassName('jscolor-active')[0]; @@ -138,7 +138,7 @@ const ColorModule = (() => { currentLayer.context.fillStyle = '#' + newColor; //add history state - new HistoryStates.AddColor(addedColor.firstElementChild.jscolor.toString()); + new HistoryState().AddColor(addedColor.firstElementChild.jscolor.toString()); //show color picker addedColor.firstElementChild.jscolor.show(); @@ -338,11 +338,20 @@ const ColorModule = (() => { currentLayer.context.putImageData(tempImage,0,0); } + function getCurrentPalette() { + return currentPalette; + } + + function resetPalette() { + currentPalette = []; + } + return { - currentPalette, + getCurrentPalette, addColor, deleteColor, replaceAllOfColor, - addToSimplePalette + addToSimplePalette, + resetPalette } })(); \ No newline at end of file diff --git a/js/History.js b/js/History.js index 2fd6dd6..04563d5 100644 --- a/js/History.js +++ b/js/History.js @@ -20,6 +20,8 @@ const History = (() => { //rename to add undo state function saveHistoryState (state) { + console.log("saved history"); + console.log(state); //get current canvas data and save to undoStates array undoStates.push(state); @@ -36,49 +38,35 @@ const History = (() => { } function undo () { - //if there are any states saved to undo - if (undoStates.length > 0) { - document.getElementById('redo-button').classList.remove('disabled'); - - // get state - var undoState = undoStates[undoStates.length-1]; - // add it to redo states - redoStates.push(undoState); - - //remove from the undo list - undoStates.splice(undoStates.length-1,1); - - //restore the state - undoState.undo(); - - //if theres none left to undo, disable the option - if (undoStates.length == 0) - document.getElementById('undo-button').classList.add('disabled'); - } + undoOrRedo('undo'); } function redo () { - console.log("Redo"); - if (redoStates.length > 0) { + undoOrRedo('redo'); + } - //enable undo button - document.getElementById('undo-button').classList.remove('disabled'); + function undoOrRedo(mode) { + if (redoStates.length <= 0 && mode == 'redo') return; + if (undoStates.length <= 0 && mode == 'undo') return; - //get state - var redoState = redoStates[redoStates.length-1]; - // Add it to undo states - undoStates.push(redoState); + // Enable button + document.getElementById(mode + '-button').classList.remove('disabled'); - //remove from redo array (do this before restoring the state, else the flatten state will break) - redoStates.splice(redoStates.length-1,1); - - //restore the state - redoState.redo(); - - //if theres none left to redo, disable the option - if (redoStates.length == 0) - document.getElementById('redo-button').classList.add('disabled'); + if (mode == 'undo') { + const undoState = undoStates.pop(); + redoStates.push(undoState); + undoState.undo(); } + else { + const redoState = redoStates.pop(); + undoStates.push(redoState); + redoState.redo(); + } + + + // if theres none left, disable the option + if (redoStates.length == 0) document.getElementById('redo-button').classList.add('disabled'); + if (undoStates.length == 0) document.getElementById('undo-button').classList.add('disabled'); } return { @@ -88,8 +76,12 @@ const History = (() => { } })(); -const HistoryStates = { - ResizeSprite: function(xRatio, yRatio, algo, oldData) { +class HistoryState { + constructor() { + History.saveHistoryState(this); + } + + ResizeSprite (xRatio, yRatio, algo, oldData) { this.xRatio = xRatio; this.yRatio = yRatio; this.algo = algo; @@ -115,11 +107,9 @@ const HistoryStates = { currentAlgo = algo; resizeSprite(null, [this.xRatio, this.yRatio]); }; - - History.saveHistoryState(this); - }, + } - ResizeCanvas: function (newSize, oldSize, imageDatas, trim) { + ResizeCanvas (newSize, oldSize, imageDatas, trim) { this.oldSize = oldSize; this.newSize = newSize; this.imageDatas = imageDatas; @@ -146,11 +136,9 @@ const HistoryStates = { trimCanvas(null, false); } }; + } - History.saveHistoryState(this); - }, - - FlattenVisible: function(flattened) { + FlattenVisible(flattened) { this.nFlattened = flattened; this.undo = function() { @@ -164,11 +152,9 @@ const HistoryStates = { redo(); } }; + } - History.saveHistoryState(this); - }, - - FlattenTwoVisibles: function(belowImageData, afterAbove, layerIndex, aboveLayer, belowLayer) { + FlattenTwoVisibles(belowImageData, afterAbove, layerIndex, aboveLayer, belowLayer) { this.aboveLayer = aboveLayer; this.belowLayer = belowLayer; this.belowImageData = belowImageData; @@ -192,11 +178,9 @@ const HistoryStates = { aboveLayer.menuEntry.remove(); layers.splice(layers.indexOf(aboveLayer), 1); }; + } - History.saveHistoryState(this); - }, - - FlattenAll: function(nFlattened) { + FlattenAll(nFlattened) { this.nFlattened = nFlattened; this.undo = function() { @@ -210,11 +194,9 @@ const HistoryStates = { redo(); } }; + } - History.saveHistoryState(this); - }, - - MergeLayer: function(aboveIndex, aboveLayer, belowData, belowLayer) { + MergeLayer(aboveIndex, aboveLayer, belowData, belowLayer) { this.aboveIndex = aboveIndex; this.belowData = belowData; this.aboveLayer = aboveLayer; @@ -235,11 +217,9 @@ const HistoryStates = { aboveLayer.selectLayer(); merge(false); }; + } - History.saveHistoryState(this); - }, - - RenameLayer: function(oldName, newName, layer) { + RenameLayer(oldName, newName, layer) { this.edited = layer; this.oldName = oldName; this.newName = newName; @@ -251,11 +231,9 @@ const HistoryStates = { this.redo = function() { layer.menuEntry.getElementsByTagName("p")[0].innerHTML = newName; }; + } - History.saveHistoryState(this); - }, - - DuplicateLayer: function(addedLayer, copiedLayer) { + DuplicateLayer(addedLayer, copiedLayer) { this.addedLayer = addedLayer; this.copiedLayer = copiedLayer; @@ -268,11 +246,9 @@ const HistoryStates = { copiedLayer.selectLayer(); duplicateLayer(null, false); }; + } - History.saveHistoryState(this); - }, - - DeleteLayer: function(layerData, before, index) { + DeleteLayer(layerData, before, index) { this.deleted = layerData; this.before = before; this.index = index; @@ -292,11 +268,9 @@ const HistoryStates = { this.deleted.selectLayer(); deleteLayer(false); }; + } - History.saveHistoryState(this); - }, - - MoveTwoLayers: function(layer, oldIndex, newIndex) { + MoveTwoLayers(layer, oldIndex, newIndex) { this.layer = layer; this.oldIndex = oldIndex; this.newIndex = newIndex; @@ -308,11 +282,9 @@ const HistoryStates = { this.redo = function() { layer.canvas.style.zIndex = newIndex; }; + } - History.saveHistoryState(this); - }, - - MoveLayer: function(afterToDrop, toDrop, staticc, nMoved) { + MoveLayer(afterToDrop, toDrop, staticc, nMoved) { this.beforeToDrop = afterToDrop; this.toDrop = toDrop; @@ -334,11 +306,9 @@ const HistoryStates = { this.redo = function() { moveLayers(toDrop.menuEntry.id, staticc.menuEntry.id, true); }; + } - History.saveHistoryState(this); - }, - - AddLayer: function(layerData, index) { + AddLayer(layerData, index) { this.added = layerData; this.index = index; @@ -361,12 +331,10 @@ const HistoryStates = { layerList.prepend(this.added.menuEntry); layers.splice(this.index, 0, this.added); }; - - History.saveHistoryState(this); - }, + } //prototype for undoing canvas changes - EditCanvas: function() { + EditCanvas() { this.canvasState = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); this.layerID = currentLayer.id; @@ -390,13 +358,10 @@ const HistoryStates = { stateLayer.updateLayerPreview(); }; - - //add self to undo array - History.saveHistoryState(this); - }, + } //prototype for undoing added colors - AddColor: function(colorValue) { + AddColor(colorValue) { this.colorValue = colorValue; this.undo = function () { @@ -406,13 +371,10 @@ const HistoryStates = { this.redo = function () { ColorModule.addColor(this.colorValue); }; - - //add self to undo array - History.saveHistoryState(this); - }, + } //prototype for undoing deleted colors - DeleteColor: function(colorValue) { + DeleteColor(colorValue) { this.colorValue = colorValue; this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); @@ -433,13 +395,10 @@ const HistoryStates = { this.canvas = currentCanvas; }; - - //add self to undo array - History.saveHistoryState(this); - }, + } //prototype for undoing colors edits - EditColor: function(newColorValue, oldColorValue) { + EditColor(newColorValue, oldColorValue) { this.newColorValue = newColorValue; this.oldColorValue = oldColorValue; this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); @@ -477,8 +436,5 @@ const HistoryStates = { this.canvas = currentCanvas; }; - - //add self to undo array - History.saveHistoryState(this); } } \ No newline at end of file diff --git a/js/Startup.js b/js/Startup.js new file mode 100644 index 0000000..b4d0638 --- /dev/null +++ b/js/Startup.js @@ -0,0 +1,3 @@ +const Startup = (() => { + +})(); \ No newline at end of file diff --git a/js/_fill.js b/js/_fill.js index e46a89b..9d99c92 100644 --- a/js/_fill.js +++ b/js/_fill.js @@ -22,7 +22,7 @@ function fill(cursorLocation) { } //save history state - new HistoryStates.EditCanvas(); + new HistoryState().EditCanvas(); //saveHistoryState({type: 'canvas', canvas: context.getImageData(0, 0, canvasSize[0], canvasSize[1])}); //console.log('filling at '+ Math.floor(cursorLocation[0]/zoom) + ','+ Math.floor(cursorLocation[1]/zoom)); diff --git a/js/_jscolor.js b/js/_jscolor.js index 852d41c..11efd26 100644 --- a/js/_jscolor.js +++ b/js/_jscolor.js @@ -551,7 +551,7 @@ if (!window.jscolor) { window.jscolor = (function () { //if they clicked on the delete button [lospec] if (e.target.className == 'delete-color-button') { //saveHistoryState({type: 'deletecolor', colorValue: jsc.picker.owner.toString(), canvas: canvas.context.getImageData(0, 0, canvasSize[0], canvasSize[1])}); - new HistoryStates.DeleteColor(jsc.picker.owner.toString()); + new HistoryState().DeleteColor(jsc.picker.owner.toString()); ColorModule.deleteColor(jsc.picker.owner.styleElement); } diff --git a/js/_layer.js b/js/_layer.js index b08e0d3..0bd17ba 100644 --- a/js/_layer.js +++ b/js/_layer.js @@ -189,7 +189,7 @@ class Layer { let name = this.menuEntry.getElementsByTagName("p")[0].innerHTML; this.name = name; - new HistoryStates.RenameLayer(oldLayerName, name, currentLayer); + new HistoryState().RenameLayer(oldLayerName, name, currentLayer); oldLayerName = null; } } @@ -310,7 +310,7 @@ function flatten(onlyVisible) { merge(); } - new HistoryStates.FlattenAll(nToFlatten); + new HistoryState().FlattenAll(nToFlatten); } else { // Getting all the visible layers @@ -332,7 +332,7 @@ function flatten(onlyVisible) { for (let i=0; i Date: Thu, 15 Jul 2021 18:33:19 +0200 Subject: [PATCH 21/91] Added Startup IIFE to take care of the creation of a new project It includes the old _createButton and _newPixel functions and a few private methods to divide the huge newPixel function into smaller chunks depending on their purpose. Those chunks could probably be part of other IIFEs, but we'll think about that in the future. Fixed Input bug that caused the on function to pass an array of arguments instead of single arguments. Removed data_asdfgasd.hbs --- js/Input.js | 4 +- js/{_presets.js => PresetModule.js} | 2 +- js/Startup.js | 261 ++++++++++++++++++++++++++++ js/_createButton.js | 42 ----- js/_fileMenu.js | 4 +- js/_loadImage.js | 5 +- js/_newPixel.js | 207 ---------------------- js/_onLoad.js | 6 +- js/pixel-editor.js | 5 +- views/data-asdfgasd.hbs | 0 views/splash-page-popup.hbs | 18 +- 11 files changed, 281 insertions(+), 273 deletions(-) rename js/{_presets.js => PresetModule.js} (97%) delete mode 100644 js/_createButton.js delete mode 100644 js/_newPixel.js delete mode 100644 views/data-asdfgasd.hbs diff --git a/js/Input.js b/js/Input.js index 3725b3d..654b6b4 100644 --- a/js/Input.js +++ b/js/Input.js @@ -7,7 +7,7 @@ class Input { function (e) { // e = event //this = element clicked - functionCallback(e, this, args); + functionCallback(e, ...args); //if you need to access the event or this variable, you need to add them //when you define the callback, but you cant use the word this, eg: //on('click', menuButton, function (e, button) {}); @@ -20,7 +20,7 @@ class Input { //loop through children and add onClick listener for (var i = 0; i < children.length; i++) { - on(event, children[i], functionCallback, args); + on(event, children[i], functionCallback, ...args); } } } \ No newline at end of file diff --git a/js/_presets.js b/js/PresetModule.js similarity index 97% rename from js/_presets.js rename to js/PresetModule.js index 955f243..0b8d5eb 100644 --- a/js/_presets.js +++ b/js/PresetModule.js @@ -17,6 +17,7 @@ const PresetModule = (() => { presetsMenu.appendChild(button); button.addEventListener('click', () => { + console.log("Preset: " + presetName); //change dimentions on new pixel form Util.setValue('size-width', presets[presetName].width); Util.setValue('size-height', presets[presetName].height); @@ -30,7 +31,6 @@ const PresetModule = (() => { //set the text of the dropdown to the newly selected preset Util.setText('preset-button', presetName); - }); }); diff --git a/js/Startup.js b/js/Startup.js index b4d0638..aa5257a 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -1,3 +1,264 @@ const Startup = (() => { + + let firstPixel = true; + let splashPostfix = ''; + + Input.on('click', 'create-button', create, false); + Input.on('click', 'create-button-splash', create, true); + + function create(e, isSplash) { + // If I'm creating from the splash menu, I append '-splash' so I get the corresponding values + if (isSplash) { + splashPostfix = '-splash'; + } + else { + splashPostfix = ''; + } + + console.log("New pixel"); + var width = Util.getValue('size-width' + splashPostfix); + var height = Util.getValue('size-height' + splashPostfix); + var selectedPalette = Util.getText('palette-button' + splashPostfix); + + newPixel(width, height); + + // If I'm not creating from the splash page, then this is not the first project I've created + if (!isSplash) + document.getElementById('new-pixel-warning').style.display = 'block'; + + resetInput(); + + //track google event + if (typeof ga !== 'undefined') + ga('send', 'event', 'Pixel Editor New', selectedPalette, width+'/'+height); /*global ga*/ + } + + /** TODO: + * - Remove firstPixel: it's enough to pass to newPixel whether it's been called from the splash page or not + * - Divide functions depending on their purpose: + * - initLayers() + * - initPalette() + * - openLPE() + */ + + /** Creates a new, empty file + * + * @param {*} width Start width of the canvas + * @param {*} height Start height of the canvas + * @param {*} fileContent If fileContent != null, then the newPixel is being called from the open menu + */ + function newPixel (width, height, fileContent = null) { + // The palette is empty, at the beginning + ColorModule.resetPalette(); + + initLayers(width, height); + initPalette(); + + //fill background of canvas with bg color + fillCheckerboard(); + fillPixelGrid(); + + // Closing the "New Pixel dialogue" + Dialogue.closeDialogue(); + // Updating the cursor of the current tool + currentTool.updateCursor(); + + // The user is now able to export the Pixel + document.getElementById('export-button').classList.remove('disabled'); + documentCreated = true; + + // This is not the first Pixel anymore + firstPixel = false; + + // Now, if I opened an LPE file + if (fileContent != null) { + loadLPE(fileContent); + // Deleting the default layer + deleteLayer(false); + } + } + + function initLayers(width, height) { + // If this is the first pixel I'm creating since the app has started + if (firstPixel) { + // I configure the layers elements + layerListEntry = layerList.firstElementChild; + + // Creating the first layer + currentLayer = new Layer(width, height, canvas, layerListEntry); + currentLayer.canvas.style.zIndex = 2; + } + else { + // If it's not the first Pixel, I have to reset the app + + // Deleting all the extra layers and canvases, leaving only one + let nLayers = layers.length; + for (let i=2; i < layers.length - nAppLayers; i++) { + let currentEntry = layers[i].menuEntry; + let associatedLayer; + + if (currentEntry != null) { + // Getting the associated layer + associatedLayer = getLayerByID(currentEntry.id); + + // Deleting its canvas + associatedLayer.canvas.remove(); + + // Adding the id to the unused ones + unusedIDs.push(currentEntry.id); + // Removing the entry from the menu + currentEntry.remove(); + } + } + + // Removing the old layers from the list + for (let i=2; i 0) { + colors[0].parentElement.remove(); + } + + // If the user selected a palette and isn't opening a file, I load the selected palette + if (selectedPalette != 'Choose a palette...') { + //if this palette isnt the one specified in the url, then reset the url + if (!palettes[selectedPalette].specified) + history.pushState(null, null, '/pixel-editor'); + + //fill the palette with specified colours + createColorPalette(palettes[selectedPalette].colors,true); + } + // Otherwise, I just generate 2 semirandom colours + else { + //this wasn't a specified palette, so reset the url + history.pushState(null, null, '/pixel-editor'); + + //generate default colors + var fg = new Color("hsv", Math.floor(Math.random()*360), 50, 50).rgb; + var bg = new Color("hsv", Math.floor(Math.random()*360), 80, 100).rgb; + + //convert colors to hex + var defaultForegroundColor = Color.rgbToHex(fg); + var defaultBackgroundColor = Color.rgbToHex(bg); + + //add colors to palette + ColorModule.addColor(defaultForegroundColor).classList.add('selected'); + ColorModule.addColor(defaultBackgroundColor); + + //set current drawing color as foreground color + currentLayer.context.fillStyle = '#'+defaultForegroundColor; + currentGlobalColor = '#' + defaultForegroundColor; + selectedPalette = 'none'; + } + } + + // OPTIMIZABLE: should probably moved to a FileManagement class or something + function loadLPE(fileContent) { + // I add every layer the file had in it + for (let i=0; i 0) { - colors[0].parentElement.remove(); - } - - //add colors from selected palette - var selectedPalette; - if (!firstPixel) - var selectedPalette = Util.getText('palette-button'); - else - var selectedPalette = Util.getText('palette-button-splash'); - - // 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 this palette isnt the one specified in the url, then reset the url - if (!palettes[selectedPalette].specified) - history.pushState(null, null, '/pixel-editor'); - - //fill the palette with specified colours - createColorPalette(palettes[selectedPalette].colors,true); - } - // Otherwise, I just generate 2 semirandom colours - else if (fileContent == null) { - //this wasn't a specified palette, so reset the url - history.pushState(null, null, '/pixel-editor'); - - //generate default colors - var fg = new Color("hsv", Math.floor(Math.random()*360), 50, 50).rgb; - var bg = new Color("hsv", Math.floor(Math.random()*360), 80, 100).rgb; - - //convert colors to hex - var defaultForegroundColor = Color.rgbToHex(fg); - var defaultBackgroundColor = Color.rgbToHex(bg); - - //add colors to palette - ColorModule.addColor(defaultForegroundColor).classList.add('selected'); - ColorModule.addColor(defaultBackgroundColor); - - //set current drawing color as foreground color - currentLayer.context.fillStyle = '#'+defaultForegroundColor; - currentGlobalColor = '#' + defaultForegroundColor; - selectedPalette = 'none'; - } - - //fill background of canvas with bg color - fillCheckerboard(); - fillPixelGrid(); - - //reset undo and redo states - undoStates = []; - redoStates = []; - - // Closing the "New Pixel dialogue" - Dialogue.closeDialogue(); - // Updating the cursor of the current tool - currentTool.updateCursor(); - - // The user is now able to export the Pixel - document.getElementById('export-button').classList.remove('disabled'); - documentCreated = true; - - // This is not the first Pixel anymore - firstPixel = false; - - // Now, if I opened an LPE file - if (fileContent != null) { - // I add every layer the file had in it - for (let i=0; i

Load

-

New Gameboy

-

New C64

-

New Pico8

-

New 16x16

-

New 32x32

-

New 64x64

-

New 128x128

-

New 256x256

-

New 512x512

+

New Gameboy

+

New C64

+

New Pico8

+

New 16x16

+

New 32x32

+

New 64x64

+

New 128x128

+

New 256x256

+

New 512x512

From 9540002c6e0ddf4b6730e980039bd5198f420889 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Thu, 15 Jul 2021 18:43:59 +0200 Subject: [PATCH 22/91] Moved popup windows into a specific folder --- build.js | 2 +- views/index.hbs | 20 +++++++++---------- views/{about-popup.hbs => popups/about.hbs} | 0 .../canvas-resize.hbs} | 0 .../changelog.hbs} | 0 .../{credits-popup.hbs => popups/credits.hbs} | 0 views/{help-popup.hbs => popups/help.hbs} | 0 .../new-pixel.hbs} | 0 .../{palette-popup.hbs => popups/palette.hbs} | 0 .../settings.hbs} | 0 .../splash-page.hbs} | 0 .../sprite-resize.hbs} | 0 12 files changed, 11 insertions(+), 11 deletions(-) rename views/{about-popup.hbs => popups/about.hbs} (100%) rename views/{canvas-resize-popup.hbs => popups/canvas-resize.hbs} (100%) rename views/{changelog-popup.hbs => popups/changelog.hbs} (100%) rename views/{credits-popup.hbs => popups/credits.hbs} (100%) rename views/{help-popup.hbs => popups/help.hbs} (100%) rename views/{start-pixel-popup.hbs => popups/new-pixel.hbs} (100%) rename views/{palette-popup.hbs => popups/palette.hbs} (100%) rename views/{settings-popup.hbs => popups/settings.hbs} (100%) rename views/{splash-page-popup.hbs => popups/splash-page.hbs} (100%) rename views/{sprite-resize-popup.hbs => popups/sprite-resize.hbs} (100%) diff --git a/build.js b/build.js index 607a923..5bb5b13 100644 --- a/build.js +++ b/build.js @@ -49,7 +49,7 @@ function compile_page(){ .pipe(include({includePaths: ['/svg']})) .pipe(handlebars({encoding: 'utf8', debug: true, bustCache: true}) - .partials('./views/[!index]*.hbs') + .partials('./views/[!index]*.hbs').partials('./views/popups/*.hbs') //.helpers({ svg: hb_svg }) .helpers('./helpers/**/*.js') .data({ diff --git a/views/index.hbs b/views/index.hbs index db5ce38..fab89c4 100644 --- a/views/index.hbs +++ b/views/index.hbs @@ -26,16 +26,16 @@ {{> holders}}
- {{> start-pixel-popup}} - {{> splash-page-popup}} - {{> sprite-resize-popup}} - {{> canvas-resize-popup}} - {{> palette-popup}} - {{> help-popup}} - {{> about-popup}} - {{> changelog-popup}} - {{> credits-popup}} - {{> settings-popup}} + {{> new-pixel}} + {{> splash-page}} + {{> sprite-resize}} + {{> canvas-resize}} + {{> palette}} + {{> help}} + {{> about}} + {{> changelog}} + {{> credits}} + {{> settings}}
diff --git a/views/about-popup.hbs b/views/popups/about.hbs similarity index 100% rename from views/about-popup.hbs rename to views/popups/about.hbs diff --git a/views/canvas-resize-popup.hbs b/views/popups/canvas-resize.hbs similarity index 100% rename from views/canvas-resize-popup.hbs rename to views/popups/canvas-resize.hbs diff --git a/views/changelog-popup.hbs b/views/popups/changelog.hbs similarity index 100% rename from views/changelog-popup.hbs rename to views/popups/changelog.hbs diff --git a/views/credits-popup.hbs b/views/popups/credits.hbs similarity index 100% rename from views/credits-popup.hbs rename to views/popups/credits.hbs diff --git a/views/help-popup.hbs b/views/popups/help.hbs similarity index 100% rename from views/help-popup.hbs rename to views/popups/help.hbs diff --git a/views/start-pixel-popup.hbs b/views/popups/new-pixel.hbs similarity index 100% rename from views/start-pixel-popup.hbs rename to views/popups/new-pixel.hbs diff --git a/views/palette-popup.hbs b/views/popups/palette.hbs similarity index 100% rename from views/palette-popup.hbs rename to views/popups/palette.hbs diff --git a/views/settings-popup.hbs b/views/popups/settings.hbs similarity index 100% rename from views/settings-popup.hbs rename to views/popups/settings.hbs diff --git a/views/splash-page-popup.hbs b/views/popups/splash-page.hbs similarity index 100% rename from views/splash-page-popup.hbs rename to views/popups/splash-page.hbs diff --git a/views/sprite-resize-popup.hbs b/views/popups/sprite-resize.hbs similarity index 100% rename from views/sprite-resize-popup.hbs rename to views/popups/sprite-resize.hbs From f76d05bffa0c163ba9a280f09fdcd7de0d489379 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Thu, 15 Jul 2021 22:21:19 +0200 Subject: [PATCH 23/91] Added FileManager and TopMenuModule The TopMenuModule binds the buttons so that they open the sub menus: at the moment it also binds those events that don't have a proper place yet. FileManager contains all the functions that have something to do with files, that is loading, opening, saving and exporting. --- js/FileManager.js | 197 +++++++++++++++++++++++++++++++++++++ js/History.js | 6 +- js/Input.js | 7 +- js/Startup.js | 4 +- js/TopMenuModule.js | 97 +++++++++++++++++++ js/_fileMenu.js | 229 -------------------------------------------- js/_layer.js | 3 +- js/_loadImage.js | 53 ---------- js/_mouseEvents.js | 2 +- js/pixel-editor.js | 4 +- 10 files changed, 303 insertions(+), 299 deletions(-) create mode 100644 js/FileManager.js create mode 100644 js/TopMenuModule.js delete mode 100644 js/_fileMenu.js delete mode 100644 js/_loadImage.js diff --git a/js/FileManager.js b/js/FileManager.js new file mode 100644 index 0000000..e5fd58d --- /dev/null +++ b/js/FileManager.js @@ -0,0 +1,197 @@ +const FileManager = (() => { + + // Binding the browse holder change event to file loading + const browseHolder = document.getElementById('open-image-browse-holder'); + Input.on('change', browseHolder, loadFile); + + function saveProject() { + //create name + let fileName; + let selectedPalette = Util.getText('palette-button'); + + if (selectedPalette != 'Choose a palette...'){ + let paletteAbbreviation = palettes[selectedPalette].abbreviation; + fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.lpe'; + } else { + fileName = 'pixel-'+canvasSize[0]+'x'+canvasSize[1]+'.lpe'; + selectedPalette = 'none'; + } + + //set download link + const linkHolder = document.getElementById('save-project-link-holder'); + // create file content + const content = getProjectData(); + + linkHolder.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(content); + linkHolder.download = fileName; + linkHolder.click(); + + if (typeof ga !== 'undefined') + ga('send', 'event', 'Pixel Editor Save', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/ + } + + function exportProject() { + if (documentCreated) { + //create name + var selectedPalette = Util.getText('palette-button'); + if (selectedPalette != 'Choose a palette...'){ + var paletteAbbreviation = palettes[selectedPalette].abbreviation; + var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.png'; + } else { + var fileName = 'pixel-'+canvasSize[0]+'x'+canvasSize[1]+'.png'; + selectedPalette = 'none'; + } + + //set download link + var linkHolder = document.getElementById('save-image-link-holder'); + // Creating a tmp canvas to flatten everything + var exportCanvas = document.createElement("canvas"); + var emptyCanvas = document.createElement("canvas"); + var layersCopy = layers.slice(); + + exportCanvas.width = canvasSize[0]; + exportCanvas.height = canvasSize[1]; + + emptyCanvas.width = canvasSize[0]; + emptyCanvas.height = canvasSize[1]; + + // Sorting the layers by z index + layersCopy.sort((a, b) => (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1); + + // Merging every layer on the export canvas + for (let i=0; i (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1); + // save canvas size + dictionary['canvasWidth'] = currentLayer.canvasSize[0]; + dictionary['canvasHeight'] = currentLayer.canvasSize[1]; + // save editor mode + dictionary['editorMode'] = pixelEditorMode; + // save palette + for (let i=0; i { const undoLogStyle = 'background: #87ff1c; color: black; padding: 5px;'; let undoStates = []; let redoStates = []; + + Input.on('click', 'undo-button', undo); + Input.on('click', 'redo-button', redo); //rename to add undo state function saveHistoryState (state) { - console.log("saved history"); - console.log(state); //get current canvas data and save to undoStates array undoStates.push(state); diff --git a/js/Input.js b/js/Input.js index 654b6b4..a518709 100644 --- a/js/Input.js +++ b/js/Input.js @@ -5,12 +5,7 @@ class Input { element.addEventListener(event, function (e) { - // e = event - //this = element clicked - functionCallback(e, ...args); - //if you need to access the event or this variable, you need to add them - //when you define the callback, but you cant use the word this, eg: - //on('click', menuButton, function (e, button) {}); + functionCallback(...args, e); }); } diff --git a/js/Startup.js b/js/Startup.js index aa5257a..3e70ab5 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -90,8 +90,6 @@ const Startup = (() => { currentLayer.canvas.style.zIndex = 2; } else { - // If it's not the first Pixel, I have to reset the app - // Deleting all the extra layers and canvases, leaving only one let nLayers = layers.length; for (let i=2; i < layers.length - nAppLayers; i++) { @@ -198,7 +196,7 @@ const Startup = (() => { } } - // OPTIMIZABLE: should probably moved to a FileManagement class or something + // REFACTOR: should probably moved to a FileManagement class or something function loadLPE(fileContent) { // I add every layer the file had in it for (let i=0; i { + + const mainMenuItems = document.getElementById('main-menu').children; + + initMenu(); + + function initMenu() { + //for each button in main menu (starting at 1 to avoid logo) + for (let i = 1; i < mainMenuItems.length; i++) { + + //get the button that's in the list item + const menuItem = mainMenuItems[i]; + const menuButton = menuItem.children[0]; + + //when you click a main menu items button + Input.on('click', menuButton, function (e) { + // Select the item + Util.select(e.target.parentElement); + }); + + const subMenu = menuItem.children[1]; + const subMenuItems = subMenu.children; + + //when you click an item within a menu button + for (var j = 0; j < subMenuItems.length; j++) { + + const currSubmenuItem = subMenuItems[j]; + const currSubmenuButton = currSubmenuItem.children[0]; + + switch (currSubmenuButton.textContent) { + case 'New': + Input.on('click', currSubmenuButton, Dialogue.showDialogue, 'new-pixel'); + break; + case 'Save project': + Input.on('click', currSubmenuButton, FileManager.saveProject); + break; + case 'Open': + Input.on('click', currSubmenuButton, FileManager.open); + break; + case 'Export': + Input.on('click', currSubmenuButton, FileManager.exportProject); + break; + case 'Exit': + //if a document exists, make sure they want to delete it + if (documentCreated) { + //ask user if they want to leave + if (confirm('Exiting will discard your current pixel. Are you sure you want to do that?')) + //skip onbeforeunload prompt + window.onbeforeunload = null; + else + e.preventDefault(); + } + break; + // REFACTOR: move the binding to the Selection IIFE or something like that once it's done + case 'Paste': + Input.on('click', currSubmenuButton, pasteSelection); + break; + case 'Copy': + Input.on('click', currSubmenuButton, copySelection); + break; + case 'Cut': + Input.on('click', currSubmenuButton, cutSelectionTool); + break; + case 'Cancel': + Input.on('click', currSubmenuButton, tool.pencil.switchTo); + break; + //Help Menu + case 'Settings': + //fill form with current settings values + //Util.setValue('setting-numberOfHistoryStates', settings.numberOfHistoryStates); + Input.on('click', currSubmenuButton, Dialogue.showDialogue, 'settings'); + break; + case 'Help': + Input.on('click', currSubmenuButton, Dialogue.showDialogue, 'help'); + break; + case 'About': + Input.on('click', currSubmenuButton, Dialogue.showDialogue, 'about'); + break; + case 'Changelog': + Input.on('click', currSubmenuButton, Dialogue.showDialogue, 'changelog'); + break; + } + } + } + } + + function closeMenu () { + //remove .selected class from all menu buttons + for (var i = 0; i < mainMenuItems.length; i++) { + Util.deselect(mainMenuItems[i]); + } + } + + return { + closeMenu + } +})(); \ No newline at end of file diff --git a/js/_fileMenu.js b/js/_fileMenu.js deleted file mode 100644 index 52733e0..0000000 --- a/js/_fileMenu.js +++ /dev/null @@ -1,229 +0,0 @@ -var mainMenuItems = document.getElementById('main-menu').children; - -//for each button in main menu (starting at 1 to avoid logo) -for (var i = 1; i < mainMenuItems.length; i++) { - - //get the button that's in the list item - var menuItem = mainMenuItems[i]; - var menuButton = menuItem.children[0]; - - //when you click a main menu items button - Input.on('click', menuButton, function (e) { - Util.select(e.target.parentElement); - }); - - var subMenu = menuItem.children[1]; - var subMenuItems = subMenu.children; - - //when you click an item within a menu button - for (var j = 0; j < subMenuItems.length; j++) { - - var subMenuItem = subMenuItems[j]; - var subMenuButton = subMenuItem.children[0]; - - subMenuButton.addEventListener('click', function (e) { - - switch(this.textContent) { - - //File Menu - case 'New': - Dialogue.showDialogue('new-pixel'); - break; - case 'Save project': - //create name - var selectedPalette = Util.getText('palette-button'); - if (selectedPalette != 'Choose a palette...'){ - var paletteAbbreviation = palettes[selectedPalette].abbreviation; - var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.lpe'; - } else { - var fileName = 'pixel-'+canvasSize[0]+'x'+canvasSize[1]+'.lpe'; - selectedPalette = 'none'; - } - - //set download link - var linkHolder = document.getElementById('save-project-link-holder'); - // create file content - var content = getProjectData(); - - linkHolder.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(content); - linkHolder.download = fileName; - linkHolder.click(); - - if (typeof ga !== 'undefined') - ga('send', 'event', 'Pixel Editor Save', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/ - - break; - case 'Open': - //if a document exists - if (documentCreated) { - //check if the user wants to overwrite - if (confirm('Opening a pixel will discard your current one. Are you sure you want to do that?')) - //open file selection dialog - document.getElementById('open-image-browse-holder').click(); - } - else - //open file selection dialog - document.getElementById('open-image-browse-holder').click(); - - break; - - case 'Export': - if (documentCreated) { - //create name - var selectedPalette = Util.getText('palette-button'); - if (selectedPalette != 'Choose a palette...'){ - var paletteAbbreviation = palettes[selectedPalette].abbreviation; - var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.png'; - } else { - var fileName = 'pixel-'+canvasSize[0]+'x'+canvasSize[1]+'.png'; - selectedPalette = 'none'; - } - - //set download link - var linkHolder = document.getElementById('save-image-link-holder'); - // Creating a tmp canvas to flatten everything - var exportCanvas = document.createElement("canvas"); - var emptyCanvas = document.createElement("canvas"); - var layersCopy = layers.slice(); - - exportCanvas.width = canvasSize[0]; - exportCanvas.height = canvasSize[1]; - - emptyCanvas.width = canvasSize[0]; - emptyCanvas.height = canvasSize[1]; - - // Sorting the layers by z index - layersCopy.sort((a, b) => (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1); - - // Merging every layer on the export canvas - for (let i=0; i (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1); - // save canvas size - dictionary['canvasWidth'] = currentLayer.canvasSize[0]; - dictionary['canvasHeight'] = currentLayer.canvasSize[1]; - // save editor mode - dictionary['editorMode'] = pixelEditorMode; - // save palette - for (let i=0; i Date: Thu, 15 Jul 2021 22:26:08 +0200 Subject: [PATCH 24/91] Removed onLoad and checkCompatibility --- js/_checkCompatibility.js | 19 ------------ js/_onLoad.js | 64 --------------------------------------- js/pixel-editor.js | 53 +++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 84 deletions(-) delete mode 100644 js/_checkCompatibility.js diff --git a/js/_checkCompatibility.js b/js/_checkCompatibility.js deleted file mode 100644 index 9edfb11..0000000 --- a/js/_checkCompatibility.js +++ /dev/null @@ -1,19 +0,0 @@ -/////=include libraries/bowser.js - -function closeCompatibilityWarning () { - document.getElementById('compatibility-warning').style.visibility = 'hidden'; -} - -console.log('checking compatibility'); - -//check browser/version -if ((bowser.msie && bowser.version < 11) || - (bowser.firefox && bowser.version < 28) || - (bowser.chrome && bowser.version < 29) || - (bowser.msedge && bowser.version < 12) || - (bowser.safari && bowser.version < 9) || - (bowser.opera && bowser.version < 17) ) - //show warning - document.getElementById('compatibility-warning').style.visibility = 'visible'; - -else alert(bowser.name+' '+bowser.version+' is fine!'); diff --git a/js/_onLoad.js b/js/_onLoad.js index 6d649fd..e69de29 100644 --- a/js/_onLoad.js +++ b/js/_onLoad.js @@ -1,64 +0,0 @@ - - - - -//when the page is done loading, you can get ready to start -window.onload = function () { - - featureToggles.onLoad(); - - 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'); - - //show splash screen - Dialogue.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]; - - //create new document - Startup.newPixel(width, height); - } - - //dimentions were not specified -- show splash screen with palette preselected - else { - //show splash - Dialogue.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 - Dialogue.showDialogue('splash', false); - }); - } -}; \ No newline at end of file diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 9cbcb75..91fde5a 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -64,4 +64,55 @@ //=include _featureToggles.js // Controls execution of this preset module -PresetModule.instrumentPresetMenu(); \ No newline at end of file +PresetModule.instrumentPresetMenu(); + +//when the page is done loading, you can get ready to start +window.onload = function () { + featureToggles.onLoad(); + + currentTool.updateCursor(); + + //check if there are any url parameters + if (window.location.pathname.replace('/pixel-editor/','').length <= 1) { + //show splash screen + Dialogue.showDialogue('splash', false); + } + //url parameters were specified + else { + 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 + 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]; + + //create new document + Startup.newPixel(width, height); + } + //dimentions were not specified -- show splash screen with palette preselected + else { + //show splash + Dialogue.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 + Dialogue.showDialogue('splash', false); + }); + } +}; \ No newline at end of file From 68dbbdc4c3576972cbd8a7e151e44c2dae4db202 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Thu, 15 Jul 2021 23:30:55 +0200 Subject: [PATCH 25/91] Tried fixing pan bug If you load an LPE file, the pan tool screws up --- js/FileManager.js | 1 - js/Startup.js | 17 ++++------------- js/_layer.js | 2 +- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/js/FileManager.js b/js/FileManager.js index e5fd58d..27e0ed0 100644 --- a/js/FileManager.js +++ b/js/FileManager.js @@ -153,7 +153,6 @@ const FileManager = (() => { // Converting the data to a json object and creating a new pixel (see _newPixel.js for more) reader.onload = function (e) { let dictionary = JSON.parse(e.target.result); - let mode = dictionary['editorMode']; Startup.newPixel(dictionary['canvasWidth'], dictionary['canvasHeight'], dictionary); } } diff --git a/js/Startup.js b/js/Startup.js index 3e70ab5..792bdbd 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -6,7 +6,7 @@ const Startup = (() => { Input.on('click', 'create-button', create, false); Input.on('click', 'create-button-splash', create, true); - function create(e, isSplash) { + function create(isSplash) { // If I'm creating from the splash menu, I append '-splash' so I get the corresponding values if (isSplash) { splashPostfix = '-splash'; @@ -34,14 +34,6 @@ const Startup = (() => { ga('send', 'event', 'Pixel Editor New', selectedPalette, width+'/'+height); /*global ga*/ } - /** TODO: - * - Remove firstPixel: it's enough to pass to newPixel whether it's been called from the splash page or not - * - Divide functions depending on their purpose: - * - initLayers() - * - initPalette() - * - openLPE() - */ - /** Creates a new, empty file * * @param {*} width Start width of the canvas @@ -73,7 +65,7 @@ const Startup = (() => { // Now, if I opened an LPE file if (fileContent != null) { - loadLPE(fileContent); + loadFromLPE(fileContent); // Deleting the default layer deleteLayer(false); } @@ -196,8 +188,7 @@ const Startup = (() => { } } - // REFACTOR: should probably moved to a FileManagement class or something - function loadLPE(fileContent) { + function loadFromLPE(fileContent) { // I add every layer the file had in it for (let i=0; i { const presetProperties = PresetModule.propertiesOf(preset); Util.setText('palette-button-splash', presetProperties.palette); Util.setText('palette-button', presetProperties.palette); - + x = presetProperties.width; y = presetProperties.height; } diff --git a/js/_layer.js b/js/_layer.js index a441bfb..43457fe 100644 --- a/js/_layer.js +++ b/js/_layer.js @@ -397,7 +397,7 @@ function deleteLayer(saveHistory = true) { layers[layerIndex + 1].selectLayer(); } // or the previous one if the next one doesn't exist - else if (layerIndex != 1) { + else { layers[layerIndex - 1].selectLayer(); } From b8ae07adfff30f0acb763e406989c9549e840d94 Mon Sep 17 00:00:00 2001 From: Leamsi Escribano Date: Sun, 18 Jul 2021 10:03:46 -0500 Subject: [PATCH 26/91] audit fix and pan issue fixed --- js/Startup.js | 3 +- package-lock.json | 389 +++++++++++++++++++++++++++++++++++++--------- package.json | 2 +- 3 files changed, 320 insertions(+), 74 deletions(-) diff --git a/js/Startup.js b/js/Startup.js index 792bdbd..81d5a7e 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -108,8 +108,7 @@ const Startup = (() => { } // Setting up the current layer - layers[1] = new Layer(width, height, layers[1].canvas, layers[1].menuEntry); - currentLayer = layers[1]; + currentLayer = new Layer(width, height, canvas, layerListEntry); currentLayer.canvas.style.zIndex = 2; // Updating canvas size to the new size diff --git a/package-lock.json b/package-lock.json index a756d4c..a8f2f7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -787,24 +787,72 @@ } }, "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -813,10 +861,31 @@ "is-extglob": "^2.1.1" } }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } } } }, @@ -2884,6 +2953,40 @@ "is-negated-glob": "^1.0.0", "just-debounce": "^1.0.0", "object.defaults": "^1.1.0" + }, + "dependencies": { + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + } } }, "global-dirs": { @@ -3123,9 +3226,9 @@ } }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "requires": { "minimist": "^1.2.5", "neo-async": "^2.6.0", @@ -3244,9 +3347,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "http-cache-semantics": { "version": "4.1.0", @@ -4152,9 +4255,9 @@ } }, "node-sass": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz", - "integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", "requires": { "async-foreach": "^0.1.3", "chalk": "^1.1.1", @@ -4170,16 +4273,26 @@ "node-gyp": "^3.8.0", "npmlog": "^4.0.0", "request": "^2.88.0", - "sass-graph": "^2.2.4", + "sass-graph": "2.2.5", "stdout-stream": "^1.4.0", "true-case-path": "^1.0.2" }, "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -4192,10 +4305,165 @@ "supports-color": "^2.0.0" } }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "sass-graph": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^13.3.2" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -4360,9 +4628,9 @@ } }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" }, "now-and-later": { "version": "2.0.1", @@ -4660,9 +4928,9 @@ } }, "trim-newlines": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", - "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==" }, "yargs-parser": { "version": "18.1.3", @@ -5173,37 +5441,27 @@ } }, "reload": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/reload/-/reload-3.1.1.tgz", - "integrity": "sha512-JblFn8P8CUfKqpclWNGs6rhda4hmywTq/a8DyjmwoGZ7Lp2krZ3swXgU3guvZ0waI3rorXFVS6z6UkKLYulmMA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/reload/-/reload-3.2.0.tgz", + "integrity": "sha512-30iJoDvFHGbfq6tT3Vag/4RV3wkpuCOqPSM3GyeuOSSo48wKfZT/iI19oeO0GCVX0XSr+44XJ6yBiRJWqOq+sw==", "dev": true, "requires": { "cli-color": "~2.0.0", - "commander": "~6.1.0", + "commander": "~7.2.0", "finalhandler": "~1.1.1", "minimist": "~1.2.0", - "open": "^7.0.0", + "open": "^8.0.0", "serve-static": "~1.14.0", "supervisor": "~0.12.0", - "url-parse": "~1.4.4", - "ws": "~7.3.0" + "url-parse": "~1.5.0", + "ws": "~7.4.0" }, "dependencies": { "commander": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz", - "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true - }, - "open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, - "requires": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - } } } }, @@ -5449,17 +5707,6 @@ "chokidar": ">=2.0.0 <4.0.0" } }, - "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", - "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" - } - }, "scss-tokenizer": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", @@ -6504,9 +6751,9 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", + "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", "dev": true, "requires": { "querystringify": "^2.1.1", @@ -6807,9 +7054,9 @@ } }, "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", "dev": true }, "xdg-basedir": { @@ -6823,9 +7070,9 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" }, "yallist": { "version": "2.1.2", diff --git a/package.json b/package.json index 0e2ad92..3469e9b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ }, "devDependencies": { "cross-env": "7.0.3", - "reload": "^3.1.1", + "reload": "^3.2.0", "wait-cli": "^1.0.0" } } From 7976675132afc3a0f1d9b9198c49bcb4018c86fe Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 18 Jul 2021 22:44:31 +0200 Subject: [PATCH 27/91] Moved some of _pixelEditorUtility.js functions to proper files Also left some comments about where to put the leftover functions once we have a more detailed structure. --- js/ColorModule.js | 2 +- js/Input.js | 27 +++++++++ js/Util.js | 21 +++++++ js/_layer.js | 41 +++++++++++++- js/_mouseEvents.js | 2 +- js/_pixelEditorUtility.js | 115 +++----------------------------------- 6 files changed, 95 insertions(+), 113 deletions(-) diff --git a/js/ColorModule.js b/js/ColorModule.js index 7f513e8..1c51028 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -18,7 +18,7 @@ const ColorModule = (() => { animation:100, filter: ".noshrink", draggable: ".draggable-colour", - onEnd: makeIsDraggingFalse + onEnd: function() {dragging = false} }); /** Changes all of one color to another after being changed from the color picker diff --git a/js/Input.js b/js/Input.js index a518709..ecb73ba 100644 --- a/js/Input.js +++ b/js/Input.js @@ -1,4 +1,31 @@ class Input { + /** Used to programmatically create an input event + * + * @param {*} keyCode KeyCode of the key to press + * @param {*} ctrl Is ctrl pressed? + * @param {*} alt Is alt pressed? + * @param {*} shift Is shift pressed? + */ + static simulateInput(keyCode, ctrl, alt, shift) { + // I just copy pasted this from stack overflow lol please have mercy + let keyboardEvent = document.createEvent("KeyboardEvent"); + let initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? "initKeyboardEvent" : "initKeyEvent"; + + keyboardEvent[initMethod]( + "keydown", // event type: keydown, keyup, keypress + true, // bubbles + true, // cancelable + window, // view: should be window + ctrl, // ctrlKey + alt, // altKey + shift, // shiftKey + false, // metaKey + keyCode, // keyCode: unsigned long - the virtual key code, else 0 + keyCode // charCode: unsigned long - the Unicode character associated with the depressed key, else 0 + ); + document.dispatchEvent(keyboardEvent); + } + static on(event, elementId, functionCallback, ...args) { //if element provided is string, get the actual element const element = Util.getElement(elementId); diff --git a/js/Util.js b/js/Util.js index 772b7a3..76a716c 100644 --- a/js/Util.js +++ b/js/Util.js @@ -1,5 +1,26 @@ // Acts as a public static class class Util { + + /** Tells if element is a child of an element with class className + * + * @param {*} element + * @param {*} className + */ + static isChildOfByClass(element, className) { + // Getting the element with class className + while (element != null && element.classList != null && !element.classList.contains(className)) { + element = element.parentElement; + } + + // If that element exists and its class is the correct one + if (element != null && element.classList != null && element.classList.contains(className)) { + // Then element is a chld of an element with class className + return true; + } + + return false; + } + /** Returns elementOrElementId if the argument is already an element, otherwise it finds * the element by its ID (given by the argument) and returns it * diff --git a/js/_layer.js b/js/_layer.js index 43457fe..b773d69 100644 --- a/js/_layer.js +++ b/js/_layer.js @@ -467,8 +467,6 @@ function duplicateLayer(event, saveHistory = true) { } function renameLayer(event) { - let layerIndex = layers.indexOf(currentLayer); - let toRename = currentLayer; let p = currentLayer.menuEntry.getElementsByTagName("p")[0]; oldLayerName = p.innerHTML; @@ -477,7 +475,7 @@ function renameLayer(event) { p.classList.add("layer-name-editable"); p.focus(); - simulateInput(65, true, false, false); + Input.simulateInput(65, true, false, false); isRenamingLayer = true; } @@ -597,6 +595,43 @@ function layerDragDrop(event) { dragging = false; } + +/** Merges topLayer onto belowLayer + * + * @param {*} belowLayer The layer on the bottom of the layer stack + * @param {*} topLayer The layer on the top of the layer stack + */ +function mergeLayers(belowLayer, topLayer) { + // Copying the above content on the layerBelow + let belowImageData = belowLayer.getImageData(0, 0, canvas.width, canvas.height); + let toMergeImageData = topLayer.getImageData(0, 0, canvas.width, canvas.height); + + for (let i=0; i
diff --git a/views/pixel-export-popup.hbs b/views/popups/pixel-export.hbs similarity index 84% rename from views/pixel-export-popup.hbs rename to views/popups/pixel-export.hbs index 17fa4d3..6642fe7 100644 --- a/views/pixel-export-popup.hbs +++ b/views/popups/pixel-export.hbs @@ -5,7 +5,7 @@

File Name

- +
- - + +
\ No newline at end of file From b2f55217507ba237c94d23ceb9aa011eda1dc345 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Mon, 6 Dec 2021 17:37:43 +0100 Subject: [PATCH 80/91] Removed all global variables, worked on File class and put canvas resizing functions in File --- js/ColorModule.js | 17 +- js/EditorState.js | 6 +- js/File.js | 327 ++++++++++++++++++++++++++- js/FileManager.js | 30 +-- js/History.js | 76 +++---- js/Input.js | 6 +- js/LayerList.js | 100 ++++---- js/Settings.js | 2 +- js/Startup.js | 51 ++--- js/Tool.js | 18 +- js/ToolManager.js | 2 +- js/_resizeCanvas.js | 311 ------------------------- js/_resizeSprite.js | 40 ++-- js/data/variables.js | 27 --- js/layers/Checkerboard.js | 14 +- js/layers/Layer.js | 60 ++--- js/layers/PixelGrid.js | 2 +- js/lib/jscolor.js | 1 - js/pixel-editor.js | 4 +- js/tools/BrushTool.js | 10 +- js/tools/EraserTool.js | 10 +- js/tools/EyeDropperTool.js | 16 +- js/tools/FillTool.js | 24 +- js/tools/LineTool.js | 24 +- js/tools/MoveSelectionTool.js | 36 +-- js/tools/PanTool.js | 12 +- js/tools/RectangleTool.js | 34 ++- js/tools/RectangularSelectionTool.js | 34 +-- js/tools/ResizableTool.js | 2 +- js/tools/ZoomTool.js | 70 +++--- js/{ => tools}/_ellipse.js | 0 views/main-menu.hbs | 6 +- 32 files changed, 668 insertions(+), 704 deletions(-) delete mode 100644 js/data/variables.js rename js/{ => tools}/_ellipse.js (100%) diff --git a/js/ColorModule.js b/js/ColorModule.js index 80019a2..2a194e6 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -318,7 +318,7 @@ const ColorModule = (() => { if (typeof newColor === 'string') newColor = Color.hexToRgb(newColor); //create temporary image from canvas to search through - var tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + var tempImage = currFile.currentLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); //loop through all pixels for (var i=0;i { } //put temp image back onto canvas - currentLayer.context.putImageData(tempImage,0,0); + currFile.currentLayer.context.putImageData(tempImage,0,0); } function getCurrentPalette() { @@ -395,9 +395,10 @@ const ColorModule = (() => { //create array out of colors object let colorPaletteArray = []; - for (let i=0; i { if (refLayer) color = refLayer.context.fillStyle; - for (let i=0; i { document.getElementById("switch-mode-button").innerHTML = 'Switch to basic mode'; //turn pixel grid off - pixelGrid.togglePixelGrid('off'); + currFile.pixelGrid.togglePixelGrid('off'); } //switch to basic mode else { @@ -32,7 +32,7 @@ const EditorState = (() => { } // Selecting the current layer - currentLayer.selectLayer(); + currFile.currentLayer.selectLayer(); // Flatten the layers LayerList.flatten(true); } @@ -47,7 +47,7 @@ const EditorState = (() => { pixelEditorMode = 'Basic'; document.getElementById("switch-mode-button").innerHTML = 'Switch to advanced mode'; - pixelGrid.togglePixelGrid('on'); + currFile.pixelGrid.togglePixelGrid('on'); } } diff --git a/js/File.js b/js/File.js index 147d5e0..8b0bf82 100644 --- a/js/File.js +++ b/js/File.js @@ -1,12 +1,319 @@ -// A file has layers - // It probably contains the LayerList, which should include the layers array -// A file contains sprite scaling and canvas resizing +class File { + // Canvas, canvas state + canvasSize = []; + zoom = 7; + canvasView = document.getElementById("canvas-view"); -/* - let canvasSize - let canvasView - let layerList + // Layers + layers = []; + currentLayer = undefined; + VFXLayer = undefined; + TMPLayer = undefined; + pixelGrid = undefined; + checkerBoard = undefined - resizeCanvas() - scaleSprite() -*/ \ No newline at end of file + // Canvas resize attributes + // Resize canvas pop up window + resizeCanvasContainer = document.getElementById("resize-canvas"); + // Start pivot + rcPivot = "middle"; + // Selected pivot button + currentPivotObject = undefined; + // Border offsets + rcBorders = {left: 0, right: 0, top: 0, bottom: 0}; + + // Sprite scaling attributes + + openResizeCanvasWindow() { + // Initializes the inputs + this.initResizeCanvasInputs(); + Dialogue.showDialogue('resize-canvas'); + } + + initResizeCanvasInputs() { + // Getting the pivot buttons + let buttons = document.getElementsByClassName("pivot-button"); + + // Adding the event handlers for them + for (let i=0; i= 0; i-=4) { + if (!Util.isPixelEmpty( + [imageData.data[i - 3], imageData.data[i - 2], + -imageData.data[i - 1], imageData.data[i]])) { + pixelPosition = getPixelPosition(i); + + // max x + if (pixelPosition[0] > maxX) { + maxX = pixelPosition[0]; + } + // min x + if (pixelPosition[0] < minX) { + minX = pixelPosition[0]; + } + // max y + if (pixelPosition[1] > maxY) { + maxY = pixelPosition[1]; + } + // min y + if (pixelPosition[1] < minY) { + minY = pixelPosition[1]; + } + } + } + } + + tmp = minY; + minY = maxY; + maxY = tmp; + + minY = currFile.canvasSize[1] - minY; + maxY = currFile.canvasSize[1] - maxY; + + // Setting the borders coherently with the values I've just computed + this.rcBorders.right = (maxX - currFile.canvasSize[0]) + 1; + this.rcBorders.left = -minX; + this.rcBorders.top = maxY - currFile.canvasSize[1] + 1; + this.rcBorders.bottom = -minY; + + // Saving the data + for (let i=0; i { if (selectedPalette != 'Choose a palette...'){ var paletteAbbreviation = palettes[selectedPalette].abbreviation; - var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]; + var fileName = 'pixel-'+paletteAbbreviation+'-'+currFile.canvasSize[0]+'x'+currFile.canvasSize[1]; } else { - var fileName = 'pixel-'+canvasSize[0]+'x'+canvasSize[1]; + var fileName = 'pixel-'+currFile.canvasSize[0]+'x'+currFile.canvasSize[1]; selectedPalette = 'none'; } @@ -33,7 +33,7 @@ const FileManager = (() => { var paletteAbbreviation = palettes[selectedPalette].name; var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.png'; } else { - var fileName = 'pixel-'+canvasSize[0]+'x'+canvasSize[1]+'.png'; + var fileName = 'pixel-'+currFile.canvasSize[0]+'x'+currFile.canvasSize[1]+'.png'; selectedPalette = 'none'; } @@ -58,7 +58,7 @@ const FileManager = (() => { linkHolder.click(); if (typeof ga !== 'undefined') - ga('send', 'event', 'Pixel Editor Save', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/ + ga('send', 'event', 'Pixel Editor Save', selectedPalette, currFile.canvasSize[0]+'/'+currFile.canvasSize[1]); /*global ga*/ } function exportProject() { @@ -70,20 +70,20 @@ const FileManager = (() => { // Creating a tmp canvas to flatten everything var exportCanvas = document.createElement("canvas"); var emptyCanvas = document.createElement("canvas"); - var layersCopy = layers.slice(); + var layersCopy = currFile.layers.slice(); - exportCanvas.width = layers[0].canvasSize[0]; - exportCanvas.height = layers[0].canvasSize[1]; + exportCanvas.width = currFile.canvasSize[0]; + exportCanvas.height = currFile.canvasSize[1]; - emptyCanvas.width = layers[0].canvasSize[0]; - emptyCanvas.height = layers[0].canvasSize[1]; + emptyCanvas.width = currFile.canvasSize[0]; + emptyCanvas.height = currFile.canvasSize[1]; // Sorting the layers by z index layersCopy.sort((a, b) => (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1); // Merging every layer on the export canvas for (let i=0; i { //track google event if (typeof ga !== 'undefined') - ga('send', 'event', 'Pixel Editor Export', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/ + ga('send', 'event', 'Pixel Editor Export', selectedPalette, currFile.canvasSize[0]+'/'+currFile.canvasSize[1]); /*global ga*/ } } @@ -157,7 +157,7 @@ const FileManager = (() => { EditorState.switchMode('Advanced'); //draw the image onto the canvas - currentLayer.context.drawImage(img, 0, 0); + currFile.currentLayer.context.drawImage(img, 0, 0); ColorModule.createPaletteFromLayers(); //track google event @@ -195,11 +195,11 @@ const FileManager = (() => { // use a dictionary let dictionary = {}; // sorting layers by increasing z-index - let layersCopy = layers.slice(); + let layersCopy = currFile.layers.slice(); layersCopy.sort((a, b) => (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1); // save canvas size - dictionary['canvasWidth'] = currentLayer.canvasSize[0]; - dictionary['canvasHeight'] = currentLayer.canvasSize[1]; + dictionary['canvasWidth'] = currFile.canvasSize[0]; + dictionary['canvasHeight'] = currFile.canvasSize[1]; // save editor mode dictionary['editorMode'] = EditorState.getCurrentMode(); // save palette diff --git a/js/History.js b/js/History.js index de11904..1afe5d9 100644 --- a/js/History.js +++ b/js/History.js @@ -108,11 +108,11 @@ class HistoryState { resizeSprite(null, [1 / this.xRatio, 1 / this.yRatio]); // Also putting the old data - for (let i=0; i this.index + 1) { - layers[this.index + 1].selectLayer(); + if (currFile.layers.length - nAppLayers > this.index + 1) { + currFile.layers[this.index + 1].selectLayer(); } else { - layers[this.index - 1].selectLayer(); + currFile.layers[this.index - 1].selectLayer(); } this.added.canvas.remove(); this.added.menuEntry.remove(); - layers.splice(index, 1); + currFile.layers.splice(index, 1); }; this.redo = function() { - canvasView.append(this.added.canvas); + currFile.canvasView.append(this.added.canvas); LayerList.getLayerListEntries().prepend(this.added.menuEntry); layers.splice(this.index, 0, this.added); }; @@ -349,12 +349,12 @@ class HistoryState { //prototype for undoing canvas changes EditCanvas() { - this.canvasState = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - this.layerID = currentLayer.id; + this.canvasState = currFile.currentLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); + this.layerID = currFile.currentLayer.id; this.undo = function () { var stateLayer = LayerList.getLayerByID(this.layerID); - var currentCanvas = stateLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + var currentCanvas = stateLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); stateLayer.context.putImageData(this.canvasState, 0, 0); this.canvasState = currentCanvas; @@ -364,7 +364,7 @@ class HistoryState { this.redo = function () { var stateLayer = LayerList.getLayerByID(this.layerID); - var currentCanvas = stateLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + var currentCanvas = stateLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); stateLayer.context.putImageData(this.canvasState, 0, 0); @@ -390,11 +390,11 @@ class HistoryState { //prototype for undoing deleted colors DeleteColor(colorValue) { this.colorValue = colorValue; - this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + this.canvas = currFile.currentLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); this.undo = function () { - var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - currentLayer.context.putImageData(this.canvas, 0, 0); + var currentCanvas = currFile.currentLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); + currFile.currentLayer.context.putImageData(this.canvas, 0, 0); ColorModule.addColor(this.colorValue); @@ -402,8 +402,8 @@ class HistoryState { }; this.redo = function () { - var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - currentLayer.context.putImageData(this.canvas, 0, 0); + var currentCanvas = currFile.currentLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); + currFile.currentLayer.context.putImageData(this.canvas, 0, 0); ColorModule.deleteColor(this.colorValue); @@ -415,11 +415,11 @@ class HistoryState { EditColor(newColorValue, oldColorValue) { this.newColorValue = newColorValue; this.oldColorValue = oldColorValue; - this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + this.canvas = currFile.currentLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); this.undo = function () { - let currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - currentLayer.context.putImageData(this.canvas, 0, 0); + let currentCanvas = currFile.currentLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); + currFile.currentLayer.context.putImageData(this.canvas, 0, 0); //find new color in palette and change it back to old color let colors = document.getElementsByClassName('color-button'); @@ -435,8 +435,8 @@ class HistoryState { }; this.redo = function () { - let currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - currentLayer.context.putImageData(this.canvas, 0, 0); + let currentCanvas = currFile.currentLayer.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]); + currFile.currentLayer.context.putImageData(this.canvas, 0, 0); //find old color in palette and change it back to new color let colors = document.getElementsByClassName('color-button'); diff --git a/js/Input.js b/js/Input.js index 2f9fd38..03d6c19 100644 --- a/js/Input.js +++ b/js/Input.js @@ -31,7 +31,7 @@ const Input = (() => { currentMouseEvent = event; dragging = false; - if (currentLayer != null && !Util.isChildOfByClass(event.target, "layers-menu-entry")) { + if (currFile.currentLayer != null && !Util.isChildOfByClass(event.target, "layers-menu-entry")) { LayerList.closeOptionsMenu(); } } @@ -49,8 +49,8 @@ const Input = (() => { y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } - x -= currentLayer.canvas.offsetLeft; - y -= currentLayer.canvas.offsetTop; + x -= currFile.currentLayer.canvas.offsetLeft; + y -= currFile.currentLayer.canvas.offsetTop; return [Math.round(x), Math.round(y)]; } diff --git a/js/LayerList.js b/js/LayerList.js index 4407e4b..2b0d546 100644 --- a/js/LayerList.js +++ b/js/LayerList.js @@ -21,11 +21,11 @@ const LayerList = (() => { function addLayer(id, saveHistory = true) { // layers.length - 3 - let index = layers.length - 3; + let index = currFile.layers.length - 3; // Creating a new canvas let newCanvas = document.createElement("canvas"); // Setting up the new canvas - canvasView.append(newCanvas); + currFile.canvasView.append(newCanvas); Layer.maxZIndex+=2; newCanvas.style.zIndex = Layer.maxZIndex; newCanvas.classList.add("drawingCanvas"); @@ -42,11 +42,11 @@ const LayerList = (() => { Layer.layerCount++; // Creating a layer object - let newLayer = new Layer(currentLayer.canvasSize[0], currentLayer.canvasSize[1], newCanvas, toAppend); - newLayer.context.fillStyle = currentLayer.context.fillStyle; - newLayer.copyData(currentLayer); + let newLayer = new Layer(currFile.canvasSize[0], currFile.canvasSize[1], newCanvas, toAppend); + newLayer.context.fillStyle = currFile.currentLayer.context.fillStyle; + newLayer.copyData(currFile.currentLayer); - layers.splice(index, 0, newLayer); + currFile.layers.splice(index, 0, newLayer); // Insert it before the Add layer button layerList.insertBefore(toAppend, layerList.childNodes[0]); @@ -134,10 +134,10 @@ const LayerList = (() => { // Finds a layer given its id function getLayerByID(id) { - for (let i=0; i { // Finds a layer given its name function getLayerByName(name) { - for (let i=0; i { } function startRenamingLayer(event) { - let p = currentLayer.menuEntry.getElementsByTagName("p")[0]; + let p = currFile.currentLayer.menuEntry.getElementsByTagName("p")[0]; - currentLayer.oldLayerName = p.innerHTML; + currFile.currentLayer.oldLayerName = p.innerHTML; p.setAttribute("contenteditable", true); p.classList.add("layer-name-editable"); @@ -182,8 +182,8 @@ const LayerList = (() => { return -1; } - let layerIndex = layers.indexOf(currentLayer); - let toDuplicate = currentLayer; + let layerIndex = currFile.layers.indexOf(currFile.currentLayer); + let toDuplicate = currFile.currentLayer; let menuEntries = layerList.children; // Increasing z-indexes of the layers above @@ -195,14 +195,14 @@ const LayerList = (() => { // Creating a new canvas let newCanvas = document.createElement("canvas"); // Setting up the new canvas - canvasView.append(newCanvas); - newCanvas.style.zIndex = parseInt(currentLayer.canvas.style.zIndex) + 2; + currFile.canvasView.append(newCanvas); + newCanvas.style.zIndex = parseInt(currFile.currentLayer.canvas.style.zIndex) + 2; newCanvas.classList.add("drawingCanvas"); if (!layerListEntry) return console.warn('skipping adding layer because no document'); // Clone the default layer - let toAppend = currentLayer.menuEntry.cloneNode(true); + let toAppend = currFile.currentLayer.menuEntry.cloneNode(true); // Setting the default name for the layer toAppend.getElementsByTagName('p')[0].innerHTML += " copy"; // Removing the selected class @@ -211,41 +211,41 @@ const LayerList = (() => { Layer.layerCount++; // Creating a layer object - let newLayer = new Layer(currentLayer.canvasSize[0], currentLayer.canvasSize[1], newCanvas, toAppend); - newLayer.context.fillStyle = currentLayer.context.fillStyle; - newLayer.copyData(currentLayer); + let newLayer = new Layer(currFile.canvasSize[0], currFile.canvasSize[1], newCanvas, toAppend); + newLayer.context.fillStyle = currFile.currentLayer.context.fillStyle; + newLayer.copyData(currFile.currentLayer); - layers.splice(layerIndex, 0, newLayer); + currFile.layers.splice(layerIndex, 0, newLayer); // Insert it before the Add layer button - layerList.insertBefore(toAppend, currentLayer.menuEntry); + layerList.insertBefore(toAppend, currFile.currentLayer.menuEntry); // Copy the layer content - newLayer.context.putImageData(currentLayer.context.getImageData( - 0, 0, currentLayer.canvasSize[0], currentLayer.canvasSize[1]), 0, 0); + newLayer.context.putImageData(currFile.currentLayer.context.getImageData( + 0, 0, currFile.canvasSize[0], currFile.canvasSize[1]), 0, 0); newLayer.updateLayerPreview(); // Basically "if I'm not adding a layer because redo() is telling meto do so", then I can save the history if (saveHistory) { - new HistoryState().DuplicateLayer(newLayer, currentLayer); + new HistoryState().DuplicateLayer(newLayer, currFile.currentLayer); } } function deleteLayer(saveHistory = true) { // Cannot delete all the layers - if (layers.length != 4) { - let layerIndex = layers.indexOf(currentLayer); - let toDelete = layers[layerIndex]; + if (currFile.layers.length != 4) { + let layerIndex = currFile.layers.indexOf(currFile.currentLayer); + let toDelete = currFile.layers[layerIndex]; let previousSibling = toDelete.menuEntry.previousElementSibling; // Adding the ids to the unused ones Layer.unusedIDs.push(toDelete.id); // Selecting the next layer - if (layerIndex != (layers.length - 4)) { - layers[layerIndex + 1].selectLayer(); + if (layerIndex != (currFile.layers.length - 4)) { + currFile.layers[layerIndex + 1].selectLayer(); } // or the previous one if the next one doesn't exist else { - layers[layerIndex - 1].selectLayer(); + currFile.layers[layerIndex - 1].selectLayer(); } // Deleting canvas and entry @@ -253,7 +253,7 @@ const LayerList = (() => { toDelete.menuEntry.remove(); // Removing the layer from the list - layers.splice(layerIndex, 1); + currFile.layers.splice(layerIndex, 1); if (saveHistory) { new HistoryState().DeleteLayer(toDelete, previousSibling, layerIndex); @@ -266,10 +266,10 @@ const LayerList = (() => { function merge(saveHistory = true) { // Saving the layer that should be merged - let toMerge = currentLayer; - let toMergeIndex = layers.indexOf(toMerge); + let toMerge = currFile.currentLayer; + let toMergeIndex = currFile.layers.indexOf(toMerge); // Getting layer below - let layerBelow = LayerList.getLayerByID(currentLayer.menuEntry.nextElementSibling.id); + let layerBelow = LayerList.getLayerByID(currFile.currentLayer.menuEntry.nextElementSibling.id); // If I have something to merge with if (layerBelow != null) { @@ -278,19 +278,19 @@ const LayerList = (() => { if (saveHistory) { new HistoryState().MergeLayer(toMergeIndex, toMerge, - layerBelow.context.getImageData(0, 0, layerBelow.canvasSize[0], layerBelow.canvasSize[1]), + layerBelow.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]), layerBelow); } - LayerList.mergeLayers(currentLayer.context, toMerge.context); + LayerList.mergeLayers(currFile.currentLayer.context, toMerge.context); // Deleting the above layer toMerge.canvas.remove(); toMerge.menuEntry.remove(); - layers.splice(toMergeIndex, 1); + currFile.layers.splice(toMergeIndex, 1); // Updating the layer preview - currentLayer.updateLayerPreview(); + currFile.currentLayer.updateLayerPreview(); } } @@ -312,9 +312,9 @@ const LayerList = (() => { let visibleLayers = []; let nToFlatten = 0; - for (let i=0; i { nToFlatten++; console.log(visibleLayers[i].menuEntry.nextElementSibling); new HistoryState().FlattenTwoVisibles( - visibleLayers[i + 1].context.getImageData(0, 0, visibleLayers[i].canvasSize[0], visibleLayers[i].canvasSize[1]), + visibleLayers[i + 1].context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]), visibleLayers[i].menuEntry.nextElementSibling, layers.indexOf(visibleLayers[i]), visibleLayers[i], visibleLayers[i + 1] @@ -339,12 +339,12 @@ const LayerList = (() => { // Deleting the above layer visibleLayers[i].canvas.remove(); visibleLayers[i].menuEntry.remove(); - layers.splice(layers.indexOf(visibleLayers[i]), 1); + currFile.layers.splice(currFile.layers.indexOf(visibleLayers[i]), 1); } new HistoryState().FlattenVisible(nToFlatten); // Updating the layer preview - currentLayer.updateLayerPreview(); + currFile.currentLayer.updateLayerPreview(); } } @@ -369,7 +369,7 @@ const LayerList = (() => { function closeOptionsMenu(event) { Layer.layerOptions.style.visibility = "hidden"; - currentLayer.rename(); + currFile.currentLayer.rename(); renamingLayer = false; } diff --git a/js/Settings.js b/js/Settings.js index 20c6a1a..dd66fa8 100644 --- a/js/Settings.js +++ b/js/Settings.js @@ -45,7 +45,7 @@ const Settings = (() => { settings.numberOfHistoryStates = Util.getValue('setting-numberOfHistoryStates'); settings.pixelGridColour = Util.getValue('setting-pixelGridColour'); // Filling pixel grid again if colour changed - pixelGrid.fillPixelGrid(); + currFile.pixelGrid.fillPixelGrid(); //save settings object to cookie var cookieValue = JSON.stringify(settings); diff --git a/js/Startup.js b/js/Startup.js index 7e4d133..44c5cb3 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -53,7 +53,7 @@ const Startup = (() => { // Deleting the default layer LayerList.deleteLayer(false); // Selecting the new one - layers[1].selectLayer(); + currFile.layers[1].selectLayer(); } console.log("Starting with mode " + EditorState.getCurrentMode()); @@ -63,17 +63,20 @@ const Startup = (() => { } function initLayers(width, height) { + // Setting the general canvasSize + currFile.canvasSize = [width, height]; + // If this is the first pixel I'm creating since the app has started if (firstPixel) { // Creating the first layer - currentLayer = new Layer(width, height, 'pixel-canvas', ""); - currentLayer.canvas.style.zIndex = 2; + currFile.currentLayer = new Layer(width, height, 'pixel-canvas', ""); + currFile.currentLayer.canvas.style.zIndex = 2; } else { // Deleting all the extra layers and canvases, leaving only one - let nLayers = layers.length; - for (let i=2; i < layers.length - nAppLayers; i++) { - let currentEntry = layers[i].menuEntry; + let nLayers = currFile.layers.length; + for (let i=2; i < currFile.layers.length - nAppLayers; i++) { + let currentEntry = currFile.layers[i].menuEntry; let associatedLayer; if (currentEntry != null) { @@ -84,7 +87,7 @@ const Startup = (() => { associatedLayer.canvas.remove(); // Adding the id to the unused ones - unusedIDs.push(currentEntry.id); + Layer.unusedIDs.push(currentEntry.id); // Removing the entry from the menu currentEntry.remove(); } @@ -92,40 +95,32 @@ const Startup = (() => { // Removing the old layers from the list for (let i=2; i { currTool = tools["brush"]; currTool.onSelect(); - canvasView.style.cursor = 'default'; + currFile.canvasView.style.cursor = 'default'; Events.on("mouseup", window, onMouseUp); Events.on("mousemove", window, onMouseMove); diff --git a/js/_resizeCanvas.js b/js/_resizeCanvas.js index e6e28c1..e69de29 100644 --- a/js/_resizeCanvas.js +++ b/js/_resizeCanvas.js @@ -1,311 +0,0 @@ -// REFACTOR: method of File class probably - -/* This scripts contains all the code used to handle the canvas resizing */ - -// Resize canvas pop up window -let resizeCanvasContainer = document.getElementById("resize-canvas"); -// Start pivot -let rcPivot = "middle"; -// Selected pivot button -let currentPivotObject; -// Border offsets -let rcBorders = {left: 0, right: 0, top: 0, bottom: 0}; - -/** Opens the canvas resize window - * - */ -function openResizeCanvasWindow() { - // Initializes the inputs - initResizeCanvasInputs(); - Dialogue.showDialogue('resize-canvas'); -} - -/** Initializes the canvas resizing input - * - */ -function initResizeCanvasInputs() { - // Getting the pivot buttons - let buttons = document.getElementsByClassName("pivot-button"); - - // Adding the event handlers for them - for (let i=0; i= 0; i-=4) { - if (!Util.isPixelEmpty( - [imageData.data[i - 3], imageData.data[i - 2], - -imageData.data[i - 1], imageData.data[i]])) { - pixelPosition = getPixelPosition(i); - - // max x - if (pixelPosition[0] > maxX) { - maxX = pixelPosition[0]; - } - // min x - if (pixelPosition[0] < minX) { - minX = pixelPosition[0]; - } - // max y - if (pixelPosition[1] > maxY) { - maxY = pixelPosition[1]; - } - // min y - if (pixelPosition[1] < minY) { - minY = pixelPosition[1]; - } - } - } - } - - tmp = minY; - minY = maxY; - maxY = tmp; - - minY = layers[0].canvasSize[1] - minY; - maxY = layers[0].canvasSize[1] - maxY; - - // Setting the borders coherently with the values I've just computed - rcBorders.right = (maxX - layers[0].canvasSize[0]) + 1; - rcBorders.left = -minX; - rcBorders.top = maxY - layers[0].canvasSize[1] + 1; - rcBorders.bottom = -minY; - - // Saving the data - for (let i=0; i max || Util.isPixelEmpty(selectedColor) || selectedColor === undefined) { - max = layers[i].canvas.style.zIndex; + if (currFile.layers[i].canvas.style.zIndex > max || Util.isPixelEmpty(selectedColor) || selectedColor === undefined) { + max = currFile.layers[i].canvas.style.zIndex; if (!Util.isPixelEmpty(tmpColour)) { selectedColor = tmpColour; diff --git a/js/tools/FillTool.js b/js/tools/FillTool.js index b9f7d45..b96c4fc 100644 --- a/js/tools/FillTool.js +++ b/js/tools/FillTool.js @@ -11,7 +11,7 @@ class FillTool extends Tool { if (target.className != 'drawingCanvas') return; this.fill(mousePos); - currentLayer.updateLayerPreview(); + currFile.currentLayer.updateLayerPreview(); new HistoryState().EditCanvas(); } @@ -40,20 +40,20 @@ class FillTool extends Tool { } //temporary image holds the data while we change it - let tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + let tempImage = currFile.currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); //this is an array that holds all of the pixels at the top of the cluster - let topmostPixelsArray = [[Math.floor(cursorLocation[0]/zoom), Math.floor(cursorLocation[1]/zoom)]]; + let topmostPixelsArray = [[Math.floor(cursorLocation[0]/currFile.zoom), Math.floor(cursorLocation[1]/currFile.zoom)]]; //console.log('topmostPixelsArray:',topmostPixelsArray) //the offset of the pixel in the temp image data to start with - let startingPosition = (topmostPixelsArray[0][1] * canvasSize[0] + topmostPixelsArray[0][0]) * 4; + let startingPosition = (topmostPixelsArray[0][1] * currFile.canvasSize[0] + topmostPixelsArray[0][0]) * 4; //the color of the cluster that is being filled let clusterColor = [tempImage.data[startingPosition],tempImage.data[startingPosition+1],tempImage.data[startingPosition+2], tempImage.data[startingPosition+3]]; //the color to fill with - let fillColor = Color.hexToRgb(currentLayer.context.fillStyle); + let fillColor = Color.hexToRgb(currFile.currentLayer.context.fillStyle); //if you try to fill with the same color that's already there, exit the function if (clusterColor[0] == fillColor.r && @@ -78,18 +78,18 @@ class FillTool extends Tool { //this variable holds the index of where the starting values for the current pixel are in the data array //we multiply the number of rows down (y) times the width of each row, then add x. at the end we multiply by 4 because //each pixel has 4 values, rgba - let pixelPos = (y * canvasSize[0] + x) * 4; + let pixelPos = (y * currFile.canvasSize[0] + x) * 4; //move up in the image until you reach the top or the pixel you hit was not the right color while (y-- >= 0 && matchStartColor(tempImage, pixelPos, clusterColor)) { - pixelPos -= canvasSize[0] * 4; + pixelPos -= currFile.canvasSize[0] * 4; } - pixelPos += canvasSize[0] * 4; + pixelPos += currFile.canvasSize[0] * 4; ++y; reachLeft = false; reachRight = false; - while (y++ < canvasSize[1] - 1 && matchStartColor(tempImage, pixelPos, clusterColor)) { + while (y++ < currFile.canvasSize[1] - 1 && matchStartColor(tempImage, pixelPos, clusterColor)) { colorPixel(tempImage, pixelPos, fillColor); if (x > 0) { if (matchStartColor(tempImage, pixelPos - 4, clusterColor)) { @@ -103,7 +103,7 @@ class FillTool extends Tool { } } - if (x < canvasSize[0] - 1) { + if (x < currFile.canvasSize[0] - 1) { if (matchStartColor(tempImage, pixelPos + 4, clusterColor)) { if (!reachRight) { topmostPixelsArray.push([x + 1, y]); @@ -115,10 +115,10 @@ class FillTool extends Tool { } } - pixelPos += canvasSize[0] * 4; + pixelPos += currFile.canvasSize[0] * 4; } } - currentLayer.context.putImageData(tempImage, 0, 0); + currFile.currentLayer.context.putImageData(tempImage, 0, 0); } onDrag(mousePos, cursorTarget) { diff --git a/js/tools/LineTool.js b/js/tools/LineTool.js index 78f66b9..8fb8006 100644 --- a/js/tools/LineTool.js +++ b/js/tools/LineTool.js @@ -11,7 +11,7 @@ class LineTool extends ResizableTool { super.onStart(mousePos); // Putting the tmp layer on top of everything - TMPLayer.canvas.style.zIndex = parseInt(currentLayer.canvas.style.zIndex, 10) + 1; + currFile.TMPLayer.canvas.style.zIndex = parseInt(currFile.currentLayer.canvas.style.zIndex, 10) + 1; this.startMousePos[0] = Math.floor(mousePos[0]) + 0.5; this.startMousePos[1] = Math.floor(mousePos[1]) + 0.5; @@ -34,18 +34,18 @@ class LineTool extends ResizableTool { onEnd(mousePos) { super.onEnd(mousePos); - const tmpContext = TMPLayer.context; - const tmpCanvas = TMPLayer.canvas; + const tmpContext = currFile.TMPLayer.context; + const tmpCanvas = currFile.TMPLayer.canvas; // Setting the correct linewidth and colour - currentLayer.context.lineWidth = this.currSize; + currFile.currentLayer.context.lineWidth = this.currSize; // Drawing the line - currentLayer.context.drawImage(tmpCanvas, 0, 0); + currFile.currentLayer.context.drawImage(tmpCanvas, 0, 0); // Update the layer preview - currentLayer.updateLayerPreview(); + currFile.currentLayer.updateLayerPreview(); // Clearing the tmp canvas - tmpContext.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height); + tmpContext.clearRect(0, 0, currFile.TMPLayer.canvas.width, currFile.TMPLayer.canvas.height); } onSelect() { @@ -57,10 +57,10 @@ class LineTool extends ResizableTool { } drawLine(mousePos) { - let x0 = Math.floor(this.startMousePos[0]/zoom); - let y0 = Math.floor(this.startMousePos[1]/zoom); - let x1 = Math.floor(mousePos[0]/zoom); - let y1 = Math.floor(mousePos[1]/zoom); + let x0 = Math.floor(this.startMousePos[0]/currFile.zoom); + let y0 = Math.floor(this.startMousePos[1]/currFile.zoom); + let x1 = Math.floor(mousePos[0]/currFile.zoom); + let y1 = Math.floor(mousePos[1]/currFile.zoom); let dx = Math.abs(x1-x0); let dy = Math.abs(y1-y0); @@ -72,7 +72,7 @@ class LineTool extends ResizableTool { const context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); - canvas.style.zIndex = parseInt(currentLayer.canvas.style.zIndex, 10) + 1; + canvas.style.zIndex = parseInt(currFile.currentLayer.canvas.style.zIndex, 10) + 1; while (true) { context.fillRect(x0-Math.floor(this.currSize/2), y0-Math.floor(this.currSize/2), this.currSize, this.currSize); diff --git a/js/tools/MoveSelectionTool.js b/js/tools/MoveSelectionTool.js index bd57383..bc9c2ed 100644 --- a/js/tools/MoveSelectionTool.js +++ b/js/tools/MoveSelectionTool.js @@ -30,7 +30,7 @@ class MoveSelectionTool extends Tool { this.endSelection(); this.currSelection = this.lastCopiedSelection; // Cut the data - currentLayer.context.clearRect(this.currSelection.left-0.5, this.currSelection.top-0.5, + currFile.currentLayer.context.clearRect(this.currSelection.left-0.5, this.currSelection.top-0.5, this.currSelection.width, this.currSelection.height); } @@ -47,7 +47,7 @@ class MoveSelectionTool extends Tool { this.currSelection = this.lastCopiedSelection; // Putting the vfx layer on top of everything - VFXLayer.canvas.style.zIndex = MAX_Z_INDEX; + currFile.VFXLayer.canvas.style.zIndex = MAX_Z_INDEX; this.onDrag(this.currMousePos); new HistoryState().EditCanvas(); @@ -65,16 +65,16 @@ class MoveSelectionTool extends Tool { onDrag(mousePos) { super.onDrag(mousePos); - this.currSelection = this.selectionTool.moveAnts(mousePos[0]/zoom, - mousePos[1]/zoom, this.currSelection.width, this.currSelection.height); + this.currSelection = this.selectionTool.moveAnts(mousePos[0]/currFile.zoom, + mousePos[1]/currFile.zoom, this.currSelection.width, this.currSelection.height); // clear the entire tmp layer - TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height); + TMPLayer.context.clearRect(0, 0, currFile.TMPLayer.canvas.width, currFile.TMPLayer.canvas.height); // put the image data on the tmp layer with offset - TMPLayer.context.putImageData( + currFile.TMPLayer.context.putImageData( this.currSelection.data, - Math.round(mousePos[0] / zoom) - this.currSelection.width / 2, - Math.round(mousePos[1] / zoom) - this.currSelection.height / 2); + Math.round(mousePos[0] / currFile.zoom) - this.currSelection.width / 2, + Math.round(mousePos[1] / currFile.zoom) - this.currSelection.height / 2); } onEnd(mousePos) { @@ -99,17 +99,17 @@ class MoveSelectionTool extends Tool { super.onHover(mousePos); if (this.cursorInSelectedArea(mousePos)) { - canvasView.style.cursor = 'move'; + currFile.canvasView.style.cursor = 'move'; } else { - canvasView.style.cursor = 'default'; + currFile.canvasView.style.cursor = 'default'; } } cursorInSelectedArea(cursorPos) { // Getting the coordinates relatively to the canvas - let x = cursorPos[0] / zoom; - let y = cursorPos[1] / zoom; + let x = cursorPos[0] / currFile.zoom; + let y = cursorPos[1] / currFile.zoom; if (this.currSelection.left <= x && x <= this.currSelection.right) { if (y <= this.currSelection.bottom && y >= this.currSelection.top) { @@ -124,12 +124,12 @@ class MoveSelectionTool extends Tool { if (this.currSelection == undefined) return; // Clearing the tmp (move preview) and vfx (ants) layers - TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height); - VFXLayer.context.clearRect(0, 0, VFXLayer.canvas.width, VFXLayer.canvas.height); + currFile.TMPLayer.context.clearRect(0, 0, currFile.TMPLayer.canvas.width, currFile.TMPLayer.canvas.height); + currFile.VFXLayer.context.clearRect(0, 0, currFile.VFXLayer.canvas.width, currFile.VFXLayer.canvas.height); // I have to save the underlying data, so that the transparent pixels in the clipboard // don't override the coloured pixels in the canvas - let underlyingImageData = currentLayer.context.getImageData( + let underlyingImageData = currFile.currentLayer.context.getImageData( this.currSelection.left, this.currSelection.top, this.currSelection.width+1, this.currSelection.height+1 ); @@ -162,13 +162,13 @@ class MoveSelectionTool extends Tool { } } - currentLayer.context.putImageData(new ImageData(pasteData, this.currSelection.width+1), + currFile.currentLayer.context.putImageData(new ImageData(pasteData, this.currSelection.width+1), this.currSelection.left, this.currSelection.top ); this.currSelection = undefined; - currentLayer.updateLayerPreview(); - VFXLayer.canvas.style.zIndex = MIN_Z_INDEX; + currFile.currentLayer.updateLayerPreview(); + currFile.VFXLayer.canvas.style.zIndex = MIN_Z_INDEX; // Switch to brush this.switchFunc(this.endTool); diff --git a/js/tools/PanTool.js b/js/tools/PanTool.js index c4fb842..a35f68c 100644 --- a/js/tools/PanTool.js +++ b/js/tools/PanTool.js @@ -8,29 +8,29 @@ class PanTool extends Tool { onStart(mousePos) { super.onStart(mousePos); - canvasView.style.cursor = "url(\'/pixel-editor/pan-held.png\'), auto"; + currFile.canvasView.style.cursor = "url(\'/pixel-editor/pan-held.png\'), auto"; } onDrag(mousePos) { super.onDrag(mousePos); // Setting first layer position - layers[0].setCanvasOffset(layers[0].canvas.offsetLeft + (mousePos[0] - this.startMousePos[0]), layers[0].canvas.offsetTop + (mousePos[1] - this.startMousePos[1])); + currFile.layers[0].setCanvasOffset(currFile.layers[0].canvas.offsetLeft + (mousePos[0] - this.startMousePos[0]), currFile.layers[0].canvas.offsetTop + (mousePos[1] - this.startMousePos[1])); // Copying that position to the other layers - for (let i=1; i currentLayer.canvas.width) { - this.startMousePos[0] = currentLayer.canvas.width; + else if (this.startMousePos[0] > currFile.currentLayer.canvas.width) { + this.startMousePos[0] = currFile.currentLayer.canvas.width; } if (this.startMousePos[1] < 0) { this.startMousePos[1] = 0; } - else if (this.startMousePos[1] > currentLayer.canvas.height) { - this.startMousePos[1] = currentLayer.canvas.height; + else if (this.startMousePos[1] > currFile.currentLayer.canvas.height) { + this.startMousePos[1] = currFile.currentLayer.canvas.height; } // Drawing the rect @@ -44,7 +44,7 @@ class RectangularSelectionTool extends SelectionTool { super.onDrag(mousePos); // Drawing the rect - this.drawSelection(Math.round(mousePos[0] / zoom) + 0.5, Math.round(mousePos[1] / zoom) + 0.5); + this.drawSelection(Math.round(mousePos[0] / currFile.zoom) + 0.5, Math.round(mousePos[1] / currFile.zoom) + 0.5); } onEnd(mousePos) { @@ -52,8 +52,8 @@ class RectangularSelectionTool extends SelectionTool { new HistoryState().EditCanvas(); // Getting the end position - this.endMousePos[0] = Math.round(this.endMousePos[0] / zoom) + 0.5; - this.endMousePos[1] = Math.round(this.endMousePos[1] / zoom) + 0.5; + this.endMousePos[0] = Math.round(this.endMousePos[0] / currFile.zoom) + 0.5; + this.endMousePos[1] = Math.round(this.endMousePos[1] / currFile.zoom) + 0.5; // Inverting end and start (start must always be the top left corner) if (this.endMousePos[0] < this.startMousePos[0]) { @@ -81,17 +81,17 @@ class RectangularSelectionTool extends SelectionTool { width: dataWidth, height: dataHeight, - data: currentLayer.context.getImageData( + data: currFile.currentLayer.context.getImageData( this.startMousePos[0], this.startMousePos[1], dataWidth + 1, dataHeight + 1) }; // Moving the selection to the TMP layer. It will be moved back to the original // layer if the user will cancel or end the selection - currentLayer.context.clearRect(this.startMousePos[0] - 0.5, this.startMousePos[1] - 0.5, + currFile.currentLayer.context.clearRect(this.startMousePos[0] - 0.5, this.startMousePos[1] - 0.5, dataWidth + 1, dataHeight + 1); // Moving those pixels from the current layer to the tmp layer - TMPLayer.context.putImageData(this.currSelection.data, this.startMousePos[0], this.startMousePos[1]); + currFile.TMPLayer.context.putImageData(this.currSelection.data, this.startMousePos[0], this.startMousePos[1]); this.moveTool.setSelectionData(this.currSelection, this); console.log("data set"); @@ -107,10 +107,10 @@ class RectangularSelectionTool extends SelectionTool { drawSelection(x, y) { // Getting the vfx context - let vfxContext = VFXLayer.context; + let vfxContext = currFile.VFXLayer.context; // Clearing the vfx canvas - vfxContext.clearRect(0, 0, VFXLayer.canvas.width, VFXLayer.canvas.height); + vfxContext.clearRect(0, 0, currFile.VFXLayer.canvas.width, currFile.VFXLayer.canvas.height); vfxContext.lineWidth = 1; vfxContext.strokeStyle = 'black'; vfxContext.setLineDash([4]); @@ -133,11 +133,11 @@ class RectangularSelectionTool extends SelectionTool { */ moveAnts(x, y, width, height) { // Getting the vfx context - let vfxContext = VFXLayer.context; + let vfxContext = currFile.VFXLayer.context; let ret = this.currSelection; // Clearing the vfx canvas - vfxContext.clearRect(0, 0, VFXLayer.canvas.width, VFXLayer.canvas.height); + vfxContext.clearRect(0, 0, currFile.VFXLayer.canvas.width, currFile.VFXLayer.canvas.height); vfxContext.lineWidth = 1; vfxContext.setLineDash([4]); diff --git a/js/tools/ResizableTool.js b/js/tools/ResizableTool.js index 29b4214..e291251 100644 --- a/js/tools/ResizableTool.js +++ b/js/tools/ResizableTool.js @@ -13,7 +13,7 @@ class ResizableTool extends Tool { onRightDrag(mousePos, mouseEvent) { //get new brush size based on x distance from original clicking location - let distanceFromClick = mousePos[0]/zoom - this.startResizePos[0]/zoom; + let distanceFromClick = mousePos[0]/currFile.zoom - this.startResizePos[0]/currFile.zoom; let brushSizeChange = Math.round(distanceFromClick/10); let newBrushSize = this.currSize + brushSizeChange; diff --git a/js/tools/ZoomTool.js b/js/tools/ZoomTool.js index e7e0de0..a945bb6 100644 --- a/js/tools/ZoomTool.js +++ b/js/tools/ZoomTool.js @@ -6,77 +6,77 @@ class ZoomTool extends Tool { super.onMouseWheel(mousePos, mode); // Computing current width and height - let oldWidth = canvasSize[0] * zoom; - let oldHeight = canvasSize[1] * zoom; + let oldWidth = currFile.canvasSize[0] * currFile.zoom; + let oldHeight = currFile.canvasSize[1] * currFile.zoom; let newWidth, newHeight; - let prevZoom = zoom; + let prevZoom = currFile.zoom; let zoomed = false; //change zoom level //if you want to zoom out, and the zoom isnt already at the smallest level - if (mode == 'out' && zoom > MIN_ZOOM_LEVEL) { + if (mode == 'out' && currFile.zoom > MIN_ZOOM_LEVEL) { zoomed = true; - if (zoom > 2) - zoom -= Math.ceil(zoom / 10); + if (currFile.zoom > 2) + currFile.zoom -= Math.ceil(currFile.zoom / 10); else - zoom -= Math.ceil(zoom * 2 / 10) / 2; + currFile.zoom -= Math.ceil(currFile.zoom * 2 / 10) / 2; - newWidth = canvasSize[0] * zoom; - newHeight = canvasSize[1] * zoom; + newWidth = currFile.canvasSize[0] * currFile.zoom; + newHeight = currFile.canvasSize[1] * currFile.zoom; //adjust canvas position - layers[0].setCanvasOffset( - layers[0].canvas.offsetLeft + (oldWidth - newWidth) * mousePos[0]/oldWidth, - layers[0].canvas.offsetTop + (oldHeight - newHeight) * mousePos[1]/oldHeight); + currFile.layers[0].setCanvasOffset( + currFile.layers[0].canvas.offsetLeft + (oldWidth - newWidth) * mousePos[0]/oldWidth, + currFile.layers[0].canvas.offsetTop + (oldHeight - newHeight) * mousePos[1]/oldHeight); } //if you want to zoom in - else if (mode == 'in' && zoom + Math.ceil(zoom/10) < window.innerHeight/4) { + else if (mode == 'in' && currFile.zoom + Math.ceil(currFile.zoom/10) < window.innerHeight/4) { zoomed = true; - if (zoom > 2) - zoom += Math.ceil(zoom/10); + if (currFile.zoom > 2) + currFile.zoom += Math.ceil(currFile.zoom/10); else { - if (zoom + zoom/10 > 2) { - zoom += Math.ceil(zoom/10); - zoom = Math.ceil(zoom); + if (currFile.zoom + currFile.zoom/10 > 2) { + currFile.zoom += Math.ceil(currFile.zoom/10); + currFile.zoom = Math.ceil(currFile.zoom); } else { - zoom += Math.ceil(zoom * 2 / 10) / 2; + currFile.zoom += Math.ceil(currFile.zoom * 2 / 10) / 2; } } - newWidth = canvasSize[0] * zoom; - newHeight = canvasSize[1] * zoom; + newWidth = currFile.canvasSize[0] * currFile.zoom; + newHeight = currFile.canvasSize[1] * currFile.zoom; //adjust canvas position - layers[0].setCanvasOffset( - layers[0].canvas.offsetLeft - Math.round((newWidth - oldWidth)*mousePos[0]/oldWidth), - layers[0].canvas.offsetTop - Math.round((newHeight - oldHeight)*mousePos[1]/oldHeight)); + currFile.layers[0].setCanvasOffset( + currFile.layers[0].canvas.offsetLeft - Math.round((newWidth - oldWidth)*mousePos[0]/oldWidth), + currFile.layers[0].canvas.offsetTop - Math.round((newHeight - oldHeight)*mousePos[1]/oldHeight)); } //resize canvas - layers[0].resize(); + currFile.layers[0].resize(); // adjust brush size ToolManager.currentTool().updateCursor(); // Adjust pixel grid thickness if (zoomed) { - if (zoom <= 7) - pixelGrid.disablePixelGrid(); - else if (zoom >= 20 && mode == 'in') { - pixelGrid.enablePixelGrid(); - pixelGrid.repaintPixelGrid((zoom - prevZoom) * 0.6); + if (currFile.zoom <= 7) + currFile.pixelGrid.disablePixelGrid(); + else if (currFile.zoom >= 20 && mode == 'in') { + currFile.pixelGrid.enablePixelGrid(); + currFile.pixelGrid.repaintPixelGrid((currFile.zoom - prevZoom) * 0.6); } else if (prevZoom >= 20 && mode == 'out') { - pixelGrid.enablePixelGrid(); - pixelGrid.repaintPixelGrid((zoom - prevZoom) * 0.6); + currFile.pixelGrid.enablePixelGrid(); + currFile.pixelGrid.repaintPixelGrid((currFile.zoom - prevZoom) * 0.6); } else { - pixelGrid.enablePixelGrid(); + currFile.pixelGrid.enablePixelGrid(); } } - for (let i=1; i
    -
  • -
  • -
  • +
  • +
  • +
From 21dd47c2b0e417b35155809a75d9f364a0a52d21 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Mon, 6 Dec 2021 20:12:57 +0100 Subject: [PATCH 81/91] Finished refactoring, moved sprite scaling functions in File --- js/Canvas.js | 0 js/EditorState.js | 1 - js/File.js | 375 +++++++++++++++++++++++++++++++- js/FileManager.js | 12 +- js/History.js | 8 +- js/Startup.js | 3 +- js/_resizeCanvas.js | 0 js/_resizeSprite.js | 396 ---------------------------------- js/pixel-editor.js | 11 +- js/tools/FillTool.js | 2 +- js/tools/MoveSelectionTool.js | 8 +- js/tools/RectangleTool.js | 2 +- refactor_dependencies | 12 ++ views/main-menu.hbs | 2 +- 14 files changed, 405 insertions(+), 427 deletions(-) delete mode 100644 js/Canvas.js delete mode 100644 js/_resizeCanvas.js delete mode 100644 js/_resizeSprite.js create mode 100644 refactor_dependencies diff --git a/js/Canvas.js b/js/Canvas.js deleted file mode 100644 index e69de29..0000000 diff --git a/js/EditorState.js b/js/EditorState.js index c8cce1d..ee1761a 100644 --- a/js/EditorState.js +++ b/js/EditorState.js @@ -52,7 +52,6 @@ const EditorState = (() => { } function chooseMode() { - console.log("Here"); let prevMode = pixelEditorMode.toLowerCase(); if (pixelEditorMode === "Basic") { diff --git a/js/File.js b/js/File.js index 8b0bf82..6d2cf2b 100644 --- a/js/File.js +++ b/js/File.js @@ -22,6 +22,18 @@ class File { // Border offsets rcBorders = {left: 0, right: 0, top: 0, bottom: 0}; + // Sprite scaling attributes + // Should I keep the sprite ratio? + keepRatio = true; + // Used to store the current ratio + currentRatio = undefined; + // The currenty selected resizing algorithm (nearest-neighbor or bilinear-interpolation) + currentAlgo = 'nearest-neighbor'; + // Current resize data + data = {width: 0, height: 0, widthPercentage: 100, heightPercentage: 100}; + // Start resize data + startData = {width: 0, height:0, widthPercentage: 100, heightPercentage: 100}; + // Sprite scaling attributes openResizeCanvasWindow() { @@ -97,7 +109,6 @@ class File { * @param {*} saveHistory Should I save the history? You shouldn't if you're undoing */ resizeCanvas(event, size, customData, saveHistory = true) { - console.log("resizing"); let imageDatas = []; let leftOffset = 0; let topOffset = 0; @@ -314,6 +325,368 @@ class File { this.currentPivotObject = event.target; this.currentPivotObject.classList.add("rc-selected-pivot"); } + + /** Opens the sprite resizing window + * + */ + openResizeSpriteWindow() { + // Inits the sprie resize inputs + this.initResizeSpriteInputs(); + + // Computing the current ratio + this.currentRatio = currFile.canvasSize[0] / currFile.canvasSize[1]; + + // Initializing the input fields + this.data.width = currFile.canvasSize[0]; + this.data.height = currFile.canvasSize[1]; + + this.startData.width = parseInt(this.data.width); + this.startData.height = parseInt(this.data.height); + this.startData.heightPercentage = 100; + this.startData.widthPercentage = 100; + + // Opening the pop up now that it's ready + Dialogue.showDialogue('resize-sprite'); + } + + /** Initalizes the input values and binds the elements to their events + * + */ + initResizeSpriteInputs() { + document.getElementById("rs-width").value = currFile.canvasSize[0]; + document.getElementById("rs-height").value = currFile.canvasSize[1]; + + document.getElementById("rs-width-percentage").value = 100; + document.getElementById("rs-height-percentage").value = 100; + + document.getElementById("rs-keep-ratio").checked = true; + + Events.on("change", "rs-width", this.changedWidth.bind(this)); + Events.on("change", "rs-height", this.changedHeight.bind(this)); + + Events.on("change", "rs-width-percentage", this.changedWidthPercentage.bind(this)); + Events.on("change", "rs-height-percentage", this.changedHeightPercentage.bind(this)); + + Events.on("click", "resize-sprite-confirm", this.resizeSprite.bind(this)); + Events.on("click", "rs-keep-ratio", this.toggleRatio.bind(this)); + Events.on("change", "resize-algorithm-combobox", this.changedAlgorithm.bind(this)); + } + + /** Resizes (scales) the sprite + * + * @param {*} event + * @param {*} ratio Keeps infos about the x ratio and y ratio + */ + resizeSprite(event, ratio) { + // Old data + let oldWidth, oldHeight; + // New data + let newWidth, newHeight; + // Current imageDatas + let rsImageDatas = []; + // Index that will be used a few lines below + let layerIndex = 0; + // Copy of the imageDatas that will be stored in the history + let imageDatasCopy = []; + + oldWidth = currFile.canvasSize[0]; + oldHeight = currFile.canvasSize[1]; + this.rcPivot = "middle"; + + // Updating values if the user didn't press enter + switch (document.activeElement.id) { + case "rs-width-percentage": + this.changedWidthPercentage(); + break; + case "rs-width": + this.changedWidth(); + break; + case "rs-height-percentage": + this.changedHeightPercentage(); + break; + case "rs-height": + this.changedHeight(); + break; + default: + // In this case everything has been updated correctly + break; + } + + // Computing newWidth and newHeight + if (ratio == null) { + newWidth = this.data.width; + newHeight = this.data.height; + } + else { + newWidth = currFile.canvasSize[0] * ratio[0]; + newHeight = currFile.canvasSize[1] * ratio[1]; + } + + // Get all the image datas + for (let i=0; i { } Util.setValue('lpe-file-name', fileName); - Events.on("click", "save-project-confirm", saveProject); - Dialogue.showDialogue('save-project', false); } @@ -38,9 +36,7 @@ const FileManager = (() => { } Util.setValue('export-file-name', fileName); - Events.on("click", "export-confirm", exportProject); - Dialogue.showDialogue('export', false); } @@ -66,11 +62,11 @@ const FileManager = (() => { //create name let fileName = Util.getValue("export-file-name"); //set download link - var linkHolder = document.getElementById('save-image-link-holder'); + let linkHolder = document.getElementById('save-image-link-holder'); // Creating a tmp canvas to flatten everything - var exportCanvas = document.createElement("canvas"); - var emptyCanvas = document.createElement("canvas"); - var layersCopy = currFile.layers.slice(); + let exportCanvas = document.createElement("canvas"); + let emptyCanvas = document.createElement("canvas"); + let layersCopy = currFile.layers.slice(); exportCanvas.width = currFile.canvasSize[0]; exportCanvas.height = currFile.canvasSize[1]; diff --git a/js/History.js b/js/History.js index 1afe5d9..89f505c 100644 --- a/js/History.js +++ b/js/History.js @@ -104,8 +104,8 @@ class HistoryState { this.undo = function() { let layerIndex = 0; - currentAlgo = algo; - resizeSprite(null, [1 / this.xRatio, 1 / this.yRatio]); + currFile.currentAlgo = algo; + currFile.resizeSprite(null, [1 / this.xRatio, 1 / this.yRatio]); // Also putting the old data for (let i=0; i { let firstPixel = true; - let editorMode = "Basic"; let splashPostfix = ''; Events.on('click', 'create-button', create, false); @@ -142,7 +141,7 @@ const Startup = (() => { else { //if this palette isnt the one specified in the url, then reset the url if (!palettes[selectedPalette].specified) - history.pushState(null, null, '/pixel-editor'); + history.pushState(null, null, '/pixel-editor'); //fill the palette with specified colours ColorModule.createColorPalette(palettes[selectedPalette].colors); diff --git a/js/_resizeCanvas.js b/js/_resizeCanvas.js deleted file mode 100644 index e69de29..0000000 diff --git a/js/_resizeSprite.js b/js/_resizeSprite.js deleted file mode 100644 index 22a2069..0000000 --- a/js/_resizeSprite.js +++ /dev/null @@ -1,396 +0,0 @@ -// REFACTOR: method of File class probably - -/* This scripts contains all the code used to handle the sprite scaling */ -// Should I keep the sprite ratio? -let keepRatio = true; -// Used to store the current ratio -let currentRatio; -// The currenty selected resizing algorithm (nearest-neighbor or bilinear-interpolation) -let currentAlgo = 'nearest-neighbor'; -// Current resize data -let data = {width: 0, height: 0, widthPercentage: 100, heightPercentage: 100}; -// Start resize data -let startData = {width: 0, height:0, widthPercentage: 100, heightPercentage: 100}; - -/** Opens the sprite resizing window - * - */ -function openResizeSpriteWindow() { - // Inits the sprie resize inputs - initResizeSpriteInputs(); - - // Computing the current ratio - currentRatio = currFile.canvasSize[0] / currFile.canvasSize[1]; - - console.log("Current ratio: " + currentRatio); - - // Initializing the input fields - data.width = currFile.canvasSize[0]; - data.height = currFile.canvasSize[1]; - - startData.width = parseInt(data.width); - startData.height = parseInt(data.height); - startData.heightPercentage = 100; - startData.widthPercentage = 100; - - // Opening the pop up now that it's ready - Dialogue.showDialogue('resize-sprite'); -} - -/** Initalizes the input values and binds the elements to their events - * - */ -function initResizeSpriteInputs() { - document.getElementById("rs-width").value = currFile.canvasSize[0]; - document.getElementById("rs-height").value = currFile.canvasSize[1]; - - document.getElementById("rs-width-percentage").value = 100; - document.getElementById("rs-height-percentage").value = 100; - - document.getElementById("rs-keep-ratio").checked = true; - - document.getElementById("rs-width").addEventListener("change", changedWidth); - document.getElementById("rs-height").addEventListener("change", changedHeight); - document.getElementById("rs-width-percentage").addEventListener("change", changedWidthPercentage); - document.getElementById("rs-height-percentage").addEventListener("change", changedHeightPercentage); - - document.getElementById("resize-sprite-confirm").addEventListener("click", resizeSprite); - document.getElementById("rs-keep-ratio").addEventListener("click", toggleRatio); - document.getElementById("resize-algorithm-combobox").addEventListener("change", changedAlgorithm); -} - -/** Resizes (scales) the sprite - * - * @param {*} event - * @param {*} ratio Keeps infos about the x ratio and y ratio - */ -function resizeSprite(event, ratio) { - // Old data - let oldWidth, oldHeight; - // New data - let newWidth, newHeight; - // Current imageDatas - let rsImageDatas = []; - // Index that will be used a few lines below - let layerIndex = 0; - // Copy of the imageDatas that will be stored in the history - let imageDatasCopy = []; - - oldWidth = currFile.canvasSize[0]; - oldHeight = currFile.canvasSize[1]; - rcPivot = "middle"; - - // Updating values if the user didn't press enter - switch (document.activeElement.id) { - case "rs-width-percentage": - changedWidthPercentage(); - break; - case "rs-width": - changedWidth(); - break; - case "rs-height-percentage": - changedHeightPercentage(); - break; - case "rs-height": - changedHeight(); - break; - default: - // In this case everything has been updated correctly - break; - } - - // Computing newWidth and newHeight - if (ratio == null) { - newWidth = data.width; - newHeight = data.height; - } - else { - newWidth = currFile.canvasSize[0] * ratio[0]; - newHeight = currFile.canvasSize[1] * ratio[1]; - } - - // Get all the image datas - for (let i=0; i
    -
  • +
  • From 05beab692960c14f0337d8ff577c06759665634b Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Tue, 7 Dec 2021 12:11:40 +0100 Subject: [PATCH 82/91] Removed a few dependencies, refactored pixel-editor.js --- js/ColorPicker.js | 12 +-------- js/Dialogue.js | 2 +- js/EditorState.js | 44 +++++++++++++++------------------ js/FileManager.js | 4 +-- js/Input.js | 2 +- js/LayerList.js | 22 +++++++++++++++++ js/PaletteBlock.js | 4 --- js/Settings.js | 4 +-- js/Startup.js | 14 +++-------- js/Tool.js | 21 +--------------- js/ToolManager.js | 10 ++++---- js/TopMenuModule.js | 8 +++--- js/layers/PixelGrid.js | 3 +++ js/pixel-editor.js | 55 +++++++++++++++++++++--------------------- refactor_dependencies | 10 +++----- 15 files changed, 94 insertions(+), 121 deletions(-) diff --git a/js/ColorPicker.js b/js/ColorPicker.js index eae3659..4fb951b 100644 --- a/js/ColorPicker.js +++ b/js/ColorPicker.js @@ -50,7 +50,6 @@ const ColorPicker = (() => { init(); function init() { - // TODO: BIND EVENTS // Appending the palette styles document.getElementsByTagName("head")[0].appendChild(styleElement); @@ -302,7 +301,6 @@ const ColorPicker = (() => { sliders[2].getElementsByTagName("label")[0].innerHTML = 'L'; break; default: - console.log("wtf select a decent picker mode"); break; } @@ -447,9 +445,7 @@ const ColorPicker = (() => { currPickerIconPos[0][1] = miniPickerCanvas.height - yPos; if (currPickerIconPos[0][1] >= 92) - { currPickerIconPos[0][1] = 91.999; - } activePickerIcon.style.left = '' + xPos + 'px'; activePickerIcon.style.top = '' + (miniPickerCanvas.height - yPos) + 'px'; @@ -467,8 +463,6 @@ const ColorPicker = (() => { let newHsv = currColor.hsv; let newHex; - console.log("Hex: " + currColor.hex); - // Adding slider value to value newHsv = new Color("hsv", newHsv.h, newHsv.s, parseInt(event.target.value)); // Updating hex @@ -575,7 +569,6 @@ const ColorPicker = (() => { case 'analog': createIcon(); createIcon(); - nHexContainers = 2; break; case 'cmpt': @@ -594,13 +587,11 @@ const ColorPicker = (() => { nHexContainers = 2; break; case 'tetra': - for (let i=0; i<3; i++) { + for (let i=0; i<3; i++) createIcon(); - } nHexContainers = 3; break; default: - console.log("How did you select the " + currentPickingMode + ", hackerman?"); break; } @@ -632,7 +623,6 @@ const ColorPicker = (() => { let currentColourHsv = new Color("hex", currentColorHex).hsv; let newColourHsv; let newColourHexes = ['', '', '']; - let tmpRgb; switch (currentPickingMode) { diff --git a/js/Dialogue.js b/js/Dialogue.js index ab687bf..26fcc8d 100644 --- a/js/Dialogue.js +++ b/js/Dialogue.js @@ -42,7 +42,7 @@ const Dialogue = (() => { document.getElementById(dialogueName).style.display = 'block'; // If I'm opening the palette window, I initialize the colour picker - if (dialogueName == 'palette-block' && Startup.documentCreated()) { + if (dialogueName == 'palette-block' && EditorState.documentCreated()) { ColorPicker.init(); PaletteBlock.init(); } diff --git a/js/EditorState.js b/js/EditorState.js index ee1761a..54d78c1 100644 --- a/js/EditorState.js +++ b/js/EditorState.js @@ -1,5 +1,6 @@ const EditorState = (() => { let pixelEditorMode = "Basic"; + let firstFile = true; Events.on('click', 'switch-editor-mode-splash', chooseMode); Events.on('click', 'switch-mode-button', toggleMode); @@ -11,35 +12,16 @@ const EditorState = (() => { function switchMode(newMode) { //switch to advanced mode if (newMode == 'Advanced') { - // Show the layer menus - LayerList.getLayerListEntries().style.display = "inline-block"; - document.getElementById('layer-button').style.display = 'inline-block'; + Events.emit("switchedToAdvanced"); // Hide the palette menu document.getElementById('colors-menu').style.right = '200px' pixelEditorMode = 'Advanced'; document.getElementById("switch-mode-button").innerHTML = 'Switch to basic mode'; - - //turn pixel grid off - currFile.pixelGrid.togglePixelGrid('off'); } //switch to basic mode - else { - //if there is a current layer (a document is active) - if (Startup.documentCreated()) { - if (!confirm('Switching to basic mode will flatten all the visible layers. Are you sure you want to continue?')) { - return; - } - - // Selecting the current layer - currFile.currentLayer.selectLayer(); - // Flatten the layers - LayerList.flatten(true); - } - - // Hide the layer menus - LayerList.getLayerListEntries().style.display = 'none'; - document.getElementById('layer-button').style.display = 'none'; + else { + Events.emit("switchedToBasic"); // Show the palette menu document.getElementById('colors-menu').style.display = 'flex'; // Move the palette menu @@ -47,7 +29,6 @@ const EditorState = (() => { pixelEditorMode = 'Basic'; document.getElementById("switch-mode-button").innerHTML = 'Switch to advanced mode'; - currFile.pixelGrid.togglePixelGrid('on'); } } @@ -73,8 +54,23 @@ const EditorState = (() => { switchMode('Advanced'); } + function documentCreated() { + return !firstFile; + } + + function firstPixel() { + return firstFile; + } + + function created() { + firstFile = false; + } + return { getCurrentMode, - switchMode + switchMode, + documentCreated, + created, + firstPixel } })(); \ No newline at end of file diff --git a/js/FileManager.js b/js/FileManager.js index eac00a4..9bd2f7f 100644 --- a/js/FileManager.js +++ b/js/FileManager.js @@ -58,7 +58,7 @@ const FileManager = (() => { } function exportProject() { - if (Startup.documentCreated()) { + if (EditorState.documentCreated()) { //create name let fileName = Util.getValue("export-file-name"); //set download link @@ -107,7 +107,7 @@ const FileManager = (() => { function open() { //if a document exists - if (Startup.documentCreated()) { + if (EditorState.documentCreated()) { //check if the user wants to overwrite if (confirm('Opening a pixel will discard your current one. Are you sure you want to do that?')) //open file selection dialog diff --git a/js/Input.js b/js/Input.js index 03d6c19..5f44c08 100644 --- a/js/Input.js +++ b/js/Input.js @@ -73,7 +73,7 @@ const Input = (() => { } //if no document has been created yet or there is a dialog box open ignore hotkeys - if (!Startup.documentCreated() || Dialogue.isOpen()) return; + if (!EditorState.documentCreated() || Dialogue.isOpen()) return; if (e.key === "Escape") { console.log("esc"); diff --git a/js/LayerList.js b/js/LayerList.js index 2b0d546..f1b48b9 100644 --- a/js/LayerList.js +++ b/js/LayerList.js @@ -9,6 +9,9 @@ const LayerList = (() => { Events.on("mousedown", layerList, openOptionsMenu); // Binding the add layer button to the right function Events.on('click',"add-layer-button", addLayer, false); + // Listening to the switch mode event so I can change the layout + Events.onCustom("switchedToAdvanced", showMenu); + Events.onCustom("switchedToBasic", hideMenu); // Making the layers list sortable new Sortable(layerList, { @@ -19,6 +22,25 @@ const LayerList = (() => { onEnd: layerDragDrop }); + function showMenu() { + layerList.style.display = "inline-block"; + document.getElementById('layer-button').style.display = 'inline-block'; + } + function hideMenu() { + if (EditorState.documentCreated()) { + if (!confirm('Switching to basic mode will flatten all the visible layers. Are you sure you want to continue?')) { + return; + } + // Selecting the current layer + currFile.currentLayer.selectLayer(); + // Flatten the layers + flatten(true); + } + + layerList.style.display = "none"; + document.getElementById('layer-button').style.display = 'none'; + } + function addLayer(id, saveHistory = true) { // layers.length - 3 let index = currFile.layers.length - 3; diff --git a/js/PaletteBlock.js b/js/PaletteBlock.js index edcb09d..b884076 100644 --- a/js/PaletteBlock.js +++ b/js/PaletteBlock.js @@ -1,14 +1,10 @@ const PaletteBlock = (() => { // HTML elements let coloursList = document.getElementById("palette-list"); - let rampMenu = document.getElementById("pb-ramp-options"); - let pbRampDialogue = document.getElementById("pb-ramp-dialogue"); // PaletteBlock-specific data let currentSquareSize = coloursList.children[0].clientWidth; let blockData = {blockWidth: 300, blockHeight: 320, squareSize: 40}; - let isRampSelecting = false; - let ramps = []; let currentSelection = {startIndex:0, endIndex:0, startCoords:[], endCoords: [], name: "", colour: "", label: null}; diff --git a/js/Settings.js b/js/Settings.js index dd66fa8..d152280 100644 --- a/js/Settings.js +++ b/js/Settings.js @@ -45,10 +45,10 @@ const Settings = (() => { settings.numberOfHistoryStates = Util.getValue('setting-numberOfHistoryStates'); settings.pixelGridColour = Util.getValue('setting-pixelGridColour'); // Filling pixel grid again if colour changed - currFile.pixelGrid.fillPixelGrid(); + Events.emit("refreshPixelGrid"); //save settings object to cookie - var cookieValue = JSON.stringify(settings); + let cookieValue = JSON.stringify(settings); Cookies.set('pixelEditorSettings', cookieValue, { expires: Infinity }); //close window diff --git a/js/Startup.js b/js/Startup.js index cff1559..2888880 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -1,6 +1,4 @@ const Startup = (() => { - - let firstPixel = true; let splashPostfix = ''; Events.on('click', 'create-button', create, false); @@ -55,10 +53,9 @@ const Startup = (() => { currFile.layers[1].selectLayer(); } - console.log("Starting with mode " + EditorState.getCurrentMode()); EditorState.switchMode(EditorState.getCurrentMode()); // This is not the first Pixel anymore - firstPixel = false; + EditorState.created(); } function initLayers(width, height) { @@ -66,7 +63,7 @@ const Startup = (() => { currFile.canvasSize = [width, height]; // If this is the first pixel I'm creating since the app has started - if (firstPixel) { + if (EditorState.firstPixel()) { // Creating the first layer currFile.currentLayer = new Layer(width, height, 'pixel-canvas', ""); currFile.currentLayer.canvas.style.zIndex = 2; @@ -113,7 +110,7 @@ const Startup = (() => { // Tmp layer to draw previews on currFile.TMPLayer = new Layer(width, height, 'tmp-canvas'); - if (firstPixel) { + if (EditorState.firstPixel()) { // Adding the first layer and the checkerboard to the list of layers currFile.layers.push(currFile.checkerBoard); currFile.layers.push(currFile.currentLayer); @@ -227,10 +224,6 @@ const Startup = (() => { newPixel(x, y); } - function documentCreated() { - return !firstPixel; - } - function splashEditorMode(mode) { editorMode = mode; } @@ -239,7 +232,6 @@ const Startup = (() => { create, newPixel, newFromTemplate, - documentCreated, splashEditorMode } })(); \ No newline at end of file diff --git a/js/Tool.js b/js/Tool.js index 38ec763..0a9e43e 100644 --- a/js/Tool.js +++ b/js/Tool.js @@ -123,23 +123,4 @@ class Tool { get size() { return this.currSize; } -} - - -/*global dragging currentTool, currentToolTemp, selectionCanceled, endSelection*/ - -/** - * Class selectionTool extends Tool { - * imageDataToMove - * startDataPos - * currDataPos - * finalDataPos - * canMove - * - * movePreview() - * - * // start and end selection just overwrite the onStart and onEnd methods - * - * } - * - */ \ No newline at end of file +} \ No newline at end of file diff --git a/js/ToolManager.js b/js/ToolManager.js index f025ef2..3177956 100644 --- a/js/ToolManager.js +++ b/js/ToolManager.js @@ -30,13 +30,13 @@ const ToolManager = (() => { Events.onCustom("tool-shortcut", onShortcut); function onShortcut(tool) { - if (!Startup.documentCreated || Dialogue.isOpen()) + if (!EditorState.documentCreated || Dialogue.isOpen()) return; switchTool(tools[tool]); } function onMouseWheel(mouseEvent) { - if (!Startup.documentCreated || Dialogue.isOpen()) + if (!EditorState.documentCreated || Dialogue.isOpen()) return; let mousePos = Input.getCursorPosition(mouseEvent); @@ -44,7 +44,7 @@ const ToolManager = (() => { } function onMouseDown(mouseEvent) { - if (!Startup.documentCreated() || Dialogue.isOpen()) + if (!EditorState.documentCreated() || Dialogue.isOpen()) return; let mousePos = Input.getCursorPosition(mouseEvent); @@ -75,7 +75,7 @@ const ToolManager = (() => { } function onMouseMove(mouseEvent) { - if (!Startup.documentCreated() || Dialogue.isOpen()) + if (!EditorState.documentCreated() || Dialogue.isOpen()) return; let mousePos = Input.getCursorPosition(mouseEvent); // Call the hover event @@ -108,7 +108,7 @@ const ToolManager = (() => { } function onMouseUp(mouseEvent) { - if (!Startup.documentCreated()) + if (!EditorState.documentCreated()) return; let mousePos = Input.getCursorPosition(mouseEvent); diff --git a/js/TopMenuModule.js b/js/TopMenuModule.js index 14097b7..885ab38 100644 --- a/js/TopMenuModule.js +++ b/js/TopMenuModule.js @@ -44,7 +44,7 @@ const TopMenuModule = (() => { break; case 'Exit': //if a document exists, make sure they want to delete it - if (Startup.documentCreated()) { + if (EditorState.documentCreated()) { //ask user if they want to leave if (confirm('Exiting will discard your current pixel. Are you sure you want to do that?')) //skip onbeforeunload prompt @@ -64,12 +64,10 @@ const TopMenuModule = (() => { Events.on('click', currSubmenuButton, function(){Events.emit("ctrl+x");}); break; case 'Cancel': - //Events.on('click', currSubmenuButton, tool.pencil.switchTo); + Events.on('click', currSubmenuButton, function(){Events.emit("esc-pressed")}); break; - //Help Menu + //Help Menu case 'Settings': - //fill form with current settings values - //Util.setValue('setting-numberOfHistoryStates', settings.numberOfHistoryStates); Events.on('click', currSubmenuButton, Dialogue.showDialogue, 'settings'); break; case 'Help': diff --git a/js/layers/PixelGrid.js b/js/layers/PixelGrid.js index aba8ffd..1a830a3 100644 --- a/js/layers/PixelGrid.js +++ b/js/layers/PixelGrid.js @@ -17,6 +17,9 @@ class PixelGrid extends Layer { initialize() { super.initialize(); this.fillPixelGrid(); + Events.onCustom("refreshPixelGrid", this.fillPixelGrid.bind(this)); + Events.onCustom("switchedToAdvanced", this.disablePixelGrid.bind(this)); + Events.onCustom("switchedToBasic", this.enablePixelGrid.bind(this)); } disablePixelGrid() { diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 43f74d6..1b4822d 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -1,22 +1,34 @@ -/**EXTERNALS AND LIBRARIES**/ +/** EXTERNALS AND LIBRARIES **/ //=include lib/cookies.js //=include lib/jscolor.js //=include lib/sortable.js -/**UTILITY AND INPUT*/ +//=include data/consts.js +//=include data/palettes.js + +/** UTILITY AND INPUT **/ //=include Util.js //=include Events.js //=include Dialogue.js //=include History.js +//=include Settings.js +//=include EditorState.js +/** COLOR-RELATED **/ //=include Color.js +//=include ColorPicker.js +//=include PaletteBlock.js - +/** BASE CLASSES **/ //=include File.js -//=include ColorModule.js - //=include Tool.js +//=include layers/Layer.js +/** SPECIAL LAYERS **/ +//=include layers/Checkerboard.js +//=include layers/PixelGrid.js + +/** TOOLS **/ //=include tools/ResizableTool.js //=include tools/SelectionTool.js @@ -31,35 +43,22 @@ //=include tools/RectangularSelectionTool.js //=include tools/MoveSelectionTool.js -/**init**/ -//=include data/consts.js -//=include Settings.js -//=include LayerList.js -//=include layers/Layer.js -//=include layers/Checkerboard.js -//=include layers/PixelGrid.js - -//=include Startup.js -//=include EditorState.js -//=include ToolManager.js - -/**dropdown formatting**/ -//=include PresetModule.js -//=include data/palettes.js - -/**functions**/ -//=include ColorPicker.js -//=include PaletteBlock.js +/** MODULES AND MENUS **/ //=include SplashPage.js +//=include PresetModule.js +//=include ColorModule.js +//=include ToolManager.js +//=include LayerList.js -/**menus**/ +/** STARTUP AND FILE MANAGEMENT **/ +//=include Startup.js //=include FileManager.js //=include TopMenuModule.js -/**event listeners**/ +/** HTML INPUT EVENTS **/ //=include Input.js -/**feature toggles**/ +/** IHER **/ //=include FeatureToggles.js // Controls execution of this preset module @@ -118,7 +117,7 @@ window.onload = function () { //prevent user from leaving page with unsaved data window.onbeforeunload = function() { - if (documentCreated) + if (EditorState.documentCreated) return 'You will lose your pixel if it\'s not saved!'; else return; diff --git a/refactor_dependencies b/refactor_dependencies index dfc3441..1799cd8 100644 --- a/refactor_dependencies +++ b/refactor_dependencies @@ -1,12 +1,8 @@ Input <- Startup, LayerList, TopMenuModule: Could be resolved by using custom events +FileManager <- LayerList, File, Startup, EditorState, ColorModule + Startup <- ColorModule, ToolManager, LayerList, EditorState, Layer(++) -EditorState <- LayerList, File, Startup(documentCreated): maybe documentCreated should stay in EditorState (that would fix the - circular dependency with Startup), for the other dependencies it'd probably be nice for them to listen to a custom events +TopMenuModule -> Startup -Color <- NONE - -ColorModule <- File - -File <- Startup, but only because Startup sets certain variables in File (pixelGrid, checkerboard and the other global layers) From 55f514b92e5bf1673d1cc8b9203ef4f6d9097ab1 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Tue, 7 Dec 2021 23:01:49 +0100 Subject: [PATCH 83/91] Fixed pixel grid bug --- js/EditorState.js | 3 +++ js/LayerList.js | 3 --- js/Startup.js | 1 + js/layers/PixelGrid.js | 47 ++++++++++++++++++++++++------------------ refactor_dependencies | 8 ------- 5 files changed, 31 insertions(+), 31 deletions(-) delete mode 100644 refactor_dependencies diff --git a/js/EditorState.js b/js/EditorState.js index 54d78c1..56f16db 100644 --- a/js/EditorState.js +++ b/js/EditorState.js @@ -10,6 +10,9 @@ const EditorState = (() => { } function switchMode(newMode) { + if (!firstFile && newMode == "Basic" && !confirm('Switching to basic mode will flatten all the visible layers. Are you sure you want to continue?')) { + return; + } //switch to advanced mode if (newMode == 'Advanced') { Events.emit("switchedToAdvanced"); diff --git a/js/LayerList.js b/js/LayerList.js index f1b48b9..66a0b13 100644 --- a/js/LayerList.js +++ b/js/LayerList.js @@ -28,9 +28,6 @@ const LayerList = (() => { } function hideMenu() { if (EditorState.documentCreated()) { - if (!confirm('Switching to basic mode will flatten all the visible layers. Are you sure you want to continue?')) { - return; - } // Selecting the current layer currFile.currentLayer.selectLayer(); // Flatten the layers diff --git a/js/Startup.js b/js/Startup.js index 2888880..999bb0a 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -103,6 +103,7 @@ const Startup = (() => { // Adding the checkerboard behind it currFile.checkerBoard = new Checkerboard(width, height, null); // Pixel grid + console.log("CREATED GRID"); currFile.pixelGrid = new PixelGrid(width, height, "pixel-grid"); // Creating the vfx layer on top of everything diff --git a/js/layers/PixelGrid.js b/js/layers/PixelGrid.js index 1a830a3..77153e3 100644 --- a/js/layers/PixelGrid.js +++ b/js/layers/PixelGrid.js @@ -12,14 +12,14 @@ class PixelGrid extends Layer { constructor(width, height, canvas, menuEntry) { super(width, height, canvas, menuEntry); this.initialize(); + Events.onCustom("refreshPixelGrid", this.fillPixelGrid.bind(this)); + Events.onCustom("switchedToAdvanced", this.togglePixelGrid.bind(this)); + Events.onCustom("switchedToBasic", this.togglePixelGrid.bind(this)); } initialize() { super.initialize(); this.fillPixelGrid(); - Events.onCustom("refreshPixelGrid", this.fillPixelGrid.bind(this)); - Events.onCustom("switchedToAdvanced", this.disablePixelGrid.bind(this)); - Events.onCustom("switchedToBasic", this.enablePixelGrid.bind(this)); } disablePixelGrid() { @@ -28,10 +28,25 @@ class PixelGrid extends Layer { } enablePixelGrid() { + if (!this.pixelGridVisible) + return; this.pixelGridEnabled = true; this.canvas.style.display = "inline-block"; } + hidePixelGrid() { + let button = document.getElementById("toggle-pixelgrid-button"); + this.pixelGridVisible = false; + button.innerHTML = "Show pixel grid"; + this.canvas.style.display = "none"; + } + showPixelGrid() { + let button = document.getElementById("toggle-pixelgrid-button"); + this.pixelGridVisible = true; + button.innerHTML = "Hide pixel grid"; + this.canvas.style.display = "inline-block"; + } + repaintPixelGrid(factor) { this.lineDistance += factor; this.fillPixelGrid(); @@ -42,24 +57,16 @@ class PixelGrid extends Layer { * */ togglePixelGrid(newState) { - // Getting the button because I have to change its text - let button = document.getElementById("toggle-pixelgrid-button"); - //Set the state based on the passed newState variable, otherwise just toggle it - if (newState == 'on') this.pixelGridVisible = true; - else if (newState == 'off') this.pixelGridVisible = false; - else this.pixelGridVisible = !this.pixelGridVisible; - - // If it was visible, I hide it - if (this.pixelGridVisible) { - button.innerHTML = "Hide pixel grid"; - this.canvas.style.display = "inline-block"; - } - // Otherwise, I show it - else { - button.innerHTML = "Show pixel grid"; - this.canvas.style.display = "none"; - } + if (newState == 'on') + this.showPixelGrid(); + else if (newState == 'off') + this.hidePixelGrid(); + else + if (this.pixelGridVisible) + this.hidePixelGrid(); + else + this.showPixelGrid(); } /** Fills the pixelGridCanvas with the pixelgrid diff --git a/refactor_dependencies b/refactor_dependencies deleted file mode 100644 index 1799cd8..0000000 --- a/refactor_dependencies +++ /dev/null @@ -1,8 +0,0 @@ -Input <- Startup, LayerList, TopMenuModule: Could be resolved by using custom events - -FileManager <- LayerList, File, Startup, EditorState, ColorModule - -Startup <- ColorModule, ToolManager, LayerList, EditorState, Layer(++) - -TopMenuModule -> Startup - From a238fb1b4719846b5e4ac044c116fa8a94bd1400 Mon Sep 17 00:00:00 2001 From: Nicola <47360416+unsettledgames@users.noreply.github.com> Date: Sat, 11 Dec 2021 10:48:14 +0100 Subject: [PATCH 84/91] Fixed #43, #41, #37 and #35 --- js/ColorModule.js | 7 +-- js/Input.js | 13 ++++- js/LayerList.js | 4 +- js/layers/Layer.js | 9 ++++ js/layers/PixelGrid.js | 4 +- package-lock.json | 106 +++++++++++++++++++---------------------- package.json.bak | 39 +++++++++++++++ 7 files changed, 117 insertions(+), 65 deletions(-) create mode 100644 package.json.bak diff --git a/js/ColorModule.js b/js/ColorModule.js index 2a194e6..9b90237 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -101,7 +101,7 @@ const ColorModule = (() => { document.querySelector('#colors-menu li.selected')?.classList.remove('selected'); //set current color - updateCurrentColor(e.target.style.backgroundColor); + updateCurrentColor(Color.cssToHex(e.target.style.backgroundColor)); //make color selected e.target.parentElement.classList.add('selected'); @@ -136,8 +136,6 @@ const ColorModule = (() => { //show color picker addedColor.firstElementChild.jscolor.show(); - console.log('showing picker'); - //hide edit button addedColor.lastChild.classList.add('hidden'); } @@ -427,6 +425,9 @@ const ColorModule = (() => { } function updateCurrentColor(color, refLayer) { + if (color[0] != '#') + color = '#' + color; + if (refLayer) color = refLayer.context.fillStyle; diff --git a/js/Input.js b/js/Input.js index 5f44c08..df7cbf1 100644 --- a/js/Input.js +++ b/js/Input.js @@ -1,6 +1,7 @@ const Input = (() => { let dragging = false; let currentMouseEvent = undefined; + let lastMouseTarget = undefined; let spacePressed = false; let altPressed = false; let ctrlPressed = false; @@ -19,6 +20,7 @@ const Input = (() => { Events.on("mouseup", window, onMouseUp); function onMouseDown(event) { + lastMouseTarget = event.target; currentMouseEvent = event; dragging = true; @@ -154,6 +156,10 @@ const Input = (() => { case 32: spacePressed = true; break; + case 46: + console.log("Pressed del"); + Events.emit("del"); + break; } } } @@ -178,12 +184,17 @@ const Input = (() => { return spacePressed; } + function getLastTarget() { + return lastMouseTarget; + } + return { isDragging, getCurrMouseEvent, getCursorPosition, isAltPressed, isCtrlPressed, - isSpacePressed + isSpacePressed, + getLastTarget } })(); \ No newline at end of file diff --git a/js/LayerList.js b/js/LayerList.js index 66a0b13..c0a2107 100644 --- a/js/LayerList.js +++ b/js/LayerList.js @@ -345,11 +345,11 @@ const LayerList = (() => { // Merging all the layer but the last one for (let i=0; i this.hover(); this.menuEntry.onmouseout = () => this.unhover(); this.menuEntry.onclick = () => this.selectLayer(); @@ -63,6 +64,8 @@ class Layer { this.menuEntry.addEventListener("dragleave", this.layerDragLeave, false); this.menuEntry.addEventListener("dragend", this.layerDragEnd, false); + Events.onCustom("del", this.tryDelete.bind(this)); + this.menuEntry.getElementsByTagName("canvas")[0].getContext('2d').imageSmoothingEnabled = false; } @@ -73,6 +76,12 @@ class Layer { return this.menuEntry != null; } + tryDelete() { + if (Input.getLastTarget() != this.menuEntry && Input.getLastTarget().parentElement != this.menuEntry) + return; + LayerList.deleteLayer(); + } + // Initializes the canvas initialize() { //resize canvas diff --git a/js/layers/PixelGrid.js b/js/layers/PixelGrid.js index 77153e3..5401ccb 100644 --- a/js/layers/PixelGrid.js +++ b/js/layers/PixelGrid.js @@ -3,7 +3,7 @@ class PixelGrid extends Layer { // Start colour of the pixel grid (can be changed in the preferences) pixelGridColor = "#000000"; // Distance between one line and another in HTML pixels - lineDistance = 11; + lineDistance = 10; // The grid is not visible by default pixelGridVisible = false; // The grid is enabled, but is disabled in order to save performance with big sprites @@ -82,6 +82,8 @@ class PixelGrid extends Layer { this.context.strokeStyle = Settings.getCurrSettings().pixelGridColour; + console.log("Line ditance: " + this.lineDistance) + // OPTIMIZABLE, could probably be a bit more elegant // Draw horizontal lines for (let i=0; i= 6" - } - }, - "node_modules/reload/node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" + "node": ">= 10" } }, "node_modules/remove-bom-buffer": { @@ -7365,9 +7352,9 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "node_modules/url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", + "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", "dev": true, "dependencies": { "querystringify": "^2.1.1", @@ -7705,12 +7692,24 @@ } }, "node_modules/ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", "dev": true, "engines": { "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/xdg-basedir": { @@ -12398,37 +12397,27 @@ } }, "reload": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/reload/-/reload-3.1.1.tgz", - "integrity": "sha512-JblFn8P8CUfKqpclWNGs6rhda4hmywTq/a8DyjmwoGZ7Lp2krZ3swXgU3guvZ0waI3rorXFVS6z6UkKLYulmMA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/reload/-/reload-3.2.0.tgz", + "integrity": "sha512-30iJoDvFHGbfq6tT3Vag/4RV3wkpuCOqPSM3GyeuOSSo48wKfZT/iI19oeO0GCVX0XSr+44XJ6yBiRJWqOq+sw==", "dev": true, "requires": { "cli-color": "~2.0.0", - "commander": "~6.1.0", + "commander": "~7.2.0", "finalhandler": "~1.1.1", "minimist": "~1.2.0", - "open": "^7.0.0", + "open": "^8.0.0", "serve-static": "~1.14.0", "supervisor": "~0.12.0", - "url-parse": "~1.4.4", - "ws": "~7.3.0" + "url-parse": "~1.5.0", + "ws": "~7.4.0" }, "dependencies": { "commander": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz", - "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true - }, - "open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, - "requires": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - } } } }, @@ -13651,9 +13640,9 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", + "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", "dev": true, "requires": { "querystringify": "^2.1.1", @@ -13936,10 +13925,11 @@ } }, "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", - "dev": true + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "dev": true, + "requires": {} }, "xdg-basedir": { "version": "4.0.0", diff --git a/package.json.bak b/package.json.bak new file mode 100644 index 0000000..0001d7b --- /dev/null +++ b/package.json.bak @@ -0,0 +1,39 @@ +{ + "name": "pixel-editor", + "version": "1.0.0", + "description": "Online pixel art creation tool", + "main": "build.js", + "scripts": { + "build": "node ./build.js ./build", + "serve": "node ./server.js ./build 3000", + "test": "npm run build && npm run serve", + "hot": "concurrently \"nodemon --exec npm test\" \"await tcp localhost:3000 && open-cli http://localhost:3000\"", + "hot:reload": "cross-env RELOAD=yes npm run hot" + }, + "author": "Lospec", + "license": "ISC", + "nodemonConfig": { + "ext": "js,hbs,scss", + "ignore": "build/" + }, + "dependencies": { + "concurrently": "^6.0.2", + "express": "^4.16.4", + "fs-extra": "^7.0.1", + "gulp": "^4.0.2", + "gulp-hb": "^8.0.0", + "gulp-include": "^2.3.1", + "gulp-rename": "^2.0.0", + "gulp-sass": "^7.0", + "handlebars-helper-svg": "^2.0.2", + "nodemon": "^2.0.7", + "open": "^8.0.6", + "open-cli": "^6.0.1", + "sass": "^1.17.3" + }, + "devDependencies": { + "cross-env": "7.0.3", + "reload": "^3.2.0", + "wait-cli": "^1.0.0" + } +} From 1bac62be4c4fb9f831b72fb2c6e6451160b20a56 Mon Sep 17 00:00:00 2001 From: Nicola <47360416+unsettledgames@users.noreply.github.com> Date: Sat, 11 Dec 2021 12:48:12 +0100 Subject: [PATCH 85/91] Fixed #45, #44, #40, #38 --- js/History.js | 12 ------------ js/LayerList.js | 2 +- js/PaletteBlock.js | 3 +++ js/Settings.js | 2 +- js/layers/Layer.js | 25 +++++++++---------------- 5 files changed, 14 insertions(+), 30 deletions(-) diff --git a/js/History.js b/js/History.js index 89f505c..f619b3e 100644 --- a/js/History.js +++ b/js/History.js @@ -1,15 +1,3 @@ -/** BUG: - * - Create a new pixel - * - Open a png file - * - Draw with the pencil - * - Hit CTRL+Z - * - RESULT: undo doesn't work, the app can't find the current layer - * - * - RELATED: when opening an LPE file, the app draws on a layer that is below the one in which the - * file is loaded. This is because the data is loaded on new layers, but the first one - * isn't removed and sometimes it could have the same ID of a recently added layer. - */ - /** How the history works * - undoStates stores the states that can be undone * - redoStates stores the states that can be redone diff --git a/js/LayerList.js b/js/LayerList.js index c0a2107..9c52c47 100644 --- a/js/LayerList.js +++ b/js/LayerList.js @@ -382,7 +382,7 @@ const LayerList = (() => { Layer.layerOptions.style.top = "0"; Layer.layerOptions.style.marginTop = "" + (event.clientY - 25) + "px"; - getLayerByID(selectedId).selectLayer(); + getLayerByID(selectedId).selectLayer(false); } } diff --git a/js/PaletteBlock.js b/js/PaletteBlock.js index b884076..c62e7be 100644 --- a/js/PaletteBlock.js +++ b/js/PaletteBlock.js @@ -131,6 +131,9 @@ const PaletteBlock = (() => { currentSelection.startCoords = getColourCoordinates(index); currentSelection.endCoords = getColourCoordinates(index); } + else if (mouseEvent.which == 1) { + endRampSelection(mouseEvent); + } } /** Updates the outline for the current selection. diff --git a/js/Settings.js b/js/Settings.js index d152280..bb9e63d 100644 --- a/js/Settings.js +++ b/js/Settings.js @@ -21,7 +21,7 @@ const Settings = (() => { enableDynamicCursorOutline: true, //unused - performance enableBrushPreview: true, //unused - performance enableEyedropperPreview: true, //unused - performance - numberOfHistoryStates: 20, + numberOfHistoryStates: 256, maxColorsOnImportedImage: 128, pixelGridColour: '#000000' }; diff --git a/js/layers/Layer.js b/js/layers/Layer.js index 3d6a7a7..466086c 100644 --- a/js/layers/Layer.js +++ b/js/layers/Layer.js @@ -186,23 +186,16 @@ class Layer { this.canvas.style.top = otherLayer.canvas.style.top; } - selectLayer(layer) { - if (layer == null) { - // Deselecting the old layer - currFile.currentLayer.deselectLayer(); + selectLayer(hideOptions = true) { + if (hideOptions) + LayerList.closeOptionsMenu(); + // Deselecting the old layer + currFile.currentLayer.deselectLayer(); - // Selecting the current layer - this.isSelected = true; - this.menuEntry.classList.add("selected-layer"); - currFile.currentLayer = LayerList.getLayerByName(this.menuEntry.getElementsByTagName("p")[0].innerHTML); - } - else { - currFile.currentLayer.deselectLayer(); - - layer.isSelected = true; - layer.menuEntry.classList.add("selected-layer"); - currFile.currentLayer = layer; - } + // Selecting the current layer + this.isSelected = true; + this.menuEntry.classList.add("selected-layer"); + currFile.currentLayer = this; } toggleLock() { From be852d9aae95ae2bbc022eee7ca342ded8485bb2 Mon Sep 17 00:00:00 2001 From: Nicola <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 12 Dec 2021 18:37:16 +0100 Subject: [PATCH 86/91] Fixed #48 and #47 --- build.js | 2 + images/Logs/grid.png | Bin 0 -> 24201 bytes js/ColorPicker.js | 6 ++- js/PaletteBlock.js | 4 +- js/ToolManager.js | 9 ++-- views/compatibility-warning.hbs | 3 +- views/latestLog.hbs | 84 +++++++++++--------------------- views/logs/splash-update.hbs | 65 ++++++++++++++++++++++++ 8 files changed, 109 insertions(+), 64 deletions(-) create mode 100644 images/Logs/grid.png create mode 100644 views/logs/splash-update.hbs diff --git a/build.js b/build.js index b4b45a9..5b4b4d0 100644 --- a/build.js +++ b/build.js @@ -21,6 +21,8 @@ function copy_images(){ gulp.src('./images/Splash images/*.png').pipe(gulp.dest(BUILDDIR)); // Logs images gulp.src('./images/Logs/*.gif').pipe(gulp.dest(BUILDDIR)); + // Logs images + gulp.src('./images/Logs/*.png').pipe(gulp.dest(BUILDDIR)); } function copy_logs() { diff --git a/images/Logs/grid.png b/images/Logs/grid.png new file mode 100644 index 0000000000000000000000000000000000000000..b13f584cbb5e570039cc540aec659883a775b495 GIT binary patch literal 24201 zcmeHPQA|@;7`_moP^^+}orc&dSy;Bzm=L!m${f3;8-i01iDeJ9P?ND_F`8j%6X$9u z=t?&9!Ne>^X>dk|rnL_yvltn5M4#xENJiKMNnDy$q&VYhN87t|ZoQY5%?nKyL(KQk za7)^A|DK$C{_lMM|9#H7?NthSv7BKTMfDbaJ;UUv87BK$em42fx=7vkeU*-J z53l}%yvb={x3LW4JysZN&L!^)_HX&9m0^?z=qqdd<25#h*{!M8vkkW055~&+_OhoO zEdl%b?q!-v*|ys69`w|IJLb1W*VYVb&lCpzE2{^4o47R{MY{Zwj-o$L#==}8%ssTn zd$>q6z|G1u=FZ$pmk+DXl)pqj!)eAn377dLT^w=JjlL_VqerKIhvJd4_VlUy2XhGos-_@8$j zvi#(7w@zskp-n$_|Lk&CPOVae{+5TkN@xgVyw;ZXTCZn$@oh`@owKa*=x7LZc$l22K~eJ9K>$iDF~hF(Dv6wnLq% zKWOm$s6j>ox;ZTbl#IFP0?)Fg`4 z{Z&Fhd~DbK{pNf+qq&!6e*5O`&Z&!zJWLiQ3oC1GU%_LDJu5AzV1q|C1ats&0M6o3 zGC*naNC5q4% zJBu1`@O&&{kFOX5!vi`DbXW@23OWpQ80aui_^5ZFIE3O5vLUh|vLUh|vLUh|vf=a2 zhS{VO=-$MQ)UK7ogx!fo(t2Xn5*jG6Ij!S{kW9zzD^mM;o;g%3Xk=+m61kPVAS~zm zlXSOCH^Q!z4xS9gOAGDE2`=H`*i+~bLOT`T+Xk`?WE;pfmm6J;C?KPNi~=$W$S5F- z1?1;_yg-kCQg8uK3Q!7A3Q+n~Gxg%=lAcNWq>(gBg+IExGch}mknM#A41&3*f<}l> zAU=Wk1mcsWC_brahTgq4h)_EzKV4 zEnJtecOj{^Gn7#E>m5Gn#ibmHYulW87HLdW+Ba*MQZ6JR$ApREc1)P)QGgXDx+ma~ z6n!1AhY9u^*z`r?5M)Ww(gd(Vbfy8USbDHxQ4+NOurSI%9T%(+nw9dSTWtnT*M?@PB zi350PU%B89hzY}lQHx1Zk--WRohb20Qo~Y;!?1^mR;SqXdCyvk!;mFKFI~V2YFo_X zFu)4Ye;7C{>0G@SSneUZq4+#o1aJVVpkuy`snY=nCzj zq9QqNVp5RPML$hprGznvSCch2skXc4!AD=r8Q2${;No`X%GXZyuf~h#h { function movePickerIcon(event) { event.preventDefault(); - if (event.which == 1 || draggingCursor) { + if (event.buttons == 1 || draggingCursor) { let cursorPos = getCursorPosMinipicker(event); let canvasRect = miniPickerCanvas.getBoundingClientRect(); @@ -507,6 +507,10 @@ const ColorPicker = (() => { styles[1] += "background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(0,0,0,1) 0%, " + "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + ",1) 100%);}"; + styles[1] += "input[type=range]#cp-minipicker-slider::-moz-range-track { background: rgb(2,0,36);"; + styles[1] += "background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(0,0,0,1) 0%, " + + "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + ",1) 100%);}"; + updateMiniPickerSpectrum(); updateStyles(); } diff --git a/js/PaletteBlock.js b/js/PaletteBlock.js index c62e7be..3035e43 100644 --- a/js/PaletteBlock.js +++ b/js/PaletteBlock.js @@ -141,11 +141,11 @@ const PaletteBlock = (() => { * @param {*} mouseEvent */ function updateRampSelection(mouseEvent) { - if (mouseEvent != null && mouseEvent.which == 3) { + if (mouseEvent != null && mouseEvent.buttons == 2) { currentSelection.endIndex = getElementIndex(mouseEvent.target); } - if (mouseEvent == null || mouseEvent.which == 3) { + if (mouseEvent == null || mouseEvent.buttons == 2) { let startCoords = getColourCoordinates(currentSelection.startIndex); let endCoords = getColourCoordinates(currentSelection.endIndex); diff --git a/js/ToolManager.js b/js/ToolManager.js index 3177956..99a8dcc 100644 --- a/js/ToolManager.js +++ b/js/ToolManager.js @@ -24,7 +24,7 @@ const ToolManager = (() => { Events.on("mouseup", window, onMouseUp); Events.on("mousemove", window, onMouseMove); Events.on("mousedown", window, onMouseDown); - Events.on("mousewheel", window, onMouseWheel); + Events.on("wheel", window, onMouseWheel); // Bind tool shortcuts Events.onCustom("tool-shortcut", onShortcut); @@ -36,6 +36,7 @@ const ToolManager = (() => { } function onMouseWheel(mouseEvent) { + console.log("MOUSE WHEEL"); if (!EditorState.documentCreated || Dialogue.isOpen()) return; @@ -82,7 +83,7 @@ const ToolManager = (() => { currTool.onHover(mousePos, mouseEvent.target); if (Input.isDragging()) { - switch (mouseEvent.which) { + switch (mouseEvent.buttons) { case 1: if (Input.isSpacePressed()) { tools["pan"].onDrag(mousePos, mouseEvent.target); @@ -94,10 +95,10 @@ const ToolManager = (() => { currTool.onDrag(mousePos, mouseEvent.target); } break; - case 2: + case 4: tools["pan"].onDrag(mousePos, mouseEvent.target); break; - case 3: + case 2: currTool.onRightDrag(mousePos, mouseEvent.target); break; default: diff --git a/views/compatibility-warning.hbs b/views/compatibility-warning.hbs index 29b7d78..02b002d 100644 --- a/views/compatibility-warning.hbs +++ b/views/compatibility-warning.hbs @@ -11,5 +11,4 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/views/latestLog.hbs b/views/latestLog.hbs index 6cdd02a..8c45377 100644 --- a/views/latestLog.hbs +++ b/views/latestLog.hbs @@ -1,65 +1,39 @@ -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. +Hi! Welcome to the latest version of the Pixel Editor. It's been quite a while! Most of the changes happened behind +the scenes: we worked very hard to refactor the code, make it a bit more modern and scalable so that contributions will, + hopefully, be easier to make.

    +We have some good news for users as well! -

    Splash page

    +

    Pixel Grid

    -The editor now has a splash page! Besides a fancy cover image with beautiful art, on the bottom -left of the page you'll be able to create a new custom pixel. You can also use the quickstart -menu to quickly select a preset or load an existing file. It was designed by Skeddles himself! +I've worked a bit on the pixel grid to make it look a bit better and less intrusive when zooming in. You can see the +difference in behaviour between the new grid (left) and the old grid (right) in the image below. + +In addition, the pixel grid will now automatically be hidden when the zoom level becomes too low: in that way looking at big +sprites becomes a lot less performance-heavy and it doesn't cause lag. - +

    Quality of life

    -Pro tip: once you've created a new project, you can go back to the splash page -by clicking on Editor -> Splash page - -

    Canvas resizing

    - -We implemented canvas resizing! If you wanted to draw a t-rex but created a 4x4 canvas, we've got you covered! -You can now click on Edit -> Resize canvas to decrease the size of the project. Same goes if you -drew an ant on a 1024x1024 canvas, just go to Edit -> Resize canvas and decrease -the dimensions. - - - -

    Sprite scaling

    - -In addition to the Lospec Pixel Art Scaler, -you can now take advantage of the editor's built-in scaling function. Just click on Edit -> Scale sprite -to scale up or down your work. With the nearest-neighbour algorithm you'll be able to scale sprites -in a pixel-perfect manner, while with bilinear interpolation it's possible to add (or remove, if you're scaling -down a sprite) antialiasing. - - - -

    Line tool

    - -Our contributor Liam added a new line tool! Quality of -life improvement are planned for it, the rectangle and the rectangular selection tools. - - - -

    Advanced mode: colour picker and palette block

    - -If you're a proud user of the advanced mode, you'll be able to try out the new colour picker: it -supports 3 colour models, 6 colour harmonies and multiple ways to input data. Next to it, -you'll find the new palette block, which lets you arrange your colours however you want, add and -remove multiple colours at once. Changes made in the palette block will update the palette list -you've always been familiar with. - - - -

    Other changes:

    +I've added some quality of life improvements, sometimes subtle (maybe you won't notice but you'd have definitely noticed +the absence of them), sometimes a bit more noticeable. For example:
      -
    • You can now move colours in the palette menu
    • -
    • Use View -> Pixel grid to show the pixel grid
    • -
    • Fixed a bunch of bugs, made the brush preview pixel perfect
    • -
    • Added Layer -> Duplicate to duplicate a layer
    • -
    • Quality of life development improvements by Nkoder and Pongles
    • -
    • Canvas trimming to get rid of all the extra space you have in your sprite
    • +
    • It's now possible to delete a layer by selecting it and hitting "DEL"
    • +
    • When adding a colour to the palette, it is automatically selected
    • +
    • Thanks to NSSure, you can now select a name for your exported / saved project
    • +
    • The brush preview should now be less intrusive while still being visible
    -

    That's all folks!

    -That's all for this update! Hope you have fun with this new release :)
    +

    Important bug fixes

    +A lot of nasty bugs have been fixed! Please, if you know more we aren't aware of, +feel free to open an issue or make a pull request. +
      +
    • Fixed the bug that caused file corruptions
    • +
    • Fixed fill tool not working and creating hundreds of similar colours in certain browsers
    • +
    • Fixed the build procedure for Windows
    • +
    • Fixed the editor ignoring the scale factor when exporting
    • +
    + +

    End of log

    +That's all for this update! We have some cool things planned for the near future, so stay tuned :)
    - Unsettled

    P.S.: we're always looking for contributors! Join the Lospec discord to get in touch! \ No newline at end of file diff --git a/views/logs/splash-update.hbs b/views/logs/splash-update.hbs new file mode 100644 index 0000000..6cdd02a --- /dev/null +++ b/views/logs/splash-update.hbs @@ -0,0 +1,65 @@ +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. + +

    Splash page

    + +The editor now has a splash page! Besides a fancy cover image with beautiful art, on the bottom +left of the page you'll be able to create a new custom pixel. You can also use the quickstart +menu to quickly select a preset or load an existing file. It was designed by Skeddles himself! + + + +Pro tip: once you've created a new project, you can go back to the splash page +by clicking on Editor -> Splash page + +

    Canvas resizing

    + +We implemented canvas resizing! If you wanted to draw a t-rex but created a 4x4 canvas, we've got you covered! +You can now click on Edit -> Resize canvas to decrease the size of the project. Same goes if you +drew an ant on a 1024x1024 canvas, just go to Edit -> Resize canvas and decrease +the dimensions. + + + +

    Sprite scaling

    + +In addition to the Lospec Pixel Art Scaler, +you can now take advantage of the editor's built-in scaling function. Just click on Edit -> Scale sprite +to scale up or down your work. With the nearest-neighbour algorithm you'll be able to scale sprites +in a pixel-perfect manner, while with bilinear interpolation it's possible to add (or remove, if you're scaling +down a sprite) antialiasing. + + + +

    Line tool

    + +Our contributor Liam added a new line tool! Quality of +life improvement are planned for it, the rectangle and the rectangular selection tools. + + + +

    Advanced mode: colour picker and palette block

    + +If you're a proud user of the advanced mode, you'll be able to try out the new colour picker: it +supports 3 colour models, 6 colour harmonies and multiple ways to input data. Next to it, +you'll find the new palette block, which lets you arrange your colours however you want, add and +remove multiple colours at once. Changes made in the palette block will update the palette list +you've always been familiar with. + + + +

    Other changes:

    +
      +
    • You can now move colours in the palette menu
    • +
    • Use View -> Pixel grid to show the pixel grid
    • +
    • Fixed a bunch of bugs, made the brush preview pixel perfect
    • +
    • Added Layer -> Duplicate to duplicate a layer
    • +
    • Quality of life development improvements by Nkoder and Pongles
    • +
    • Canvas trimming to get rid of all the extra space you have in your sprite
    • +
    + +

    That's all folks!

    +That's all for this update! Hope you have fun with this new release :)
    +- Unsettled +

    +P.S.: we're always looking for contributors! Join the Lospec discord to get in touch! \ No newline at end of file From 1d9ef0f372bc3f54f35d32d1f559314c7f83d5bc Mon Sep 17 00:00:00 2001 From: Nicola <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 12 Dec 2021 22:22:46 +0100 Subject: [PATCH 87/91] Fixed #46 --- js/ToolManager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/ToolManager.js b/js/ToolManager.js index 99a8dcc..4b9339f 100644 --- a/js/ToolManager.js +++ b/js/ToolManager.js @@ -59,7 +59,7 @@ const ToolManager = (() => { else if (Input.isAltPressed()) { tools["eyedropper"].onStart(mousePos, mouseEvent.target); } - else { + else if (!currFile.currentLayer.isLocked){ currTool.onStart(mousePos, mouseEvent.target); } break; @@ -91,7 +91,7 @@ const ToolManager = (() => { else if (Input.isAltPressed()) { tools["eyedropper"].onDrag(mousePos, mouseEvent.target); } - else { + else if (!currFile.currentLayer.isLocked){ currTool.onDrag(mousePos, mouseEvent.target); } break; @@ -122,7 +122,7 @@ const ToolManager = (() => { else if (Input.isAltPressed()) { tools["eyedropper"].onEnd(mousePos, mouseEvent.target); } - else { + else if (!currFile.currentLayer.isLocked){ currTool.onEnd(mousePos); } break; From 62130ae90dea548849a17643464fff79d974dcf3 Mon Sep 17 00:00:00 2001 From: Nicola <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 12 Dec 2021 22:50:21 +0100 Subject: [PATCH 88/91] Polished previous bug fix Now it's possible to use all non-resizable tool and even copy a locked layer to paste it on an unlocked one. --- js/ToolManager.js | 6 +++--- js/pixel-editor.js | 1 + js/tools/DrawingTool.js | 5 +++++ js/tools/FillTool.js | 2 +- js/tools/MoveSelectionTool.js | 6 +++++- js/tools/ResizableTool.js | 2 +- 6 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 js/tools/DrawingTool.js diff --git a/js/ToolManager.js b/js/ToolManager.js index 4b9339f..b5eaa8b 100644 --- a/js/ToolManager.js +++ b/js/ToolManager.js @@ -59,7 +59,7 @@ const ToolManager = (() => { else if (Input.isAltPressed()) { tools["eyedropper"].onStart(mousePos, mouseEvent.target); } - else if (!currFile.currentLayer.isLocked){ + else if (!currFile.currentLayer.isLocked || !((Object.getPrototypeOf(currTool) instanceof DrawingTool))) { currTool.onStart(mousePos, mouseEvent.target); } break; @@ -91,7 +91,7 @@ const ToolManager = (() => { else if (Input.isAltPressed()) { tools["eyedropper"].onDrag(mousePos, mouseEvent.target); } - else if (!currFile.currentLayer.isLocked){ + else if (!currFile.currentLayer.isLocked || !((Object.getPrototypeOf(currTool) instanceof DrawingTool))){ currTool.onDrag(mousePos, mouseEvent.target); } break; @@ -122,7 +122,7 @@ const ToolManager = (() => { else if (Input.isAltPressed()) { tools["eyedropper"].onEnd(mousePos, mouseEvent.target); } - else if (!currFile.currentLayer.isLocked){ + else if (!currFile.currentLayer.isLocked || !((Object.getPrototypeOf(currTool) instanceof DrawingTool))) { currTool.onEnd(mousePos); } break; diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 1b4822d..29a8087 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -29,6 +29,7 @@ //=include layers/PixelGrid.js /** TOOLS **/ +//=include tools/DrawingTool.js //=include tools/ResizableTool.js //=include tools/SelectionTool.js diff --git a/js/tools/DrawingTool.js b/js/tools/DrawingTool.js new file mode 100644 index 0000000..5153dbf --- /dev/null +++ b/js/tools/DrawingTool.js @@ -0,0 +1,5 @@ +class DrawingTool extends Tool { + constructor (name, options) { + super(name, options); + } +} \ No newline at end of file diff --git a/js/tools/FillTool.js b/js/tools/FillTool.js index 51890d7..cdcd0df 100644 --- a/js/tools/FillTool.js +++ b/js/tools/FillTool.js @@ -1,4 +1,4 @@ -class FillTool extends Tool { +class FillTool extends DrawingTool { constructor(name, options, switchFunction) { super(name, options); diff --git a/js/tools/MoveSelectionTool.js b/js/tools/MoveSelectionTool.js index 10ff903..3c81145 100644 --- a/js/tools/MoveSelectionTool.js +++ b/js/tools/MoveSelectionTool.js @@ -1,4 +1,4 @@ -class MoveSelectionTool extends Tool { +class MoveSelectionTool extends DrawingTool { currSelection = undefined; selectionTool = undefined; endTool = undefined; @@ -25,6 +25,8 @@ class MoveSelectionTool extends Tool { } cutSelection() { + if (currFile.currentLayer.isLocked) + return; this.cutting = true; this.lastCopiedSelection = this.currSelection; this.endSelection(); @@ -35,6 +37,8 @@ class MoveSelectionTool extends Tool { } pasteSelection() { + if (currFile.currentLayer.isLocked) + return; if (this.lastCopiedSelection === undefined) return; // Finish the current selection and start a new one with the same data diff --git a/js/tools/ResizableTool.js b/js/tools/ResizableTool.js index e291251..b8d3335 100644 --- a/js/tools/ResizableTool.js +++ b/js/tools/ResizableTool.js @@ -1,4 +1,4 @@ -class ResizableTool extends Tool { +class ResizableTool extends DrawingTool { startResizePos = undefined; currSize = 1; prevSize = 1; From 8433b6018afe44b0e30c2560404bcd8ef52a6966 Mon Sep 17 00:00:00 2001 From: Nicola <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 12 Dec 2021 22:55:28 +0100 Subject: [PATCH 89/91] Fixed #39 --- js/tools/PanTool.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/js/tools/PanTool.js b/js/tools/PanTool.js index a35f68c..af54a5e 100644 --- a/js/tools/PanTool.js +++ b/js/tools/PanTool.js @@ -6,13 +6,17 @@ class PanTool extends Tool { Events.on('click', this.mainButton, switchFunction, this); } - onStart(mousePos) { + onStart(mousePos, target) { super.onStart(mousePos); + if (target.className != 'drawingCanvas') + return; currFile.canvasView.style.cursor = "url(\'/pixel-editor/pan-held.png\'), auto"; } - onDrag(mousePos) { + onDrag(mousePos, target) { super.onDrag(mousePos); + if (target.className != 'drawingCanvas') + return; // Setting first layer position currFile.layers[0].setCanvasOffset(currFile.layers[0].canvas.offsetLeft + (mousePos[0] - this.startMousePos[0]), currFile.layers[0].canvas.offsetTop + (mousePos[1] - this.startMousePos[1])); @@ -22,8 +26,10 @@ class PanTool extends Tool { } } - onEnd(mousePos) { + onEnd(mousePos, target) { super.onEnd(mousePos); + if (target.className != 'drawingCanvas') + return; currFile.canvasView.style.cursor = "url(\'/pixel-editor/pan.png\'), auto"; } From 8abe1f04bbb21b3d3788355947fe4e19f3b5a1aa Mon Sep 17 00:00:00 2001 From: Nicola <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 12 Dec 2021 23:08:13 +0100 Subject: [PATCH 90/91] Binded closeDialogue to esc In that way the user can exit a dialogue without using the button and the mouse --- js/Dialogue.js | 2 ++ js/Input.js | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/js/Dialogue.js b/js/Dialogue.js index 26fcc8d..7ace4b8 100644 --- a/js/Dialogue.js +++ b/js/Dialogue.js @@ -8,6 +8,8 @@ const Dialogue = (() => { const popUpContainer = document.getElementById("pop-up-container"); const cancelButtons = popUpContainer.getElementsByClassName('close-button'); + Events.onCustom("esc-pressed", closeDialogue); + // Add click handlers for all cancel buttons for (var i = 0; i < cancelButtons.length; i++) { cancelButtons[i].addEventListener('click', function () { diff --git a/js/Input.js b/js/Input.js index df7cbf1..55395b9 100644 --- a/js/Input.js +++ b/js/Input.js @@ -75,13 +75,12 @@ const Input = (() => { } //if no document has been created yet or there is a dialog box open ignore hotkeys - if (!EditorState.documentCreated() || Dialogue.isOpen()) return; + if (!EditorState.documentCreated()) return; if (e.key === "Escape") { - console.log("esc"); Events.emit("esc-pressed"); } - else { + else if (!Dialogue.isOpen()){ switch (keyboardEvent.keyCode) { //pencil tool - 1, b case 49: case 66: From a08f239b5c26d118ca411812582c8ad39c94e886 Mon Sep 17 00:00:00 2001 From: Nicola <47360416+unsettledgames@users.noreply.github.com> Date: Mon, 13 Dec 2021 15:24:03 +0100 Subject: [PATCH 91/91] Updated readme --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a75d3d7..b49a328 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Please do not submit pull requests with new features or core changes. Instead, p ## What to Contribute -Any changes that fix bugs or add features are welcome. +Any changes that fix bugs or add features are welcome. Check out the issues if you don't know where to start: if +you're new to the editor, we suggest you check out the Wiki first. The next version is mostly focused on adding missing essential features and porting to mobile. @@ -24,10 +25,6 @@ Suggestions / Planned features: - Make a palette grid instead of having a huge stack on the right when colours are too many - Possibly add collaborate function -- Code refactoring - - Find and fix inefficient sections (nested loops, useless / inefficient parts) - - Refactor the ColorPicker IIFE - - Mobile - Touch equivalent for mouse clicks - Hide or scale ui @@ -41,7 +38,7 @@ Suggestions / Planned features: - Move selection with arrows - Update borders by dragging the canvas' edges with the mouse when resizing canvas - Move the canvases so they're centered after resizing the canvas (maybe a .center() method in layer class) - - Scale selection + - Scale / rotate selection ## How to Contribute