[aseprite] 92/128: Fix selection UX to show white/black negative for the stroke

Tobias Hansen thansen at moszumanska.debian.org
Mon May 9 21:24:27 UTC 2016


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 <davidcapello at gmail.com>
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



More information about the Pkg-games-commits mailing list