This commit is contained in:
Jeff Wofford 2021-07-31 18:45:02 -07:00 committed by GitHub
commit 310a9a87b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 128 additions and 5 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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 : {

View File

@ -0,0 +1,44 @@
/**
* @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);
};
})();

View File

@ -154,6 +154,79 @@
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(function(pixel) {
return atLeastOneNeighborHasNonTargetColor(pixel);
});
var paintedPixels = [];
for (var i = 0; i < pixels.length; i++) {
var pixel = pixels[i];
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 +240,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];

View File

@ -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",