Skip to content

Commit

Permalink
Feature #541 crop based on the current selection
Browse files Browse the repository at this point in the history
  • Loading branch information
juliandescottes committed Jun 1, 2017
1 parent a9e2253 commit 799c9fb
Show file tree
Hide file tree
Showing 7 changed files with 554 additions and 13 deletions.
6 changes: 6 additions & 0 deletions src/js/devtools/DrawingTestRecorder.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@
recordEvent.type = 'instrumented-event';
recordEvent.methodName = methodName;
recordEvent.args = Array.prototype.slice.call(args, 0);

if (methodName === 'setPiskel' && args[1].noSnapshot) {
// Skip recording calls to setPiskel that don't trigger a save.
return;
}

this.events.push(recordEvent);
}
};
Expand Down
94 changes: 83 additions & 11 deletions src/js/tools/transform/Crop.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,47 @@
];
};

pskl.utils.inherit(ns.Crop, ns.AbstractTransformTool);
// This transform tool is the only one that adapts to the current selection and can't
// rely on the default AbstractTransformTool behavior.
pskl.utils.inherit(ns.Crop, pskl.tools.Tool);

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);
});
ns.Crop.prototype.applyTransformation = function (evt) {
var frames = this.getFrames_();

var boundaries;
if (pskl.app.selectionManager.currentSelection) {
// If we have a selection, we will compute the boundaries of the selection instead
// of looping on the frames.
boundaries = this.getBoundariesForSelection_();
} else {
boundaries = pskl.tools.transform.TransformUtils.getBoundaries(frames);
}

var boundaries = pskl.tools.transform.TransformUtils.getBoundaries(frames);
var applied = this.applyTool_(frames, boundaries);
if (applied) {
this.raiseSaveStateEvent({
boundaries : boundaries
});
}
};

ns.Crop.prototype.replay = function (frame, replayData) {
var frames = this.getFrames_();
this.applyTool_(frames, replayData.boundaries);
};

ns.Crop.prototype.applyTool_ = function (frames, boundaries) {
if (boundaries.minx >= boundaries.maxx) {
return;
return false;
}

var currentPiskel = pskl.app.piskelController.getPiskel();
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;
return false;
}

frames.forEach(function (frame) {
Expand All @@ -46,10 +66,62 @@
resizeContent: false
});

// Clear the current selection.
$.publish(Events.SELECTION_DISMISSED);

// Replace the current piskel with the resized version.
pskl.app.piskelController.setPiskel(piskel, {
preserveState: true,
// Saving is already handled by recording the transform tool action, no need for
// an expensive snapshot.
noSnapshot: true
});

return true;
};

/**
* Retrieve the list of frames for the current piskel in a single flat array.
*/
ns.Crop.prototype.getFrames_ = function () {
var currentPiskel = pskl.app.piskelController.getPiskel();

// Get all frames in a single array.
var frames = currentPiskel.getLayers().map(function (l) {
return l.getFrames();
}).reduce(function (p, n) {
return p.concat(n);
});

return frames;
};

/**
* Retrieve a boundaries object {minx, maxx, miny, maxy} for the current selection.
*/
ns.Crop.prototype.getBoundariesForSelection_ = function () {
var selectionManager = pskl.app.selectionManager;
var pixels = selectionManager.currentSelection.pixels;

// Fetch the first frame to perform out-of-bound checks.
var currentPiskel = pskl.app.piskelController.getPiskel();
var exampleFrame = currentPiskel.getLayerAt(0).getFrameAt(0);

// Anything different from Constants.TRANSPARENT_COLOR toInt().
var FAKE_COLOR = 1;
// Create a fake frame reimplementing the forEachPixel API.
var selectionFrame = {
forEachPixel : function (callback) {
for (var i = 0; i < pixels.length ; i++) {
var pixel = pixels[i];
// Selections might contain out of bound pixels, filter those out.
if (exampleFrame.containsPixel(pixel.col, pixel.row)) {
callback(FAKE_COLOR, pixel.col, pixel.row);
}
}
}
};

return pskl.tools.transform.TransformUtils.getBoundaries([selectionFrame]);
};
})();
4 changes: 2 additions & 2 deletions src/js/tools/transform/TransformUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@
},

getBoundaries : function(frames) {
var minx = frames[0].width;
var miny = frames[0].height;
var minx = +Infinity;
var miny = +Infinity;
var maxx = 0;
var maxy = 0;

Expand Down
2 changes: 2 additions & 0 deletions test/drawing/DrawingTests.browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"transform.center.json",
"transform.clone.once.json",
"transform.clone.twice.undo.once.json",
"transform.crop.json",
"transform.crop.selection.json",
"transform.rotate.once.alt.json",
"transform.rotate.twice.undo.once.json",
"transform.rotate.alt.twice.undo.once.json",
Expand Down
2 changes: 2 additions & 0 deletions test/drawing/DrawingTests.casper.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"transform.center.json",
"transform.clone.once.json",
"transform.clone.twice.undo.once.json",
"transform.crop.json",
"transform.crop.selection.json",
"transform.rotate.once.alt.json",
"transform.rotate.twice.undo.once.json",
"transform.rotate.alt.twice.undo.once.json",
Expand Down
185 changes: 185 additions & 0 deletions test/drawing/tests/transform.crop.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
{
"events": [
{
"event": {
"type": "mousedown",
"button": 0,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 1,
"y": 1
},
"type": "mouse-event"
},
{
"event": {
"type": "mouseup",
"button": 0,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 1,
"y": 1
},
"type": "mouse-event"
},
{
"event": {
"type": "mousedown",
"button": 0,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 1,
"y": 3
},
"type": "mouse-event"
},
{
"event": {
"type": "mouseup",
"button": 0,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 1,
"y": 3
},
"type": "mouse-event"
},
{
"event": {
"type": "mousedown",
"button": 0,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 2,
"y": 3
},
"type": "mouse-event"
},
{
"event": {
"type": "mouseup",
"button": 0,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 2,
"y": 3
},
"type": "mouse-event"
},
{
"event": {
"type": "mousedown",
"button": 0,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 3,
"y": 1
},
"type": "mouse-event"
},
{
"event": {
"type": "mouseup",
"button": 0,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 3,
"y": 1
},
"type": "mouse-event"
},
{
"type": "transformtool-event",
"toolId": "tool-crop",
"event": {
"shiftKey": false,
"altKey": false,
"ctrlKey": false
}
},
{
"event": {
"type": "mousedown",
"button": 2,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 2,
"y": 0
},
"type": "mouse-event"
},
{
"event": {
"type": "mouseup",
"button": 2,
"shiftKey": false,
"altKey": false,
"ctrlKey": false
},
"coords": {
"x": 2,
"y": 0
},
"type": "mouse-event"
},
{
"type": "transformtool-event",
"toolId": "tool-crop",
"event": {
"shiftKey": false,
"altKey": false,
"ctrlKey": false
}
},
{
"type": "keyboard-event",
"event": {
"which": 90,
"shiftKey": false,
"altKey": false,
"ctrlKey": true,
"target": {
"nodeName": "BODY"
}
}
}
],
"initialState": {
"size": {
"width": 4,
"height": 4
},
"primaryColor": "#000000",
"secondaryColor": "rgba(0, 0, 0, 0)",
"selectedTool": "tool-pen",
"penSize": 1
},
"png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAG0lEQVQYV2NkYGD4z8DAwMgAI0AMGAckA2YDACxpAgQTZnIjAAAAAElFTkSuQmCC"
}
Loading

0 comments on commit 799c9fb

Please sign in to comment.