feature #541: add crop transform tool

This commit is contained in:
Julian Descottes 2017-05-20 19:43:05 +02:00
parent 4b4cbe47c8
commit a9e22535d6
10 changed files with 123 additions and 30 deletions

View File

@ -25,7 +25,7 @@
.transformations-show-more-link { .transformations-show-more-link {
position: absolute; position: absolute;
color: #999; color: #999;
right: 8px; right: 10px;
font-weight: normal; font-weight: normal;
cursor: pointer; cursor: pointer;
transition: 0.2s linear; transition: 0.2s linear;

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

View File

@ -8,6 +8,7 @@
new pskl.tools.transform.Rotate(), new pskl.tools.transform.Rotate(),
new pskl.tools.transform.Clone(), new pskl.tools.transform.Clone(),
new pskl.tools.transform.Center(), new pskl.tools.transform.Center(),
new pskl.tools.transform.Crop(),
]; ];
this.toolIconBuilder = new pskl.tools.ToolIconBuilder(); this.toolIconBuilder = new pskl.tools.ToolIconBuilder();

View File

@ -12,11 +12,15 @@
/** /**
* Set the current piskel. Will reset the selected frame and layer unless specified * Set the current piskel. Will reset the selected frame and layer unless specified
* @param {Object} piskel * @param {Object} piskel
* @param {Boolean} preserveState if true, keep the selected frame and layer * @param {Object} options:
* preserveState {Boolean} if true, keep the selected frame and layer
* noSnapshot {Boolean} if true, do not save a snapshot in the piskel
* history for this call to setPiskel
*/ */
ns.PiskelController.prototype.setPiskel = function (piskel, preserveState) { ns.PiskelController.prototype.setPiskel = function (piskel, options) {
this.piskel = piskel; this.piskel = piskel;
if (!preserveState) { options = options || {};
if (!options.preserveState) {
this.currentLayerIndex = 0; this.currentLayerIndex = 0;
this.currentFrameIndex = 0; this.currentFrameIndex = 0;
} }

View File

@ -49,14 +49,25 @@
return this.piskelController; return this.piskelController;
}; };
ns.PublicPiskelController.prototype.setPiskel = function (piskel, preserveState) { /**
this.piskelController.setPiskel(piskel, preserveState); * Set the current piskel. Will reset the selected frame and layer unless specified
* @param {Object} piskel
* @param {Object} options:
* preserveState {Boolean} if true, keep the selected frame and layer
* noSnapshot {Boolean} if true, do not save a snapshot in the piskel
* history for this call to setPiskel
*/
ns.PublicPiskelController.prototype.setPiskel = function (piskel, options) {
this.piskelController.setPiskel(piskel, options);
$.publish(Events.FRAME_SIZE_CHANGED); $.publish(Events.FRAME_SIZE_CHANGED);
$.publish(Events.PISKEL_RESET); $.publish(Events.PISKEL_RESET);
if (!options || !options.noSnapshot) {
$.publish(Events.PISKEL_SAVE_STATE, { $.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.SNAPSHOT type : pskl.service.HistoryService.SNAPSHOT
}); });
}
}; };
ns.PublicPiskelController.prototype.resetWrap_ = function (methodName) { ns.PublicPiskelController.prototype.resetWrap_ = function (methodName) {

View File

@ -69,7 +69,9 @@
resizeContent: this.resizeContentCheckbox.checked resizeContent: this.resizeContentCheckbox.checked
}); });
pskl.app.piskelController.setPiskel(piskel, true); pskl.app.piskelController.setPiskel(piskel, {
preserveState: true
});
$.publish(Events.CLOSE_SETTINGS_DRAWER); $.publish(Events.CLOSE_SETTINGS_DRAWER);
}; };

View File

