diff --git a/src/js/service/FileDropperService.js b/src/js/service/FileDropperService.js index 9f7ab2d..84957da 100644 --- a/src/js/service/FileDropperService.js +++ b/src/js/service/FileDropperService.js @@ -64,15 +64,17 @@ }; ns.FileDropperService.prototype.onImageLoaded_ = function () { - var droppedFrame = pskl.utils.FrameUtils.createFromImage(this.importedImage_); var currentFrame = this.piskelController.getCurrentFrame(); + // Convert client coordinates to sprite coordinates + var spriteDropPosition = pskl.app.drawingController.getSpriteCoordinates( + this.dropPosition_.x, + this.dropPosition_.y + ); - var origin = this.adjustDropPosition_(this.dropPosition_, droppedFrame); - droppedFrame.forEachPixel(function (color, x, y) { - if (color != pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR)) { - currentFrame.setPixel(origin.x + x, origin.y + y, color); - } - }); + var x = spriteDropPosition.x; + var y = spriteDropPosition.y; + + pskl.utils.FrameUtils.addImageToFrame(currentFrame, this.importedImage_, x, y); $.publish(Events.PISKEL_RESET); $.publish(Events.PISKEL_SAVE_STATE, { @@ -80,28 +82,4 @@ }); }; - ns.FileDropperService.prototype.adjustDropPosition_ = function (position, droppedFrame) { - var framePosition = pskl.app.drawingController.getSpriteCoordinates(position.x, position.y); - - var xCoord = framePosition.x - Math.floor(droppedFrame.width / 2); - var yCoord = framePosition.y - Math.floor(droppedFrame.height / 2); - - xCoord = Math.max(0, xCoord); - yCoord = Math.max(0, yCoord); - - var currentFrame = this.piskelController.getCurrentFrame(); - if (droppedFrame.width <= currentFrame.width) { - xCoord = Math.min(xCoord, currentFrame.width - droppedFrame.width); - } - - if (droppedFrame.height <= currentFrame.height) { - yCoord = Math.min(yCoord, currentFrame.height - droppedFrame.height); - } - - return { - x : xCoord, - y : yCoord - }; - }; - })(); diff --git a/src/js/utils/FrameUtils.js b/src/js/utils/FrameUtils.js index 42ce52a..9ebc17c 100644 --- a/src/js/utils/FrameUtils.js +++ b/src/js/utils/FrameUtils.js @@ -123,6 +123,33 @@ } }, + /** + * Insert the provided image in the provided frame, at the x, y sprite coordinates. + * Coordinates will be adjusted so that the image fits in the frame, if possible. + */ + addImageToFrame: function (frame, image, x, y) { + var imageFrame = pskl.utils.FrameUtils.createFromImage(image); + x = x - Math.floor(imageFrame.width / 2); + y = y - Math.floor(imageFrame.height / 2); + + x = Math.max(0, x); + y = Math.max(0, y); + + if (imageFrame.width <= frame.width) { + x = Math.min(x, frame.width - imageFrame.width); + } + + if (imageFrame.height <= frame.height) { + y = Math.min(y, frame.height - imageFrame.height); + } + + imageFrame.forEachPixel(function (color, frameX, frameY) { + if (color != pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR)) { + frame.setPixel(x + frameX, y + frameY, color); + } + }); + }, + resize : function (frame, targetWidth, targetHeight, smoothing) { var image = pskl.utils.FrameUtils.toImage(frame); var resizedImage = pskl.utils.ImageResizer.resize(image, targetWidth, targetHeight, smoothing); diff --git a/test/js/utils/FrameUtilsTest_add_image.js b/test/js/utils/FrameUtilsTest_add_image.js new file mode 100644 index 0000000..75e3287 --- /dev/null +++ b/test/js/utils/FrameUtilsTest_add_image.js @@ -0,0 +1,144 @@ +describe("FrameUtils addImageToFrame tests", function() { + var black = '#000000'; + var red = '#ff0000'; + var transparent = Constants.TRANSPARENT_COLOR; + var B = black, R = red, T = transparent; + + // shortcuts + var toFrameGrid = test.testutils.toFrameGrid; + + /** + * The three helpers below enable using only "visual" grids, while + * most frame helpers use rotated grids. + */ + var frameEqualsGrid = function (frame, grid) { + test.testutils.frameEqualsGrid(frame, grid); + }; + + var createFrameFromGrid = function (grid) { + return pskl.model.Frame.fromPixelGrid(toFrameGrid(grid)); + }; + + var createImageFromGrid = function (grid) { + return pskl.utils.FrameUtils.toImage(createFrameFromGrid(grid)); + }; + + it("adds smaller image at drop position", function () { + // Transparent frame 2x2 + var frame = createFrameFromGrid([ + [T, T], + [T, T] + ]); + + // Single red pixel image + var image = createImageFromGrid([[R]]); + + pskl.utils.FrameUtils.addImageToFrame(frame, image, 0, 0); + + // Verify + frameEqualsGrid(frame, [ + [R, T], + [T, T] + ]); + + pskl.utils.FrameUtils.addImageToFrame(frame, image, 1, 1); + // Verify + frameEqualsGrid(frame, [ + [R, T], + [T, R] + ]); + }); + + it("adds line image at drop position", function () { + // Transparent frame 2x2 + var frame = createFrameFromGrid([ + [T, T], + [T, T] + ]); + + // Line of 2 red pixels + var image = createImageFromGrid([[R, R]]); + + pskl.utils.FrameUtils.addImageToFrame(frame, image, 0, 0); + + // Verify + frameEqualsGrid(frame, [ + [R, R], + [T, T] + ]); + + pskl.utils.FrameUtils.addImageToFrame(frame, image, 0, 1); + + // Verify + frameEqualsGrid(frame, [ + [R, R], + [R, R] + ]); + }); + + it("does not erase under transparent areas", function () { + // Black frame 2x2 + var frame = createFrameFromGrid([ + [B, B], + [B, B] + ]); + + // 2x2 image with 3 transparent pixels and a red pixel + var image = createImageFromGrid([ + [T, T], + [T, R] + ]); + + pskl.utils.FrameUtils.addImageToFrame(frame, image, 0, 0); + + // Verify + frameEqualsGrid(frame, [ + [B, B], + [B, R] + ]); + }); + + it("offsets drop position", function () { + // Transparent frame 2x2 + var frame = createFrameFromGrid([ + [T, T], + [T, T] + ]); + + // Line of 2 red pixels + var image = createImageFromGrid([ + [R, R] + ]); + + // Drop it on the right side, should be moved back to te left + pskl.utils.FrameUtils.addImageToFrame(frame, image, 1, 0); + + // Verify + frameEqualsGrid(frame, [ + [R, R], + [T, T] + ]); + }); + + it("offsets drop position take 2", function () { + // Transparent frame 2x2 + var frame = createFrameFromGrid([ + [T, T], + [T, T] + ]); + + // 2x2 image + var image = createImageFromGrid([ + [B, R], + [R, B] + ]); + + pskl.utils.FrameUtils.addImageToFrame(frame, image, 1, 1); + + // Verify + frameEqualsGrid(frame, [ + [B, R], + [R, B] + ]); + }); +}); \ No newline at end of file