mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Add outliner tool.
This commit is contained in:
parent
cb41a72b5b
commit
0f5501bc3b
BIN
misc/proto-ui-1/img/outliner-icon-dark.png
Normal file
BIN
misc/proto-ui-1/img/outliner-icon-dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
BIN
misc/proto-ui-1/img/outliner-icon.png
Normal file
BIN
misc/proto-ui-1/img/outliner-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
@ -46,6 +46,7 @@ body {
|
||||
.tool.bucket { background-image: url(img/paintbucket-icon.png); }
|
||||
.tool.pen { background-image: url(img/pen-icon.png); }
|
||||
.tool.eyedropper { background-image: url(img/eyedropper-icon.png);}
|
||||
.tool.outliner { background-image: url(img/outliner-icon.png);} /* TODO!!! replace */
|
||||
|
||||
.tool:hover {
|
||||
cursor: pointer;
|
||||
|
@ -202,6 +202,10 @@
|
||||
background-image: url(../img/icons/tools/tool-paint-bucket.png);
|
||||
}
|
||||
|
||||
.cheatsheet-icon-tool-outliner {
|
||||
background-image: url(../img/icons/tools/tool-outliner.png);
|
||||
}
|
||||
|
||||
.cheatsheet-icon-tool-pen {
|
||||
background-image: url(../img/icons/tools/tool-pen.png);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
*/
|
||||
|
||||
.tool-paint-bucket .drawing-canvas-container:hover,
|
||||
.tool-outliner .drawing-canvas-container:hover,
|
||||
.tool-colorswap .drawing-canvas-container:hover {
|
||||
cursor: url(../img/cursors/paint-bucket.png) 14 14, pointer;
|
||||
}
|
||||
|
@ -18,7 +18,8 @@
|
||||
new pskl.tools.drawing.selection.LassoSelect(),
|
||||
new pskl.tools.drawing.Lighten(),
|
||||
new pskl.tools.drawing.DitheringTool(),
|
||||
new pskl.tools.drawing.ColorPicker()
|
||||
new pskl.tools.drawing.ColorPicker(),
|
||||
new pskl.tools.drawing.Outliner()
|
||||
];
|
||||
|
||||
this.toolIconBuilder = new pskl.tools.ToolIconBuilder();
|
||||
|
@ -31,7 +31,8 @@
|
||||
LASSO_SELECT : createShortcut('tool-lasso-select', 'Lasso selection', 'H'),
|
||||
LIGHTEN : createShortcut('tool-lighten', 'Lighten tool', 'U'),
|
||||
DITHERING : createShortcut('tool-dithering', 'Dithering tool', 'T'),
|
||||
COLORPICKER : createShortcut('tool-colorpicker', 'Color picker', 'O')
|
||||
COLORPICKER : createShortcut('tool-colorpicker', 'Color picker', 'O'),
|
||||
OUTLINER : createShortcut('tool-outliner', 'Outliner', 'Q')
|
||||
},
|
||||
|
||||
SELECTION : {
|
||||
|
39
src/js/tools/drawing/Outliner.js
Normal file
39
src/js/tools/drawing/Outliner.js
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @provide pskl.tools.drawing.Outliner
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace('pskl.tools.drawing');
|
||||
|
||||
ns.Outliner = function() {
|
||||
this.toolId = 'tool-outliner';
|
||||
this.helpText = 'Outliner tool';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.OUTLINER;
|
||||
this.tooltipDescriptors = [
|
||||
{key : 'ctrl', description : 'Fill corners'}
|
||||
];
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Outliner, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Outliner.prototype.applyToolAt = function(col, row, frame, overlay, event) {
|
||||
var fillCorners = pskl.utils.UserAgent.isMac ? event.metaKey : event.ctrlKey;
|
||||
var color = this.getToolColor();
|
||||
pskl.PixelUtils.outlineSimilarConnectedPixelsFromFrame(frame, col, row, color, fillCorners);
|
||||
|
||||
this.raiseSaveStateEvent({
|
||||
col : col,
|
||||
row : row,
|
||||
color : color,
|
||||
fillCorners: fillCorners
|
||||
});
|
||||
};
|
||||
|
||||
ns.Outliner.prototype.replay = function (frame, replayData) {
|
||||
pskl.PixelUtils.outlineSimilarConnectedPixelsFromFrame(frame, replayData.col, replayData.row, replayData.color, replayData.fillCorners);
|
||||
};
|
||||
})();
|
@ -154,6 +154,76 @@
|
||||
return paintedPixels;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply the outliner tool in a frame at the (col, row) initial position
|
||||
* with the replacement color.
|
||||
*
|
||||
* @param frame pskl.model.Frame The frame target in which we want to paintbucket
|
||||
* @param col number Column coordinate in the frame
|
||||
* @param row number Row coordinate in the frame
|
||||
* @param replacementColor string Hexadecimal color used to fill the area
|
||||
* @param fillCorners boolean If true, also paint corner pixels
|
||||
*
|
||||
* @return an array of the pixel coordinates paint with the replacement color
|
||||
*/
|
||||
outlineSimilarConnectedPixelsFromFrame: function(frame, col, row, replacementColor, fillCorners) {
|
||||
/**
|
||||
* Acts like floodfill, except that a given pixel is only painted if it has at
|
||||
* least one non-filled-color neighbor.
|
||||
*
|
||||
*/
|
||||
if (typeof replacementColor == 'string') {
|
||||
replacementColor = pskl.utils.colorToInt(replacementColor);
|
||||
}
|
||||
|
||||
if (fillCorners===undefined) {
|
||||
fillCorners = false;
|
||||
}
|
||||
|
||||
var targetColor;
|
||||
try {
|
||||
targetColor = frame.getPixel(col, row);
|
||||
} catch (e) {
|
||||
// Frame out of bound exception.
|
||||
}
|
||||
|
||||
if (targetColor === null || targetColor == replacementColor) {
|
||||
return;
|
||||
}
|
||||
|
||||
var atLeastOneNeighborHasNonTargetColor = function(pixel) {
|
||||
for (var y = -1; y <= 1; y++ ) {
|
||||
for (var x = -1; x <= 1; x++ ) {
|
||||
if (x != 0 || y != 0) {
|
||||
if (fillCorners || (x == 0 || y == 0)) {
|
||||
try {
|
||||
var pixelColor = frame.getPixel(pixel.col + x, pixel.row + y);
|
||||
if ( pixelColor !== null && pixelColor !== targetColor) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
// Frame out of bound exception.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row);
|
||||
pixels = pixels.filter(pixel => atLeastOneNeighborHasNonTargetColor(pixel));
|
||||
|
||||
var paintedPixels = [];
|
||||
|
||||
for (var pixel of pixels) {
|
||||
frame.setPixel(pixel.col, pixel.row, replacementColor);
|
||||
paintedPixels.push(pixel);
|
||||
}
|
||||
|
||||
return paintedPixels;
|
||||
},
|
||||
|
||||
/**
|
||||
* Starting from a provided origin, visit connected pixels using a visitor function.
|
||||
* After visiting a pixel, select the 4 connected pixels (up, right, down, left).
|
||||
@ -167,9 +237,6 @@
|
||||
* @return {Array} the array of visited pixels {col, row}
|
||||
*/
|
||||
visitConnectedPixels : function (pixel, frame, pixelVisitor) {
|
||||
var col = pixel.col;
|
||||
var row = pixel.row;
|
||||
|
||||
var queue = [];
|
||||
var visitedPixels = [];
|
||||
var dy = [-1, 0, 1, 0];
|
||||
|
@ -225,6 +225,7 @@
|
||||
"js/tools/drawing/Eraser.js",
|
||||
"js/tools/drawing/Stroke.js",
|
||||
"js/tools/drawing/PaintBucket.js",
|
||||
"js/tools/drawing/Outliner.js",
|
||||
"js/tools/drawing/Rectangle.js",
|
||||
"js/tools/drawing/Circle.js",
|
||||
"js/tools/drawing/Move.js",
|
||||
|
Loading…
Reference in New Issue
Block a user