[aseprite] 221/250: Fix symmetry mode when cel origin != sprite origin (0, 0)

Tobias Hansen thansen at moszumanska.debian.org
Sun Dec 20 15:27:33 UTC 2015


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit 08a04fcb64faf1f3a7ae267260ac8e9561b9bda3
Author: David Capello <davidcapello at gmail.com>
Date:   Mon Nov 2 16:44:17 2015 -0300

    Fix symmetry mode when cel origin != sprite origin (0,0)
    
    Change ToolLoop::getOffset() to getCelOrigin()
---
 src/app/tools/controller.h           |  4 +++-
 src/app/tools/ink_processing.h       |  4 ++--
 src/app/tools/inks.h                 |  8 ++++----
 src/app/tools/intertwine.cpp         | 15 ++++++++++++---
 src/app/tools/intertwine.h           |  3 +++
 src/app/tools/point_shape.h          |  2 ++
 src/app/tools/point_shapes.h         | 25 +++++++++++++------------
 src/app/tools/symmetry.h             |  2 ++
 src/app/tools/tool_loop.h            |  4 ++--
 src/app/tools/tool_loop_manager.cpp  | 24 ++++++++++++++----------
 src/app/tools/tool_loop_manager.h    |  1 +
 src/app/ui/editor/brush_preview.cpp  |  3 +--
 src/app/ui/editor/tool_loop_impl.cpp | 23 +++++++++--------------
 src/app/ui/editor/tool_loop_impl.h   |  2 +-
 14 files changed, 69 insertions(+), 51 deletions(-)

diff --git a/src/app/tools/controller.h b/src/app/tools/controller.h
index e0305e2..4206edf 100644
--- a/src/app/tools/controller.h
+++ b/src/app/tools/controller.h
@@ -39,7 +39,8 @@ namespace app {
 
       // Called when the user starts drawing and each time a new button is
       // pressed. The controller could be sure that this method is called
-      // at least one time.
+      // at least one time. The point is a position relative to sprite
+      // bounds.
       virtual void pressButton(Stroke& stroke, const gfx::Point& point) = 0;
 
       // Called each time a mouse button is released.
@@ -48,6 +49,7 @@ namespace app {
       // Called when the mouse is moved.
       virtual void movement(ToolLoop* loop, Stroke& stroke, const gfx::Point& point) = 0;
 
+      // The input and output strokes are relative to sprite coordinates.
       virtual void getStrokeToInterwine(const Stroke& input, Stroke& output) = 0;
       virtual void getStatusBarText(const Stroke& stroke, std::string& text) = 0;
     };
diff --git a/src/app/tools/ink_processing.h b/src/app/tools/ink_processing.h
index 7ec1df9..3add6b0 100644
--- a/src/app/tools/ink_processing.h
+++ b/src/app/tools/ink_processing.h
@@ -906,8 +906,8 @@ public:
     m_opacity = loop->getOpacity();
     m_width = m_brush->bounds().w;
     m_height = m_brush->bounds().h;
-    m_u = (loop->getOffset().x + m_brush->patternOrigin().x) % m_width;
-    m_v = (loop->getOffset().y + m_brush->patternOrigin().y) % m_height;
+    m_u = (m_brush->patternOrigin().x - loop->getCelOrigin().x) % m_width;
+    m_v = (m_brush->patternOrigin().y - loop->getCelOrigin().y) % m_height;
   }
 
   void processPixel(int x, int y) {
diff --git a/src/app/tools/inks.h b/src/app/tools/inks.h
index 95aa4f4..da49656 100644
--- a/src/app/tools/inks.h
+++ b/src/app/tools/inks.h
@@ -321,19 +321,19 @@ public:
 
   void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
     if (m_modify_selection) {
-      Point offset = loop->getOffset();
+      Point origin = loop->getCelOrigin();
 
       switch (loop->getSelectionMode()) {
         case SelectionMode::DEFAULT:
         case SelectionMode::ADD:
-          m_mask.add(gfx::Rect(x1-offset.x, y-offset.y, x2-x1+1, 1));
+          m_mask.add(gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1));
           break;
         case SelectionMode::SUBTRACT:
-          m_mask.subtract(gfx::Rect(x1-offset.x, y-offset.y, x2-x1+1, 1));
+          m_mask.subtract(gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1));
           break;
       }
 
