diff --git a/Gruntfile.js b/Gruntfile.js index 6872f830..ffa321b8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -36,7 +36,7 @@ module.exports = function(grunt) { }, 'travis' : { suite : './test/casperjs/TravisTestSuite.js', - delay : 5000 + delay : 10000 } }; diff --git a/src/css/icons.css b/src/css/icons.css index dc1ddc1e..809ce976 100644 --- a/src/css/icons.css +++ b/src/css/icons.css @@ -7,4 +7,8 @@ .action-icon.edit-icon { background-image: url('../img/tools/pen.png'); +} + +.action-icon.merge-icon { + background-image: url('../img/merge-icon.png'); } \ No newline at end of file diff --git a/src/css/toolbox-layers-list.css b/src/css/toolbox-layers-list.css index 052a5013..1b43b338 100644 --- a/src/css/toolbox-layers-list.css +++ b/src/css/toolbox-layers-list.css @@ -46,22 +46,34 @@ cursor : pointer; } -.layer-item .edit-icon { +.layer-item .edit-icon, .layer-item .merge-icon { float: right; - width: 30px; - background-size: 12px; opacity: 0; transition : opacity 0.2s; } -.layer-item:hover .edit-icon { +.layer-item:hover .edit-icon, .layer-item:hover .merge-icon { opacity : 0.6; } -.layer-item:hover .edit-icon:hover { +.layer-item:hover .edit-icon:hover, .layer-item:hover .merge-icon:hover { opacity : 1; } +.layer-item .edit-icon { + width: 25px; + background-size: 12px; +} + +.layer-item .merge-icon { + width: 18px; + background-size: 16px; +} + +.layer-item:last-child .merge-icon { + display : none; +} + .layer-item:hover { background : #222; } diff --git a/src/img/merge-icon.png b/src/img/merge-icon.png new file mode 100644 index 00000000..3210c100 Binary files /dev/null and b/src/img/merge-icon.png differ diff --git a/src/js/controller/LayersListController.js b/src/js/controller/LayersListController.js index 48b6e3e7..b33c36a3 100644 --- a/src/js/controller/LayersListController.js +++ b/src/js/controller/LayersListController.js @@ -67,6 +67,9 @@ } else if (el.classList.contains('edit-icon')) { index = el.parentNode.dataset.layerIndex; this.renameLayerAt_(index); + } else if (el.classList.contains('merge-icon')) { + index = el.parentNode.dataset.layerIndex; + this.mergeDownLayerAt_(index); } }; @@ -79,6 +82,11 @@ } }; + ns.LayersListController.prototype.mergeDownLayerAt_ = function (index) { + this.piskelController.mergeDownLayerAt(index); + this.renderLayerList_(); + }; + ns.LayersListController.prototype.onButtonClick_ = function (button) { var action = button.getAttribute('data-action'); if (action == 'up') { diff --git a/src/js/controller/piskel/PiskelController.js b/src/js/controller/piskel/PiskelController.js index ed03a303..4226807b 100644 --- a/src/js/controller/piskel/PiskelController.js +++ b/src/js/controller/piskel/PiskelController.js @@ -205,6 +205,18 @@ } }; + ns.PiskelController.prototype.mergeDownLayerAt = function (index) { + var layer = this.getLayerByIndex(index); + var downLayer = this.getLayerByIndex(index-1); + if (layer && downLayer) { + var mergedLayer = pskl.utils.LayerUtils.mergeLayers(layer, downLayer); + this.removeLayerAt(index); + this.piskel.addLayerAt(mergedLayer, index); + this.removeLayerAt(index-1); + this.selectLayer(mergedLayer); + } + }; + ns.PiskelController.prototype.generateLayerName_ = function () { var name = "Layer " + this.layerIdCounter; while (this.hasLayerForName_(name)) { diff --git a/src/js/controller/piskel/PublicPiskelController.js b/src/js/controller/piskel/PublicPiskelController.js index 39264cef..e5da46bf 100644 --- a/src/js/controller/piskel/PublicPiskelController.js +++ b/src/js/controller/piskel/PublicPiskelController.js @@ -99,6 +99,12 @@ $.publish(Events.PISKEL_RESET); }; + ns.PublicPiskelController.prototype.mergeDownLayerAt = function (index) { + this.raiseSaveStateEvent_(this.piskelController.mergeDownLayerAt, [index]); + this.piskelController.mergeDownLayerAt(index); + $.publish(Events.PISKEL_RESET); + }; + ns.PublicPiskelController.prototype.moveLayerUp = function () { this.raiseSaveStateEvent_(this.piskelController.moveLayerUp, []); this.piskelController.moveLayerUp(); diff --git a/src/js/devtools/DrawingTestPlayer.js b/src/js/devtools/DrawingTestPlayer.js index 82dfbf3c..7f72ab80 100644 --- a/src/js/devtools/DrawingTestPlayer.js +++ b/src/js/devtools/DrawingTestPlayer.js @@ -101,6 +101,10 @@ var screenCoordinates = pskl.app.drawingController.getScreenCoordinates(recordEvent.coords.x, recordEvent.coords.y); event.clientX = screenCoordinates.x; event.clientY = screenCoordinates.y; + if (pskl.utils.UserAgent.isMac && event.ctrlKey) { + event.metaKey = true; + } + if (event.type == 'mousedown') { pskl.app.drawingController.onMousedown_(event); } else if (event.type == 'mouseup') { diff --git a/src/js/model/Piskel.js b/src/js/model/Piskel.js index ab28ec14..a59593a3 100644 --- a/src/js/model/Piskel.js +++ b/src/js/model/Piskel.js @@ -73,6 +73,10 @@ this.layers.push(layer); }; + ns.Piskel.prototype.addLayerAt = function (layer, index) { + this.layers.splice(index, 0, layer); + }; + ns.Piskel.prototype.moveLayerUp = function (layer) { var index = this.layers.indexOf(layer); if (index > -1 && index < this.layers.length-1) { diff --git a/src/js/utils/LayerUtils.js b/src/js/utils/LayerUtils.js index 38a08e5a..d551e505 100644 --- a/src/js/utils/LayerUtils.js +++ b/src/js/utils/LayerUtils.js @@ -25,6 +25,18 @@ frames.push(frame); } return frames; + }, + + mergeLayers : function (layerA, layerB) { + var framesA = layerA.getFrames(); + var framesB = layerB.getFrames(); + var mergedFrames = []; + framesA.forEach(function (frame, index) { + var otherFrame = framesB[index]; + mergedFrames.push(pskl.utils.FrameUtils.merge([otherFrame, frame])); + }); + var mergedLayer = pskl.model.Layer.fromFrames(layerA.getName(), mergedFrames); + return mergedLayer; } }; diff --git a/src/templates/layers-list.html b/src/templates/layers-list.html index 7208e10d..35f599f7 100644 --- a/src/templates/layers-list.html +++ b/src/templates/layers-list.html @@ -13,7 +13,8 @@ diff --git a/test/drawing/DrawingTests.browser.js b/test/drawing/DrawingTests.browser.js index fa7a32d7..7db7ef2b 100644 --- a/test/drawing/DrawingTests.browser.js +++ b/test/drawing/DrawingTests.browser.js @@ -4,6 +4,7 @@ "color.picker.json", "frames.fun.json", "layers.fun.json", + "layers.merge.json", "lighten.darken.json", "move.json", "pen.secondary.color.json", diff --git a/test/drawing/DrawingTests.casper.js b/test/drawing/DrawingTests.casper.js index 68e8b83f..6dd57335 100644 --- a/test/drawing/DrawingTests.casper.js +++ b/test/drawing/DrawingTests.casper.js @@ -3,6 +3,7 @@ "color.picker.json", "frames.fun.json", "layers.fun.json", + "layers.merge.json", "move.json", "pen.secondary.color.json", "squares.circles.json", diff --git a/test/drawing/tests/layers.merge.json b/test/drawing/tests/layers.merge.json new file mode 100644 index 00000000..5262e828 --- /dev/null +++ b/test/drawing/tests/layers.merge.json @@ -0,0 +1 @@ +{"events":[{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":0},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":0},"type":"mouse-event"},{"type":"instrumented-event","methodName":"createLayer","args":[]},{"type":"color-event","color":"#942d2d","isPrimary":true},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"type":"instrumented-event","methodName":"createLayer","args":[]},{"type":"color-event","color":"#2d9430","isPrimary":true},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":3},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":3},"type":"mouse-event"},{"type":"instrumented-event","methodName":"moveLayerDown","args":[]},{"type":"instrumented-event","methodName":"mergeDownLayerAt","args":["2"]},{"type":"instrumented-event","methodName":"mergeDownLayerAt","args":["1"]},{"type":"tool-event","toolId":"tool-paint-bucket"},{"type":"color-event","color":"#2d5994","isPrimary":true},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":4},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":4},"type":"mouse-event"},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":0},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":0},"type":"mouse-event"}],"initialState":{"size":{"width":5,"height":5},"primaryColor":"#000000","secondaryColor":"rgba(0, 0, 0, 0)","selectedTool":"tool-pen"},"png":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAN0lEQVQIW2NkYGD4D8RgoBs5BUwzggSn6OrCxBlm6qRjEUxnZmAEavmffmUmQiVMECxiPQcuAQAoxRAISNM8EgAAAABJRU5ErkJggg=="} \ No newline at end of file