@ -0,0 +1,55 @@
(function () {
var ns = $.namespace('pskl.tools.transform');
ns.Crop = function () {
this.toolId = 'tool-crop';
this.helpText = 'Crop the sprite';
this.tooltipDescriptors = [
{
description : 'Crop to fit the content or the selection. ' +
'Applies to all frames and layers!'
}
];
};
pskl.utils.inherit(ns.Crop, ns.AbstractTransformTool);
ns.Crop.prototype.applyToolOnFrame_ = function (frame, altKey) {
var currentPiskel = pskl.app.piskelController.getPiskel();
var frames = currentPiskel.getLayers().map(function (l) {
return l.getFrames();
}).reduce(function (p, n) {
return p.concat(n);
});
var boundaries = pskl.tools.transform.TransformUtils.getBoundaries(frames);
if (boundaries.minx >= boundaries.maxx) {
return;
}
var width = 1 + boundaries.maxx - boundaries.minx;
var height = 1 + boundaries.maxy - boundaries.miny;
if (width === currentPiskel.getWidth() && height === currentPiskel.getHeight()) {
// Do not perform an unnecessary resize if it's a noop.
return;
}
frames.forEach(function (frame) {
pskl.tools.transform.TransformUtils.moveFramePixels(frame, -boundaries.minx, -boundaries.miny);
});
var piskel = pskl.utils.ResizeUtils.resizePiskel(currentPiskel, {
width : 1 + boundaries.maxx - boundaries.minx,
height : 1 + boundaries.maxy - boundaries.miny,
origin: 'TOP-LEFT',
resizeContent: false
});
pskl.app.piskelController.setPiskel(piskel, {
preserveState: true,
noSnapshot: true
});
};
})();

View File

@ -64,13 +64,15 @@
return frame; return frame;
}, },
center : function(frame) { getBoundaries : function(frames) {
// Figure out the boundary var minx = frames[0].width;
var minx = frame.width; var miny = frames[0].height;
var miny = frame.height;
var maxx = 0; var maxx = 0;
var maxy = 0; var maxy = 0;
var transparentColorInt = pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR); var transparentColorInt = pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR);
frames.forEach(function (frame) {
frame.forEachPixel(function (color, x, y) { frame.forEachPixel(function (color, x, y) {
if (color !== transparentColorInt) { if (color !== transparentColorInt) {
minx = Math.min(minx, x); minx = Math.min(minx, x);
@ -79,17 +81,17 @@
maxy = Math.max(maxy, y); maxy = Math.max(maxy, y);
} }
}); });
});
// Calculate how much to move the pixels return {
var bw = (maxx - minx + 1) / 2; minx: minx,
var bh = (maxy - miny + 1) / 2; maxx: maxx,
var fw = frame.width / 2; miny: miny,
var fh = frame.height / 2; maxy: maxy,
};
},
var dx = Math.floor(fw - bw - minx); moveFramePixels : function (frame, dx, dy) {
var dy = Math.floor(fh - bh - miny);
// Actually move the pixels
var clone = frame.clone(); var clone = frame.clone();
frame.forEachPixel(function(color, x, y) { frame.forEachPixel(function(color, x, y) {
var _x = x; var _x = x;
@ -104,7 +106,24 @@
frame.setPixel(_x, _y, Constants.TRANSPARENT_COLOR); frame.setPixel(_x, _y, Constants.TRANSPARENT_COLOR);
} }
}); });
},
center : function(frame) {
// Figure out the boundary
var boundaries = ns.TransformUtils.getBoundaries([frame]);
// Calculate how much to move the pixels
var bw = (boundaries.maxx - boundaries.minx + 1) / 2;
var bh = (boundaries.maxy - boundaries.miny + 1) / 2;
var fw = frame.width / 2;
var fh = frame.height / 2;
var dx = Math.floor(fw - bw - boundaries.minx);
var dy = Math.floor(fh - bh - boundaries.miny);
// Actually move the pixels
ns.TransformUtils.moveFramePixels(frame, dx, dy);
return frame; return frame;
} }
}; };

View File

@ -226,6 +226,7 @@
"js/tools/transform/AbstractTransformTool.js", "js/tools/transform/AbstractTransformTool.js",
"js/tools/transform/Center.js", "js/tools/transform/Center.js",
"js/tools/transform/Clone.js", "js/tools/transform/Clone.js",
"js/tools/transform/Crop.js",
"js/tools/transform/Flip.js", "js/tools/transform/Flip.js",
"js/tools/transform/Rotate.js", "js/tools/transform/Rotate.js",
"js/tools/transform/TransformUtils.js", "js/tools/transform/TransformUtils.js",