-      m_maxBounds |= gfx::Rect(x1-offset.x, y-offset.y, x2-x1+1, 1);
+      m_maxBounds |= gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1);
     }
     // TODO show the selection-preview with a XOR color or something like that
     else {
diff --git a/src/app/tools/intertwine.cpp b/src/app/tools/intertwine.cpp
index 3cb2c97..02e992e 100644
--- a/src/app/tools/intertwine.cpp
+++ b/src/app/tools/intertwine.cpp
@@ -27,14 +27,23 @@ void Intertwine::doPointshapePoint(int x, int y, ToolLoop* loop)
 {
   Symmetry* symmetry = loop->getSymmetry();
   if (symmetry) {
+    Point origin(loop->getCelOrigin());
+
+    // Convert the point to the sprite position so we can apply the
+    // symmetry transformation.
     Stroke main_stroke;
-    main_stroke.addPoint(gfx::Point(x, y));
+    main_stroke.addPoint(Point(x, y) + origin);
 
     Strokes strokes;
     symmetry->generateStrokes(main_stroke, strokes);
-    for (const auto& stroke : strokes)
+    for (const auto& stroke : strokes) {
+      // We call transformPoint() moving back each point to the cel
+      // origin.
       loop->getPointShape()->transformPoint(
-        loop, stroke[0].x, stroke[0].y);
+        loop,
+        stroke[0].x - origin.x,
+        stroke[0].y - origin.y);
+    }
   }
   else {
     loop->getPointShape()->transformPoint(loop, x, y);
diff --git a/src/app/tools/intertwine.h b/src/app/tools/intertwine.h
index f73d8a2..cf1b174 100644
--- a/src/app/tools/intertwine.h
+++ b/src/app/tools/intertwine.h
@@ -29,10 +29,13 @@ namespace app {
       virtual ~Intertwine() { }
       virtual bool snapByAngle() { return false; }
       virtual void prepareIntertwine() { }
+
+      // The given stroke must be relative to the cel origin.
       virtual void joinStroke(ToolLoop* loop, const Stroke& stroke) = 0;
       virtual void fillStroke(ToolLoop* loop, const Stroke& stroke) = 0;
 
     protected:
+      // The given point must be relative to the cel origin.
       static void doPointshapePoint(int x, int y, ToolLoop* loop);
       static void doPointshapeHline(int x1, int y, int x2, ToolLoop* loop);
       static void doPointshapeLine(int x1, int y1, int x2, int y2, ToolLoop* loop);
diff --git a/src/app/tools/point_shape.h b/src/app/tools/point_shape.h
index 137c0dc..6f2034c 100644
--- a/src/app/tools/point_shape.h
+++ b/src/app/tools/point_shape.h
@@ -22,6 +22,8 @@ namespace app {
       virtual bool isFloodFill() { return false; }
       virtual bool isSpray() { return false; }
       virtual void preparePointShape(ToolLoop* loop) { }
+
+      // The x, y position must be relative to the cel/src/dst image origin.
       virtual void transformPoint(ToolLoop* loop, int x, int y) = 0;
       virtual void getModifiedArea(ToolLoop* loop, int x, int y, gfx::Rect& area) = 0;
 
diff --git a/src/app/tools/point_shapes.h b/src/app/tools/point_shapes.h
index a3fb490..d524768 100644
--- a/src/app/tools/point_shapes.h
+++ b/src/app/tools/point_shapes.h
@@ -52,14 +52,14 @@ public:
       if (m_brush->type() == kImageBrushType) {
         if (m_brush->pattern() == BrushPattern::ALIGNED_TO_DST ||
             m_brush->pattern() == BrushPattern::PAINT_BRUSH) {
-          m_brush->setPatternOrigin(gfx::Point(x, y)-loop->getOffset());
+          m_brush->setPatternOrigin(gfx::Point(x, y)+loop->getCelOrigin());
         }
       }
     }
     else {
       if (m_brush->type() == kImageBrushType &&
           m_brush->pattern() == BrushPattern::PAINT_BRUSH) {
-        m_brush->setPatternOrigin(gfx::Point(x, y)-loop->getOffset());
+        m_brush->setPatternOrigin(gfx::Point(x, y)+loop->getCelOrigin());
       }
     }
 
@@ -84,24 +84,25 @@ public:
   void transformPoint(ToolLoop* loop, int x, int y) override {
     doc::algorithm::floodfill(
       const_cast<Image*>(loop->getSrcImage()), x, y,
-      paintBounds(loop, x, y),
+      floodfillBounds(loop, x, y),
       loop->getTolerance(),
       loop->getContiguous(),
       loop, (AlgoHLine)doInkHline);
   }
 
   void getModifiedArea(ToolLoop* loop, int x, int y, Rect& area) override {
-    area = paintBounds(loop, x, y);
+    area = floodfillBounds(loop, x, y);
   }
 
 private:
-  gfx::Rect paintBounds(ToolLoop* loop, int x, int y) {
-    gfx::Point offset = loop->getOffset();
-    gfx::Rect bounds(
-      offset.x, offset.y,
-      loop->sprite()->width(), loop->sprite()->height());
+  gfx::Rect floodfillBounds(ToolLoop* loop, int x, int y) const {
+    gfx::Point origin = loop->getCelOrigin();
+    gfx::Rect bounds(-origin.x, -origin.y,
+                     loop->sprite()->width(),
+                     loop->sprite()->height());
 
-    bounds = bounds.createIntersection(loop->getSrcImage()->bounds());
+    bounds = bounds.createIntersection(
+      loop->getSrcImage()->bounds());
 
     // Limit the flood-fill to the current tile if the grid is visible.
     if (loop->getStopAtGrid()) {
@@ -109,8 +110,8 @@ private:
       if (!grid.isEmpty()) {
         div_t d, dx, dy;
 
-        dx = div(grid.x+loop->getOffset().x, grid.w);
-        dy = div(grid.y+loop->getOffset().y, grid.h);
+        dx = div(grid.x-origin.x, grid.w);
+        dy = div(grid.y-origin.y, grid.h);
 
         if (dx.rem > 0) dx.rem -= grid.w;
         if (dy.rem > 0) dy.rem -= grid.h;
diff --git a/src/app/tools/symmetry.h b/src/app/tools/symmetry.h
index d1368dd..d70c637 100644
--- a/src/app/tools/symmetry.h
+++ b/src/app/tools/symmetry.h
@@ -20,6 +20,8 @@ namespace app {
     class Symmetry {
     public:
       virtual ~Symmetry() { }
+
+      // The "stroke" must be relative to the sprite origin.
       virtual void generateStrokes(const Stroke& stroke, Strokes& strokes) = 0;
     };
 
diff --git a/src/app/tools/tool_loop.h b/src/app/tools/tool_loop.h
index 9e8306f..1a5d8f8 100644
--- a/src/app/tools/tool_loop.h
+++ b/src/app/tools/tool_loop.h
@@ -187,8 +187,8 @@ namespace app {
       virtual int getSprayWidth() = 0;
       virtual int getSpraySpeed() = 0;
 
-      // Offset for each point
-      virtual gfx::Point getOffset() = 0;
+      // X,Y origin of the cel where we are drawing
+      virtual gfx::Point getCelOrigin() = 0;
 
       // Velocity vector of the mouse
       virtual void setSpeed(const gfx::Point& speed) = 0;
diff --git a/src/app/tools/tool_loop_manager.cpp b/src/app/tools/tool_loop_manager.cpp
index ce858b4..8e7565f 100644
--- a/src/app/tools/tool_loop_manager.cpp
+++ b/src/app/tools/tool_loop_manager.cpp
@@ -164,15 +164,14 @@ void ToolLoopManager::movement(const Pointer& pointer)
 
 void ToolLoopManager::doLoopStep(bool last_step)
 {
-  // Original set of points to interwine (original user stroke).
+  // Original set of points to interwine (original user stroke,
+  // relative to sprite origin).
   Stroke main_stroke;
   if (!last_step)
     m_toolLoop->getController()->getStrokeToInterwine(m_stroke, main_stroke);
   else
     main_stroke = m_stroke;
 
-  main_stroke.offset(m_toolLoop->getOffset());
-
   // Calculate the area to be updated in all document observers.
   Symmetry* symmetry = m_toolLoop->getSymmetry();
   Strokes strokes;
@@ -209,6 +208,9 @@ void ToolLoopManager::doLoopStep(bool last_step)
 
   m_toolLoop->validateDstImage(m_dirtyArea);
 
+  // Move the stroke to be relative to the cel origin.
+  main_stroke.offset(-m_toolLoop->getCelOrigin());
+
   // Join or fill user points
   if (!m_toolLoop->getFilled() || (!last_step && !m_toolLoop->getPreviewFilled()))
     m_toolLoop->getIntertwine()->joinStroke(m_toolLoop, main_stroke);
@@ -235,6 +237,7 @@ void ToolLoopManager::snapToGrid(Point& point)
   point = snap_to_grid(m_toolLoop->getGridBounds(), point);
 }
 
+// Strokes are relative to sprite origin.
 void ToolLoopManager::calculateDirtyArea(const Strokes& strokes)
 {
   // Save the current dirty area if it's needed
@@ -245,6 +248,8 @@ void ToolLoopManager::calculateDirtyArea(const Strokes& strokes)
   // Start with a fresh dirty area
   m_dirtyArea.clear();
 
+  const Point celOrigin = m_toolLoop->getCelOrigin();
+
   for (auto& stroke : strokes) {
     gfx::Rect strokeBounds = stroke.bounds();
     if (strokeBounds.isEmpty())
@@ -255,20 +260,19 @@ void ToolLoopManager::calculateDirtyArea(const Strokes& strokes)
 
     m_toolLoop->getPointShape()->getModifiedArea(
       m_toolLoop,
-      strokeBounds.x,
-      strokeBounds.y, r1);
+      strokeBounds.x - celOrigin.x,
+      strokeBounds.y - celOrigin.y, r1);
 
     m_toolLoop->getPointShape()->getModifiedArea(
       m_toolLoop,
-      strokeBounds.x+strokeBounds.w-1,
-      strokeBounds.y+strokeBounds.h-1, r2);
+      strokeBounds.x+strokeBounds.w-1 - celOrigin.x,
+      strokeBounds.y+strokeBounds.h-1 - celOrigin.y, r2);
 
     m_dirtyArea.createUnion(m_dirtyArea, Region(r1.createUnion(r2)));
   }
 
-  // Apply offset mode
-  Point offset(m_toolLoop->getOffset());
-  m_dirtyArea.offset(-offset);
+  // Make the dirty area relative to the sprite.
+  m_dirtyArea.offset(celOrigin);
 
   // Merge new dirty area with the previous one (for tools like line
   // or rectangle it's needed to redraw the previous position and
diff --git a/src/app/tools/tool_loop_manager.h b/src/app/tools/tool_loop_manager.h
index 500f777..063d191 100644
--- a/src/app/tools/tool_loop_manager.h
+++ b/src/app/tools/tool_loop_manager.h
@@ -38,6 +38,7 @@ namespace app {
     //    is called.
     // 5. When the user release the mouse:
     //    - ToolLoopManager::releaseButton
+    //
     class ToolLoopManager {
     public:
 
diff --git a/src/app/ui/editor/brush_preview.cpp b/src/app/ui/editor/brush_preview.cpp
index cdeae7b..d236399 100644
--- a/src/app/ui/editor/brush_preview.cpp
+++ b/src/app/ui/editor/brush_preview.cpp
@@ -184,8 +184,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
       base::UniquePtr<tools::ToolLoop> loop(
         create_tool_loop_preview(
           m_editor, extraImage,
-          -gfx::Point(brushBounds.x,
-                      brushBounds.y)));
+          brushBounds.getOrigin()));
       if (loop) {
         loop->getInk()->prepareInk(loop);
         loop->getIntertwine()->prepareIntertwine();
diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp
index 218965c..b4b3a42 100644
--- a/src/app/ui/editor/tool_loop_impl.cpp
+++ b/src/app/ui/editor/tool_loop_impl.cpp
@@ -70,7 +70,7 @@ protected:
   int m_opacity;
   int m_tolerance;
   bool m_contiguous;
-  gfx::Point m_offset;
+  gfx::Point m_celOrigin;
   gfx::Point m_speed;
   tools::ToolLoop::Button m_button;
   base::UniquePtr<tools::Ink> m_ink;
@@ -207,7 +207,7 @@ public:
     return false;
   }
   gfx::Rect getGridBounds() override { return m_docPref.grid.bounds(); }
-  gfx::Point getOffset() override { return m_offset; }
+  gfx::Point getCelOrigin() override { return m_celOrigin; }
   void setSpeed(const gfx::Point& speed) override { m_speed = speed; }
   gfx::Point getSpeed() override { return m_speed; }
   tools::Ink* getInk() override { return m_ink; }
@@ -317,16 +317,11 @@ public:
       m_transaction.execute(new cmd::SetMask(m_document, &emptyMask));
     }
 
-    int x1 = m_expandCelCanvas.getCel()->x();
-    int y1 = m_expandCelCanvas.getCel()->y();
-
+    m_celOrigin = m_expandCelCanvas.getCel()->position();
     m_mask = m_document->mask();
-    m_maskOrigin = (!m_mask->isEmpty() ? gfx::Point(m_mask->bounds().x-x1,
-                                                    m_mask->bounds().y-y1):
+    m_maskOrigin = (!m_mask->isEmpty() ? gfx::Point(m_mask->bounds().x-m_celOrigin.x,
+                                                    m_mask->bounds().y-m_celOrigin.y):
                                          gfx::Point(0, 0));
-
-    m_offset.x = -x1;
-    m_offset.y = -y1;
   }
 
   // IToolLoop interface
@@ -485,12 +480,12 @@ public:
     const app::Color& fgColor,
     const app::Color& bgColor,
     Image* image,
-    const gfx::Point& offset)
+    const gfx::Point& celOrigin)
     : ToolLoopBase(editor, tool, ink, document,
                    tools::ToolLoop::Left, fgColor, bgColor)
     , m_image(image)
   {
-    m_offset = offset;
+    m_celOrigin = celOrigin;
 
     // Avoid preview for spray and flood fill like tools
     if (m_pointShape->isSpray()) {
@@ -529,7 +524,7 @@ public:
 
 tools::ToolLoop* create_tool_loop_preview(
   Editor* editor, Image* image,
-  const gfx::Point& offset)
+  const gfx::Point& celOrigin)
 {
   tools::Tool* current_tool = editor->getCurrentEditorTool();
   tools::Ink* current_ink = editor->getCurrentEditorInk();
@@ -557,7 +552,7 @@ tools::ToolLoop* create_tool_loop_preview(
       current_tool,
       current_ink,
       editor->document(),
-      fg, bg, image, offset);
+      fg, bg, image, celOrigin);
   }
   catch (const std::exception&) {
     return nullptr;
diff --git a/src/app/ui/editor/tool_loop_impl.h b/src/app/ui/editor/tool_loop_impl.h
index 0a83a3b..e89ec41 100644
--- a/src/app/ui/editor/tool_loop_impl.h
+++ b/src/app/ui/editor/tool_loop_impl.h
@@ -29,7 +29,7 @@ namespace app {
 
   tools::ToolLoop* create_tool_loop_preview(
     Editor* editor, doc::Image* image,
-    const gfx::Point& offset);
+    const gfx::Point& celOrigin);
 
 } // namespace app
 

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