From b8d1f11f93b7d506305ce35b2520968375b4d67f Mon Sep 17 00:00:00 2001 From: NSSure <19178714+NSSure@users.noreply.github.com> Date: Sat, 22 Oct 2022 05:46:48 -0400 Subject: [PATCH] Added ability to select import position --- css/_import-image.scss | 9 ++++- js/ColorModule.js | 67 ++++++++++++++++++++++++++++++---- js/FileManager.js | 47 ++++++++++++++++++++++-- js/Util.js | 69 +++++++++++++++++++++++++++++++++++ views/popups/import-image.hbs | 28 +++++++++++++- 5 files changed, 204 insertions(+), 16 deletions(-) diff --git a/css/_import-image.scss b/css/_import-image.scss index 1e88c36..e34ed29 100644 --- a/css/_import-image.scss +++ b/css/_import-image.scss @@ -1,12 +1,17 @@ #import-image { + ul { + list-style-type: none; + margin: 15px 0; + padding: 0; + } + .import-image-file { button { margin: 0; } } - .import-image-checkbox { - height: 50px; + .import-image-location-pivot { display: flex; align-items: center; } diff --git a/js/ColorModule.js b/js/ColorModule.js index 9b90237..0fac69e 100644 --- a/js/ColorModule.js +++ b/js/ColorModule.js @@ -197,6 +197,7 @@ const ColorModule = (() => { //add # at beginning if not present if (newColor.charAt(0) != '#') newColor = '#' + newColor; + currentPalette.push(newColor); //create list item const listItem = document.createElement('li'); @@ -388,18 +389,69 @@ const ColorModule = (() => { * */ function createPaletteFromLayers() { + //create array out of colors object + let colorPaletteArray = getLayerColors(); + + //create palette from colors array + createColorPalette(colorPaletteArray); + } + + /** + * Scan the layers for any colors that are not currently in the palette. If any colors + * are found they should be added as new colors for the palette. + */ + function updatePaletteFromLayers() { + let layersPaletteArray = getLayerColors(); + + for (let i = 0; i < layersPaletteArray.length; i++) { + if (currentPalette.indexOf(layersPaletteArray[i]) !== -1) { + continue; + } + + addColor(layersPaletteArray[i]); + } + + return; + + // Compare the current layer colors to the current palette and add any layer colors that aren't in the palette. + let mergedPalette = [...currentPalette]; + + for (let i = 0; i < layersPaletteArray.length; i++) { + let isNewPaletteColor = true; + + for (let j = 0; j < currentPalette.length; j++) { + // If the layer color matches an existing palette color skip it so it isn't added again. + if (layersPaletteArray[i] === mergedPalette[j]) { + isNewPaletteColor = false; + break; + } + } + + if (isNewPaletteColor) { + mergedPalette.push(layersPaletteArray[i]); + } + } + + // Recreate the palette using the merged colors array. + createColorPalette(mergedPalette); + } + + /** + * Iterates each layer and grab each unique color. + * @returns Array of colors used within the current layers. + */ + function getLayerColors() { let colors = {}; let nColors = 0; //create array out of colors object let colorPaletteArray = []; - for (let i=0; i { colorPaletteArray.push('#' + new Color("rgb", imageData[j], imageData[j + 1], imageData[j + 2]).hex); colors[color] = new Color("rgb", imageData[j], imageData[j + 1], imageData[j + 2]).rgb; nColors++; + //don't allow more than 256 colors to be added if (nColors >= Settings.getCurrSettings().maxColorsOnImportedImage) { alert('The image loaded seems to have more than '+Settings.getCurrSettings().maxColorsOnImportedImage+' colors.'); @@ -418,10 +471,7 @@ const ColorModule = (() => { } } - //create palette from colors array - createColorPalette(colorPaletteArray); - - console.log("Done 2"); + return colorPaletteArray; } function updateCurrentColor(color, refLayer) { @@ -446,6 +496,7 @@ const ColorModule = (() => { resetPalette, createColorPalette, createPaletteFromLayers, + updatePaletteFromLayers, updateCurrentColor, } })(); \ No newline at end of file diff --git a/js/FileManager.js b/js/FileManager.js index 905c6d9..84cf9d6 100644 --- a/js/FileManager.js +++ b/js/FileManager.js @@ -272,6 +272,10 @@ const FileManager = (() => { browsePaletteHolder.value = null; } + currentImportPivotElement = undefined; + currentImportPivotPosition = 'middle'; + isImportWindowInitialized = false; + /** * Displays the import image window to allow for configurations * to be made be the image is imported. @@ -279,11 +283,25 @@ const FileManager = (() => { function openImportImageWindow() { // Reset window values. importImageHolder.value = null; + document.getElementById('import-image-match-size').checked = false; + document.getElementById('import-image-update-palette').checked = false; document.getElementById('import-image-name').innerText = ""; - Events.on("click", "select-image", () => document.getElementById('import-image-browse-holder')?.click()); - Events.on("click", "import-image-confirm", importImage); + // Workaround to prevent events from firing twice for the import window. + if (!this.isImportWindowInitialized) { + // Getting the pivot buttons and setting the default pivot selection. + let pivotButtons = document.getElementsByClassName("pivot-button"); + this.currentImportPivotElement = document.querySelector('.import-image-location-pivot .rc-selected-pivot'); + + // Add event handlers for each pivot. + for (let i=0; i < pivotButtons.length; i++) { + Events.on("click", pivotButtons[i], onImportPivotChanged.bind(this)); + } + + Events.on("click", "select-image", () => document.getElementById('import-image-browse-holder')?.click()); + Events.on("click", "import-image-confirm", importImage); + } Dialogue.showDialogue('import-image', false); } @@ -301,17 +319,25 @@ const FileManager = (() => { var fileReader = new FileReader(); // Once the image has been loaded draw the image to the current layer at the top right. - fileReader.onload = function(e) { + fileReader.onload = (e) => { var img = new Image(); + img.onload = () => { let shouldResizeCanvas = document.getElementById('import-image-match-size').checked; + let shouldImportColors = document.getElementById('import-image-update-palette').checked; // Resize the canvas to the image size if the flag was set to true. if (shouldResizeCanvas) { currFile.resizeCanvas(null, { x: img.width, y: img.height }, null, false); } - currFile.currentLayer.context.drawImage(img, 0, 0) + // Calculate pivot offset and draw the imported image. Ensure the pivot position accounts for the imported images dimensions. + let offset = Util.getPivotPosition(this.currentImportPivotPosition, currFile.canvasSize[0], currFile.canvasSize[1], img.width, img.height); + currFile.currentLayer.context.drawImage(img, offset.x, offset.y); + + if (shouldImportColors) { + ColorModule.updatePaletteFromLayers(); + } Dialogue.closeDialogue(); }; @@ -340,6 +366,19 @@ const FileManager = (() => { } } + /** + * Called when the selected pivot for the import image is changed. + * @param {*} event The event for the selected pivot. + */ + function onImportPivotChanged(event) { + this.currentImportPivotPosition = event.target.getAttribute("value"); + + // Setting the selected class + this.currentImportPivotElement.classList.remove("rc-selected-pivot"); + this.currentImportPivotElement = event.target; + this.currentImportPivotElement.classList.add("rc-selected-pivot"); + } + return { saveProject, exportProject, diff --git a/js/Util.js b/js/Util.js index 7f0b2a0..9056d99 100644 --- a/js/Util.js +++ b/js/Util.js @@ -134,4 +134,73 @@ class Util { static getFileExtension(fileName) { return (fileName.substring(fileName.lastIndexOf('.')+1, fileName.length) || fileName).toLowerCase(); } + + static getCanvasBorders() { + + } + + /** + * Determines the x and y offset for drawing images at a specific point 'topleft', 'middle', etc. + * + * @param {*} pivot A string representing the position of the pivot 'topleft', 'middle', etc. + * @param {*} width Width of the bounds often represents the canvas width. + * @param {*} height Height of the bounds often represents the canvas height. + * @param {*} imageWidth Substracts the offset from calculated x position of the pivot. Defaults to 0. + * @param {*} imageHeight Subtracts the offset from the calculated y position of the pivot. Defaults to 0. + * + * @returns Object containing the x and y offset for the pivot. + */ + static getPivotPosition(pivot, width, height, imageWidth = 0, imageHeight = 0) { + let position = { + x: 0, + y: 0 + }; + + let centerX = width / 2; + let centerY = height / 2; + + switch (pivot) + { + case 'topleft': + position.x = 0; + position.y = 0; + break; + case 'top': + position.x = centerX - (imageWidth / 2); + position.y = 0; + break; + case 'topright': + position.x = width - imageWidth; + position.y = 0; + break; + case 'left': + position.x = 0; + position.y = centerY - (imageHeight / 2); + break; + case 'middle': + position.x = centerX - (imageWidth / 2); + position.y = centerY - (imageHeight / 2); + break; + case 'right': + position.x = width - imageWidth; + position.y = centerY - (imageHeight / 2); + break; + case 'bottomleft': + position.x = 0; + position.y = height - imageHeight; + break; + case 'bottom': + position.x = centerX - (imageWidth / 2); + position.y = height - imageHeight; + break; + case 'bottomright': + position.x = width - imageWidth + position.y = height - imageHeight; + break; + default: + break; + } + + return position; + } } \ No newline at end of file diff --git a/views/popups/import-image.hbs b/views/popups/import-image.hbs index c848956..c85cba2 100644 --- a/views/popups/import-image.hbs +++ b/views/popups/import-image.hbs @@ -10,8 +10,32 @@ -
- Match canvas to image size + + +

Canvas Location

+ +

If matching to image size canvas location is ignored.

+ + +
+ + + + + + + + + + +