mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
feature #541: add crop transform tool
This commit is contained in:
parent
4b4cbe47c8
commit
a9e22535d6
@ -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;
|
||||||
|
BIN
src/img/icons/transform/tool-crop.png
Normal file
BIN
src/img/icons/transform/tool-crop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 393 B |
BIN
src/img/icons/transform/tool-crop@2x.png
Normal file
BIN
src/img/icons/transform/tool-crop@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 693 B |
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
$.publish(Events.PISKEL_SAVE_STATE, {
|
|
||||||
type : pskl.service.HistoryService.SNAPSHOT
|
if (!options || !options.noSnapshot) {
|
||||||
});
|
$.publish(Events.PISKEL_SAVE_STATE, {
|
||||||
|
type : pskl.service.HistoryService.SNAPSHOT
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PublicPiskelController.prototype.resetWrap_ = function (methodName) {
|
ns.PublicPiskelController.prototype.resetWrap_ = function (methodName) {
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
55
src/js/tools/transform/Crop.js
Normal file
55
src/js/tools/transform/Crop.js
Normal 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
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
@ -64,32 +64,34 @@
|
|||||||
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);
|
||||||
frame.forEachPixel(function (color, x, y) {
|
|
||||||
if (color !== transparentColorInt) {
|
frames.forEach(function (frame) {
|
||||||
minx = Math.min(minx, x);
|
frame.forEachPixel(function (color, x, y) {
|
||||||
maxx = Math.max(maxx, x);
|
if (color !== transparentColorInt) {
|
||||||
miny = Math.min(miny, y);
|
minx = Math.min(minx, x);
|
||||||
maxy = Math.max(maxy, y);
|
maxx = Math.max(maxx, x);
|
||||||
}
|
miny = Math.min(miny, 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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user