diff --git a/src/css/tools.css b/src/css/tools.css index c2a7be7c..de0936ac 100644 --- a/src/css/tools.css +++ b/src/css/tools.css @@ -114,6 +114,12 @@ background-size: 30px; } +.tool-icon.tool-dithering { + background-image: url(../img/tools/dithering.png); + background-position: 8px 9px; + background-size: 30px; +} + /* * Tool cursors: */ @@ -128,7 +134,8 @@ } .tool-pen .drawing-canvas-container:hover, -.tool-lighten .drawing-canvas-container:hover { +.tool-lighten .drawing-canvas-container:hover, +.tool-dithering .drawing-canvas-container:hover { cursor: url(../img/icons/pen.png) 0 15, pointer; } diff --git a/src/img/tools/dithering.png b/src/img/tools/dithering.png new file mode 100644 index 00000000..6bd0f11b Binary files /dev/null and b/src/img/tools/dithering.png differ diff --git a/src/js/app.js b/src/js/app.js index b8dbd171..b0a2e6df 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -38,6 +38,9 @@ this.paletteService = new pskl.service.palette.PaletteService(); this.paletteService.addDynamicPalette(new pskl.service.palette.CurrentColorsPalette()); + this.selectedColorsService = new pskl.service.SelectedColorsService(); + this.selectedColorsService.init(); + this.paletteController = new pskl.controller.PaletteController(); this.paletteController.init(); diff --git a/src/js/controller/PaletteController.js b/src/js/controller/PaletteController.js index 30120ac6..f6e0559b 100644 --- a/src/js/controller/PaletteController.js +++ b/src/js/controller/PaletteController.js @@ -2,6 +2,7 @@ var ns = $.namespace('pskl.controller'); ns.PaletteController = function () { + // TODO(grosbouddha): Reuse default colors from SelectedColorsService. this.primaryColor = Constants.DEFAULT_PEN_COLOR; this.secondaryColor = Constants.TRANSPARENT_COLOR; }; diff --git a/src/js/controller/ToolController.js b/src/js/controller/ToolController.js index de29d9ce..00f134e9 100644 --- a/src/js/controller/ToolController.js +++ b/src/js/controller/ToolController.js @@ -19,6 +19,7 @@ toDescriptor('rectangleSelect', 'S', new pskl.tools.drawing.RectangleSelect()), toDescriptor('shapeSelect', 'Z', new pskl.tools.drawing.ShapeSelect()), toDescriptor('lighten', 'U', new pskl.tools.drawing.Lighten()), + toDescriptor('dithering', 'T', new pskl.tools.drawing.DitheringTool()), toDescriptor('colorPicker', 'O', new pskl.tools.drawing.ColorPicker()) ]; diff --git a/src/js/service/SelectedColorsService.js b/src/js/service/SelectedColorsService.js new file mode 100644 index 00000000..2e7d46c2 --- /dev/null +++ b/src/js/service/SelectedColorsService.js @@ -0,0 +1,28 @@ +(function () { + var ns = $.namespace('pskl.service'); + + ns.SelectedColorsService = function () { + this.primaryColor_ = Constants.DEFAULT_PEN_COLOR; + this.secondaryColor_ = Constants.TRANSPARENT_COLOR; + }; + + ns.SelectedColorsService.prototype.init = function () { + $.subscribe(Events.PRIMARY_COLOR_SELECTED, this.onPrimaryColorUpdate_.bind(this)); + $.subscribe(Events.SECONDARY_COLOR_SELECTED, this.onSecondaryColorUpdate_.bind(this)); + }; + + ns.SelectedColorsService.prototype.getColors = function () { + if (this.primaryColor_ === null || this.secondaryColor_ === null) { + throw 'SelectedColorsService not properly initialized.'; + } + return [this.primaryColor_, this.secondaryColor_]; + }; + + ns.SelectedColorsService.prototype.onPrimaryColorUpdate_ = function (evt, color) { + this.primaryColor_ = color; + }; + + ns.SelectedColorsService.prototype.onSecondaryColorUpdate_ = function (evt, color) { + this.secondaryColor_ = color; + }; +})(); diff --git a/src/js/tools/drawing/DitheringTool.js b/src/js/tools/drawing/DitheringTool.js new file mode 100644 index 00000000..505cf86b --- /dev/null +++ b/src/js/tools/drawing/DitheringTool.js @@ -0,0 +1,36 @@ +/** + * @provide pskl.tools.drawing.DitheringTool + * + * @require pskl.utils + */ +(function() { + var ns = $.namespace('pskl.tools.drawing'); + + ns.DitheringTool = function() { + ns.SimplePen.call(this); + this.toolId = 'tool-dithering'; + this.helpText = 'Dithering tool'; + }; + pskl.utils.inherit(ns.DitheringTool, ns.SimplePen); + + /** + * @override + */ + ns.DitheringTool.prototype.applyToolAt = function(col, row, color, frame, overlay, event) { + // On Firefox/IE, the clicked button type is not part of the mousemove event. + // Ensure we record the pressed button on the initial mousedown only. + if (event.type == 'mousedown') { + this.invertColors_ = event.button === Constants.RIGHT_BUTTON; + } + + // Use primary selected color on cell with either an odd col or row. + // Use secondary color otherwise. + // When using the right mouse button, invert the above behavior to allow quick corrections. + var usePrimaryColor = (col + row) % 2; + usePrimaryColor = this.invertColors_ ? !usePrimaryColor : usePrimaryColor; + + var selectedColors = pskl.app.selectedColorsService.getColors(); + var ditheringColor = usePrimaryColor ? selectedColors[0] : selectedColors[1]; + this.superclass.applyToolAt.call(this, col, row, ditheringColor, frame, overlay, event); + }; +})(); diff --git a/src/piskel-script-list.js b/src/piskel-script-list.js index 64f8fd8e..f478e0d5 100644 --- a/src/piskel-script-list.js +++ b/src/piskel-script-list.js @@ -161,6 +161,7 @@ "js/service/ImageUploadService.js", "js/service/CurrentColorsService.js", "js/service/FileDropperService.js", + "js/service/SelectedColorsService.js", // Tools "js/tools/ToolsHelper.js", @@ -182,6 +183,7 @@ "js/tools/drawing/selection/ShapeSelect.js", "js/tools/drawing/ColorPicker.js", "js/tools/drawing/ColorSwap.js", + "js/tools/drawing/DitheringTool.js", "js/tools/transform/Transform.js", "js/tools/transform/Clone.js", "js/tools/transform/Flip.js",