This is an automated email from the git hooks/post-receive script. thansen pushed a commit to branch master in repository aseprite.
commit 640025e84bb211151415b569c7b42da80c865477 Author: David Capello <[email protected]> Date: Mon May 2 18:42:02 2016 -0300 Fix selection UX to show white/black negative for the stroke With this patch now we can use the selection tool in locked or hidden layers, because the selection doesn't modify the layers (only the selection). Also we can use the selection tool on any layer and we'll always see the feedback stroke/shape/rectangle while we're creating the new selection. --- src/app/commands/filters/filter_preview.cpp | 6 ++- src/app/ui/editor/drawing_state.cpp | 7 ++- src/app/ui/editor/pixels_movement.cpp | 3 +- src/app/ui/editor/standby_state.cpp | 5 +- src/app/ui/editor/tool_loop_impl.cpp | 75 +++++++++++++++++++---------- src/app/util/expand_cel_canvas.cpp | 27 ++++++++--- src/app/util/expand_cel_canvas.h | 6 ++- src/render/render.cpp | 52 ++++++++++++++++++-- src/render/render.h | 16 +++++- 9 files changed, 150 insertions(+), 47 deletions(-) diff --git a/src/app/commands/filters/filter_preview.cpp b/src/app/commands/filters/filter_preview.cpp index 5ea2450..41fc463 100644 --- a/src/app/commands/filters/filter_preview.cpp +++ b/src/app/commands/filters/filter_preview.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -14,6 +14,7 @@ #include "app/commands/filters/filter_manager_impl.h" #include "app/modules/editors.h" #include "app/ui/editor/editor.h" +#include "doc/layer.h" #include "doc/sprite.h" #include "ui/manager.h" #include "ui/message.h" @@ -68,7 +69,8 @@ bool FilterPreview::onProcessMessage(Message* msg) current_editor->renderEngine().setPreviewImage( m_filterMgr->layer(), m_filterMgr->frame(), - m_filterMgr->destinationImage()); + m_filterMgr->destinationImage(), + static_cast<doc::LayerImage*>(m_filterMgr->layer())->blendMode()); break; case kCloseMessage: diff --git a/src/app/ui/editor/drawing_state.cpp b/src/app/ui/editor/drawing_state.cpp index 75f26bb..d8a75dd 100644 --- a/src/app/ui/editor/drawing_state.cpp +++ b/src/app/ui/editor/drawing_state.cpp @@ -24,6 +24,7 @@ #include "app/ui/editor/glue.h" #include "app/ui/keyboard_shortcuts.h" #include "app/ui_context.h" +#include "doc/layer.h" #include "ui/message.h" #include "ui/system.h" @@ -61,7 +62,11 @@ void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg) editor->renderEngine().setPreviewImage( m_toolLoop->getLayer(), m_toolLoop->getFrame(), - m_toolLoop->getDstImage()); + m_toolLoop->getDstImage(), + (m_toolLoop->getLayer() && + m_toolLoop->getLayer()->isImage() ? + static_cast<LayerImage*>(m_toolLoop->getLayer())->blendMode(): + BlendMode::NEG_BW)); m_lastPoint = editor->lastDrawingPosition(); diff --git a/src/app/ui/editor/pixels_movement.cpp b/src/app/ui/editor/pixels_movement.cpp index 2509867..f6d4989 100644 --- a/src/app/ui/editor/pixels_movement.cpp +++ b/src/app/ui/editor/pixels_movement.cpp @@ -479,7 +479,8 @@ void PixelsMovement::stampImage() { // Expand the canvas to paste the image in the fully visible // portion of sprite. - ExpandCelCanvas expand(m_site, + ExpandCelCanvas expand( + m_site, m_site.layer(), TiledMode::NONE, m_transaction, ExpandCelCanvas::None); diff --git a/src/app/ui/editor/standby_state.cpp b/src/app/ui/editor/standby_state.cpp index 3ae205a..c4e8231 100644 --- a/src/app/ui/editor/standby_state.cpp +++ b/src/app/ui/editor/standby_state.cpp @@ -378,9 +378,10 @@ bool StandbyState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos) editor->showMouseCursor(kArrowPlusCursor); else editor->showMouseCursor(kMoveCursor); - - return true; } + else + editor->showBrushPreview(mouseScreenPos); + return true; } else if (ink->isEyedropper()) { editor->showMouseCursor(kEyedropperCursor); diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp index cc4a245..c787455 100644 --- a/src/app/ui/editor/tool_loop_impl.cpp +++ b/src/app/ui/editor/tool_loop_impl.cpp @@ -81,6 +81,7 @@ protected: tools::TracePolicy m_tracePolicy; base::UniquePtr<tools::Symmetry> m_symmetry; base::UniquePtr<doc::Remap> m_shadingRemap; + app::ColorTarget m_colorTarget; doc::color_t m_fgColor; doc::color_t m_bgColor; doc::color_t m_primaryColor; @@ -89,6 +90,7 @@ protected: public: ToolLoopBase(Editor* editor, + Layer* layer, tools::Tool* tool, tools::Ink* ink, Document* document, @@ -100,7 +102,7 @@ public: , m_brush(App::instance()->contextBar()->activeBrush(m_tool)) , m_document(document) , m_sprite(editor->sprite()) - , m_layer(editor->layer()) + , m_layer(layer) , m_frame(editor->frame()) , m_rgbMap(nullptr) , m_docPref(Preferences::instance().document(m_document)) @@ -115,8 +117,12 @@ public: , m_intertwine(m_tool->getIntertwine(m_button)) , m_tracePolicy(m_tool->getTracePolicy(m_button)) , m_symmetry(nullptr) - , m_fgColor(color_utils::color_for_target_mask(fgColor, ColorTarget(m_layer))) - , m_bgColor(color_utils::color_for_target_mask(bgColor, ColorTarget(m_layer))) + , m_colorTarget(m_layer ? ColorTarget(m_layer): + ColorTarget(ColorTarget::BackgroundLayer, + m_sprite->pixelFormat(), + m_sprite->transparentColor())) + , m_fgColor(color_utils::color_for_target_mask(fgColor, m_colorTarget)) + , m_bgColor(color_utils::color_for_target_mask(bgColor, m_colorTarget)) , m_primaryColor(button == tools::ToolLoop::Left ? m_fgColor: m_bgColor) , m_secondaryColor(button == tools::ToolLoop::Left ? m_bgColor: m_fgColor) { @@ -184,7 +190,8 @@ public: RgbMap* getRgbMap() override { if (!m_rgbMap) { Sprite::RgbMapFor forLayer = - ((m_layer->isBackground() || + ((!m_layer || + m_layer->isBackground() || m_sprite->pixelFormat() == IMAGE_RGB) ? Sprite::RgbMapFor::OpaqueLayer: Sprite::RgbMapFor::TransparentLayer); @@ -265,6 +272,7 @@ class ToolLoopImpl : public ToolLoopBase { public: ToolLoopImpl(Editor* editor, + Layer* layer, Context* context, tools::Tool* tool, tools::Ink* ink, @@ -272,7 +280,7 @@ public: tools::ToolLoop::Button button, const app::Color& fgColor, const app::Color& bgColor) - : ToolLoopBase(editor, tool, ink, document, + : ToolLoopBase(editor, layer, tool, ink, document, button, fgColor, bgColor) , m_context(context) , m_canceled(false) @@ -284,7 +292,9 @@ public: getInk()->isSlice() || getInk()->isZoom()) ? DoesntModifyDocument: ModifyDocument)) - , m_expandCelCanvas(editor->getSite(), + , m_expandCelCanvas( + editor->getSite(), + layer, m_docPref.tiled.mode(), m_transaction, ExpandCelCanvas::Flags( @@ -424,24 +434,39 @@ tools::ToolLoop* create_tool_loop(Editor* editor, Context* context) if (!current_tool || !current_ink) return NULL; - Layer* layer = editor->layer(); - if (!layer) { - StatusBar::instance()->showTip(1000, - "There is no active layer"); - return NULL; - } - - // If the active layer is not visible. - if (!layer->isVisible()) { - StatusBar::instance()->showTip(1000, - "Layer '%s' is hidden", layer->name().c_str()); - return NULL; + Layer* layer; + + // For selection tools, we can use any layer (even without layers at + // all), so we specify a nullptr here as the active layer. This is + // used as a special case by the render::Render class to show the + // preview image/selection stroke as a xor'd overlay in the render + // result. + // + // Anyway this cannot be used in 'magic wand' tool (isSelection + + // isFloodFill) because we need the original layer source + // image/pixels to stop the flood-fill algorithm. + if (current_ink->isSelection() && + !current_tool->getPointShape(editor->isSecondaryButton() ? 1: 0)->isFloodFill()) { + layer = nullptr; } - // If the active layer is read-only. - else if (!layer->isEditable()) { - StatusBar::instance()->showTip(1000, - "Layer '%s' is locked", layer->name().c_str()); - return NULL; + else { + layer = editor->layer(); + if (!layer) { + StatusBar::instance()->showTip( + 1000, "There is no active layer"); + return nullptr; + } + else if (!layer->isVisible()) { + StatusBar::instance()->showTip( + 1000, "Layer '%s' is hidden", layer->name().c_str()); + return nullptr; + } + // If the active layer is read-only. + else if (!layer->isEditable()) { + StatusBar::instance()->showTip( + 1000, "Layer '%s' is locked", layer->name().c_str()); + return nullptr; + } } // Get fg/bg colors @@ -463,7 +488,7 @@ tools::ToolLoop* create_tool_loop(Editor* editor, Context* context) // Create the new tool loop try { return new ToolLoopImpl( - editor, context, + editor, layer, context, current_tool, current_ink, editor->document(), @@ -496,7 +521,7 @@ public: const app::Color& bgColor, Image* image, const gfx::Point& celOrigin) - : ToolLoopBase(editor, tool, ink, document, + : ToolLoopBase(editor, editor->layer(), tool, ink, document, tools::ToolLoop::Left, fgColor, bgColor) , m_image(image) { diff --git a/src/app/util/expand_cel_canvas.cpp b/src/app/util/expand_cel_canvas.cpp index 7206392..3cc41c2 100644 --- a/src/app/util/expand_cel_canvas.cpp +++ b/src/app/util/expand_cel_canvas.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -27,6 +27,7 @@ #include "doc/primitives.h" #include "doc/site.h" #include "doc/sprite.h" +#include "render/render.h" namespace { @@ -57,11 +58,13 @@ static void create_buffers() namespace app { -ExpandCelCanvas::ExpandCelCanvas(Site site, +ExpandCelCanvas::ExpandCelCanvas( + Site site, Layer* layer, TiledMode tiledMode, Transaction& transaction, Flags flags) : m_document(static_cast<app::Document*>(site.document())) , m_sprite(site.sprite()) - , m_layer(site.layer()) + , m_layer(layer) + , m_frame(site.frame()) , m_cel(NULL) , m_celImage(NULL) , m_celCreated(false) @@ -77,14 +80,14 @@ ExpandCelCanvas::ExpandCelCanvas(Site site, create_buffers(); - if (m_layer->isImage()) { + if (m_layer && m_layer->isImage()) { m_cel = m_layer->cel(site.frame()); if (m_cel) m_celImage = m_cel->imageRef(); } // Create a new cel - if (m_cel == NULL) { + if (!m_cel) { m_celCreated = true; m_cel = new Cel(site.frame(), ImageRef(NULL)); } @@ -117,7 +120,9 @@ ExpandCelCanvas::ExpandCelCanvas(Site site, if (m_celCreated) { getDestCanvas(); m_cel->data()->setImage(m_dstImage); - static_cast<LayerImage*>(m_layer)->addCel(m_cel); + + if (m_layer && m_layer->isImage()) + static_cast<LayerImage*>(m_layer)->addCel(m_cel); } } @@ -140,6 +145,11 @@ void ExpandCelCanvas::commit() ASSERT(!m_closed); ASSERT(!m_committed); + if (!m_layer) { + m_committed = true; + return; + } + // Was the cel created in the start of the tool-loop? if (m_celCreated) { ASSERT(m_cel); @@ -150,6 +160,7 @@ void ExpandCelCanvas::commit() validateDestCanvas(gfx::Region(m_bounds)); // We can temporary remove the cel. + ASSERT(m_layer->isImage()); static_cast<LayerImage*>(m_layer)->removeCel(m_cel); // Add a copy of m_dstImage in the sprite's image stock @@ -213,7 +224,9 @@ void ExpandCelCanvas::rollback() m_cel->setPosition(m_origCelPos); if (m_celCreated) { - static_cast<LayerImage*>(m_layer)->removeCel(m_cel); + if (m_layer && m_layer->isImage()) + static_cast<LayerImage*>(m_layer)->removeCel(m_cel); + delete m_cel; m_celImage.reset(NULL); } diff --git a/src/app/util/expand_cel_canvas.h b/src/app/util/expand_cel_canvas.h index f2339a3..9c2bf28 100644 --- a/src/app/util/expand_cel_canvas.h +++ b/src/app/util/expand_cel_canvas.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -9,6 +9,7 @@ #define APP_UTIL_EXPAND_CEL_CANVAS_H_INCLUDED #pragma once +#include "doc/frame.h" #include "doc/image_ref.h" #include "filters/tiled_mode.h" #include "gfx/point.h" @@ -45,7 +46,7 @@ namespace app { UseModifiedRegionAsUndoInfo = 2, }; - ExpandCelCanvas(Site site, + ExpandCelCanvas(Site site, Layer* layer, TiledMode tiledMode, Transaction& undo, Flags flags); ~ExpandCelCanvas(); @@ -73,6 +74,7 @@ namespace app { Document* m_document; Sprite* m_sprite; Layer* m_layer; + frame_t m_frame; Cel* m_cel; ImageRef m_celImage; bool m_celCreated; diff --git a/src/render/render.cpp b/src/render/render.cpp index da7d29d..3e0ad35 100644 --- a/src/render/render.cpp +++ b/src/render/render.cpp @@ -348,6 +348,7 @@ Render::Render() , m_selectedLayer(nullptr) , m_selectedFrame(-1) , m_previewImage(nullptr) + , m_previewBlendMode(BlendMode::NORMAL) , m_onionskin(OnionskinType::NONE) { } @@ -377,11 +378,13 @@ void Render::setBgCheckedSize(const gfx::Size& size) m_bgCheckedSize = size; } -void Render::setPreviewImage(const Layer* layer, frame_t frame, Image* image) +void Render::setPreviewImage(const Layer* layer, frame_t frame, + Image* image, BlendMode blendMode) { m_selectedLayer = layer; m_selectedFrame = frame; m_previewImage = image; + m_previewBlendMode = blendMode; } void Render::setExtraImage( @@ -400,7 +403,7 @@ void Render::setExtraImage( void Render::removePreviewImage() { - m_previewImage = NULL; + m_previewImage = nullptr; } void Render::removeExtraImage() @@ -548,6 +551,22 @@ void Render::renderSprite( // Draw onion skin in front of the sprite. if (m_onionskin.position() == OnionskinPosition::INFRONT) renderOnionskin(dstImage, area, frame, zoom, scaled_func); + + // Overlay preview image + if (m_previewImage && + m_selectedLayer == nullptr && + m_selectedFrame == frame) { + renderImage( + dstImage, + m_previewImage, + m_sprite->palette(frame), + 0, 0, + area, + scaled_func, + 255, + m_previewBlendMode, + zoom); + } } void Render::renderOnionskin( @@ -827,13 +846,36 @@ void Render::renderCel( RenderScaledImage scaled_func, int opacity, BlendMode blend_mode, Zoom zoom) { - int cel_x = zoom.apply(cel->x()); - int cel_y = zoom.apply(cel->y()); + renderImage(dst_image, + cel_image, + pal, + cel->x(), + cel->y(), + area, + scaled_func, + opacity, + blend_mode, + zoom); +} + +void Render::renderImage( + Image* dst_image, + const Image* cel_image, + const Palette* pal, + const int x, + const int y, + const gfx::Clip& area, + RenderScaledImage scaled_func, + int opacity, BlendMode blend_mode, Zoom zoom) +{ + int cel_x = zoom.apply(x); + int cel_y = zoom.apply(y); gfx::Rect src_bounds = area.srcBounds().createIntersection( gfx::Rect( - cel_x, cel_y, + cel_x, + cel_y, zoom.apply(cel_image->width()), zoom.apply(cel_image->height()))); if (src_bounds.isEmpty()) diff --git a/src/render/render.h b/src/render/render.h index 5f41aed..93a6dbe 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -1,5 +1,5 @@ // Aseprite Render Library -// Copyright (c) 2001-2015 David Capello +// Copyright (c) 2001-2016 David Capello // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -102,7 +102,8 @@ namespace render { // Sets the preview image. This preview image is an alternative // image to be used for the given layer/frame. - void setPreviewImage(const Layer* layer, frame_t frame, Image* drawable); + void setPreviewImage(const Layer* layer, frame_t frame, + Image* image, BlendMode blendMode); void removePreviewImage(); // Sets an extra cel/image to be drawn after the current @@ -190,6 +191,16 @@ namespace render { RenderScaledImage scaled_func, int opacity, BlendMode blend_mode, Zoom zoom); + void renderImage( + Image* dst_image, + const Image* cel_image, + const Palette* pal, + const int x, + const int y, + const gfx::Clip& area, + RenderScaledImage scaled_func, + int opacity, BlendMode blend_mode, Zoom zoom); + static RenderScaledImage getRenderScaledImageFunc( PixelFormat dstFormat, PixelFormat srcFormat); @@ -211,6 +222,7 @@ namespace render { const Layer* m_selectedLayer; frame_t m_selectedFrame; Image* m_previewImage; + BlendMode m_previewBlendMode; OnionskinOptions m_onionskin; }; -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

