diff --git a/src/app/ui/editor/pixels_movement.cpp b/src/app/ui/editor/pixels_movement.cpp index e74559c53..286477539 100644 --- a/src/app/ui/editor/pixels_movement.cpp +++ b/src/app/ui/editor/pixels_movement.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019-2022 Igara Studio S.A. +// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -369,32 +369,14 @@ void PixelsMovement::moveImage(const gfx::PointF& pos, MoveModifier moveModifier gfx::RectF bounds = m_initialData.bounds(); gfx::PointF abs_initial_pivot = m_initialData.pivot(); gfx::PointF abs_pivot = m_currentData.pivot(); - const bool tilemapModeOrSnapToGrid = - (m_site.tilemapMode() == TilemapMode::Tiles && m_site.layer()->isTilemap()) || - (moveModifier & SnapToGridMovement) == SnapToGridMovement; auto newTransformation = m_currentData; - gfx::Point initialDataOrigin; - switch (m_handle) { case MovePixelsHandle: { double dx = (pos.x - m_catchPos.x); double dy = (pos.y - m_catchPos.y); - if (tilemapModeOrSnapToGrid) { - initialDataOrigin = bounds.origin(); - if (m_catchPos.x == 0 && m_catchPos.y == 0) { - // Movement through keyboard: - dx *= m_site.gridBounds().w; - dy *= m_site.gridBounds().h; - } - else { - // Movement through mouse/trackpad: - dx = double(int(dx) / m_site.gridBounds().w * m_site.gridBounds().w); - dy = double(int(dy) / m_site.gridBounds().h * m_site.gridBounds().h); - } - } if ((moveModifier & FineControl) == 0) { if (dx >= 0.0) { dx = std::floor(dx); } else { dx = std::ceil(dx); } if (dy >= 0.0) { dy = std::floor(dy); } else { dy = std::ceil(dy); } @@ -408,10 +390,26 @@ void PixelsMovement::moveImage(const gfx::PointF& pos, MoveModifier moveModifier } bounds.offset(dx, dy); + + if ((m_site.tilemapMode() == TilemapMode::Tiles) || + (moveModifier & SnapToGridMovement) == SnapToGridMovement) { + // Snap the x1,y1 point to the grid. + gfx::Rect gridBounds = m_site.gridBounds(); + gfx::PointF gridOffset( + snap_to_grid( + gridBounds, + gfx::Point(bounds.origin()), + PreferSnapTo::ClosestGridVertex)); + + // Now we calculate the difference from x1,y1 point and we can + // use it to adjust all coordinates (x1, y1, x2, y2). + bounds.setOrigin(gridOffset); + } + newTransformation.bounds(bounds); newTransformation.pivot(abs_initial_pivot + bounds.origin() - - initialDataOrigin); + m_initialData.bounds().origin()); break; } @@ -714,7 +712,6 @@ void PixelsMovement::moveImage(const gfx::PointF& pos, MoveModifier moveModifier void PixelsMovement::getDraggedImageCopy(std::unique_ptr& outputImage, std::unique_ptr& outputMask) { - ASSERT(!(m_site.tilemapMode() == TilemapMode::Tiles && !m_site.layer()->isTilemap())); gfx::Rect bounds = m_currentData.transformedBounds(); if (bounds.isEmpty()) return; @@ -762,29 +759,6 @@ void PixelsMovement::getDraggedImageCopy(std::unique_ptr& outputImage, outputMask.reset(mask.release()); } -void PixelsMovement::alignMasksAndTransformData( - const Mask* initialMask0, - const Mask* initialMask, - const Mask* currentMask, - const Transformation* initialData, - const Transformation* currentData, - const doc::Grid& grid, - const gfx::SizeF& initialScaleRatio) -{ - m_initialMask0->replace(Mask(grid.makeAlignedMask(initialMask0))); - m_initialMask->replace(Mask(grid.makeAlignedMask(initialMask))); - m_currentMask->replace(Mask(grid.makeAlignedMask(currentMask))); - gfx::RectF iniBounds = grid.alignBounds(initialData->bounds()); - m_initialData.bounds(iniBounds); - m_currentData.bounds(gfx::RectF(gfx::PointF(grid.alignBounds(currentData->bounds()).origin()), - gfx::SizeF(initialScaleRatio.w == 1.0 ? - iniBounds.w : - m_currentData.bounds().w, - initialScaleRatio.h == 1.0 ? - iniBounds.h : - m_currentData.bounds().h))); -} - void PixelsMovement::stampImage() { stampImage(false); @@ -817,101 +791,14 @@ void PixelsMovement::stampImage(bool finalStamp) stampExtraCelImage(); } - // Saving original values before the 'for' loop - TilemapMode originalSiteTilemapMode = (m_site.tilemapMode() == TilemapMode::Tiles && - m_site.layer()->isTilemap()? TilemapMode::Tiles : TilemapMode::Pixels); - TilesetMode originalSiteTilesetMode = m_site.tilesetMode(); - std::unique_ptr initialMask0(new Mask(*m_initialMask0.get())); - std::unique_ptr initialMask(new Mask(*m_initialMask.get())); - std::unique_ptr currentMask(new Mask(*m_currentMask.get())); - std::unique_ptr initialData(new Transformation(m_initialData)); - std::unique_ptr currentData(new Transformation(m_currentData)); - - gfx::SizeF initialScaleRatio(double(m_currentData.bounds().w) / double(m_initialData.bounds().w), - double(m_currentData.bounds().h) / double(m_initialData.bounds().h)); - - bool lastProcessedLayerWasTilemap; - Grid lastGrid = m_site.grid(); - if (originalSiteTilemapMode == TilemapMode::Tiles) { - alignMasksAndTransformData(initialMask0.get(), - initialMask.get(), - currentMask.get(), - initialData.get(), - currentData.get(), - lastGrid, - initialScaleRatio); - lastProcessedLayerWasTilemap = true; - } - else - lastProcessedLayerWasTilemap = false; - - Grid targetGrid(m_site.grid()); for (Cel* target : cels) { // We'll re-create the transformation for the other cels if (target != currentCel) { ASSERT(target); m_site.layer(target->layer()); m_site.frame(target->frame()); - targetGrid = m_site.grid(); - // Preparing masks and transform Data before to reproduceAllTransformationsWithInnerCmds - if (lastProcessedLayerWasTilemap && target->layer()->isTilemap()) { - // Need to re-align masks and transform data of a new tilemap. - // The 'temp' buffers has to be re-calculated if the last grid is different - // compared with the last one 'lastGrid'. - if (originalSiteTilemapMode == TilemapMode::Tiles && targetGrid != lastGrid) { - alignMasksAndTransformData(initialMask0.get(), - initialMask.get(), - currentMask.get(), - initialData.get(), - currentData.get(), - targetGrid, - initialScaleRatio); - lastGrid = targetGrid; - lastProcessedLayerWasTilemap = true; - } - else - lastProcessedLayerWasTilemap = false; - } - else if (lastProcessedLayerWasTilemap && !target->layer()->isTilemap()) { - // Convert masks and transform data to initial - m_initialMask0->replace(*initialMask0.get()); - m_initialMask->replace(*initialMask.get()); - m_currentMask->replace(*currentMask.get()); - m_initialData.bounds(initialData.get()->bounds()); - m_currentData.bounds(currentData.get()->bounds()); - lastProcessedLayerWasTilemap = false; - } - else if (!lastProcessedLayerWasTilemap && target->layer()->isTilemap()) { - // Align masks and transforms data to initial - if (originalSiteTilemapMode == TilemapMode::Tiles) { - alignMasksAndTransformData(initialMask0.get(), - initialMask.get(), - currentMask.get(), - initialData.get(), - currentData.get(), - targetGrid, - initialScaleRatio); - lastGrid = targetGrid; - lastProcessedLayerWasTilemap = true; - } - else { - // Do nothing, because 'lastProcessedLayerWasTilemap' was NO tilemap, - // so 'm_initialData' and 'm_currentData' is correctly adjusted from - // the previous 'for' iteration. - lastProcessedLayerWasTilemap = false; - } - } - else {// !lastProcessedLayerWasTilemap && !target->layer()->isTilemap() - // Do nothing - lastProcessedLayerWasTilemap = false; - } ASSERT(m_site.cel() == target); - if (originalSiteTilemapMode == TilemapMode::Tiles && target->layer()->isTilemap()) - m_site.tilemapMode(TilemapMode::Tiles); - else - m_site.tilemapMode(TilemapMode::Pixels); - if (originalSiteTilemapMode == TilemapMode::Pixels) - m_site.tilesetMode(TilesetMode::Auto); + reproduceAllTransformationsWithInnerCmds(); } @@ -919,20 +806,12 @@ void PixelsMovement::stampImage(bool finalStamp) stampExtraCelImage(); } - m_initialMask0->replace(*initialMask0.get()); - m_initialMask->replace(*initialMask.get()); - m_currentMask->replace(*currentMask.get()); - m_initialData.bounds(initialData.get()->bounds()); - m_currentData.bounds(currentData.get()->bounds()); - m_site.tilesetMode(originalSiteTilesetMode); currentCel = m_site.cel(); if (currentCel && (m_site.layer() != currentCel->layer() || m_site.frame() != currentCel->frame())) { m_site.layer(currentCel->layer()); m_site.frame(currentCel->frame()); - m_site.tilemapMode(originalSiteTilemapMode); - m_site.tilesetMode(originalSiteTilesetMode); redrawExtraImage(); } } @@ -1109,7 +988,6 @@ void PixelsMovement::redrawExtraImage(Transformation* transformation) if (!m_extraCel) m_extraCel.reset(new ExtraCel); - ASSERT(!(m_site.tilemapMode() == TilemapMode::Tiles && !m_site.layer()->isTilemap())); gfx::Rect bounds = transformation->transformedBounds(); if (!bounds.isEmpty()) { @@ -1117,7 +995,6 @@ void PixelsMovement::redrawExtraImage(Transformation* transformation) if (m_site.tilemapMode() == TilemapMode::Tiles) { // Transforming tiles extraCelSize = m_site.grid().canvasToTile(bounds).size(); - bounds = m_site.grid().alignBounds(bounds); } else { // Transforming pixels @@ -1164,7 +1041,7 @@ void PixelsMovement::drawImage( auto corners = transformation.transformedCorners(); gfx::Rect bounds = corners.bounds(transformation.cornerThick()); - if (m_site.tilemapMode() == TilemapMode::Tiles && m_site.layer()->isTilemap()) { + if (m_site.tilemapMode() == TilemapMode::Tiles) { dst->setMaskColor(doc::notile); dst->clear(dst->maskColor()); @@ -1525,17 +1402,10 @@ void PixelsMovement::reproduceAllTransformationsWithInnerCmds() m_document->setMask(m_initialMask0.get()); m_initialMask->copyFrom(m_initialMask0.get()); - if (m_site.layer()->isTilemap() && m_site.tilemapMode() == TilemapMode::Tiles) { - m_originalImage.reset( - new_tilemap_from_mask( - m_site, m_initialMask0.get())); - } - else { - m_originalImage.reset( + m_originalImage.reset( new_image_from_mask( - m_site, m_initialMask0.get(), + m_site, m_initialMask.get(), Preferences::instance().experimental.newBlend())); - } for (const InnerCmd& c : m_innerCmds) { switch (c.type) { diff --git a/src/app/ui/editor/pixels_movement.h b/src/app/ui/editor/pixels_movement.h index 2b42fba95..b5b13d1d8 100644 --- a/src/app/ui/editor/pixels_movement.h +++ b/src/app/ui/editor/pixels_movement.h @@ -159,15 +159,6 @@ namespace app { const double angle); CelList getEditableCels(); void reproduceAllTransformationsWithInnerCmds(); - - void alignMasksAndTransformData(const Mask* initialMask0, - const Mask* initialMask, - const Mask* currentMask, - const Transformation* initialData, - const Transformation* currentData, - const doc::Grid& grid, - const gfx::SizeF& initialScaleRatio); - #if _DEBUG void dumpInnerCmds(); #endif diff --git a/src/doc/grid.cpp b/src/doc/grid.cpp index 24f884c61..4f6db0ed4 100644 --- a/src/doc/grid.cpp +++ b/src/doc/grid.cpp @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (c) 2019-2022 Igara Studio S.A. +// Copyright (c) 2019-2021 Igara Studio S.A. // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -13,7 +13,6 @@ #include "doc/image.h" #include "doc/image_impl.h" #include "doc/image_ref.h" -#include "doc/mask.h" #include "doc/primitives.h" #include "gfx/point.h" #include "gfx/rect.h" @@ -184,49 +183,4 @@ std::vector Grid::tilesInCanvasRegion(const gfx::Region& rgn) const return result; } -Mask Grid::makeAlignedMask(const Mask* mask) const -{ - // Fact: the newBounds will be always larger or equal than oldBounds - Mask maskOutput; - if (mask->isFrozen()) { - ASSERT(false); - return maskOutput; - } - gfx::Rect oldBounds = mask->bounds(); - gfx::Rect newBounds = alignBounds(mask->bounds()); - ASSERT(newBounds.w > 0 && newBounds.h > 0); - ImageRef newBitmap; - if (!mask->bitmap()) { - maskOutput.replace(newBounds); - return maskOutput; - } - - newBitmap.reset(Image::create(IMAGE_BITMAP, newBounds.w, newBounds.h)); - maskOutput.freeze(); - maskOutput.reserve(newBounds); - - const LockImageBits bits(mask->bitmap()); - typename LockImageBits::const_iterator it = bits.begin(); - // We must travel thought the old bitmap and masking the new bitmap - gfx::Point previousPoint(std::numeric_limits::max(), std::numeric_limits::max()); - for (int y=0; y < oldBounds.h; ++y) { - for (int x=0; x < oldBounds.w; ++x, ++it) { - ASSERT(it != bits.end()); - if (*it) { - gfx::Rect newBoundsTile = alignBounds(gfx::Rect(oldBounds.x + x, oldBounds.y + y, 1, 1)); - if (previousPoint != newBoundsTile.origin()) { - // Fill a tile region in the newBitmap - fill_rect(maskOutput.bitmap(), - gfx::Rect(newBoundsTile.x - newBounds.x, newBoundsTile.y - newBounds.y, - tileSize().w, tileSize().h), - 1); - previousPoint = newBoundsTile.origin(); - } - } - } - } - maskOutput.unfreeze(); - return maskOutput; -} - } // namespace doc diff --git a/src/doc/grid.h b/src/doc/grid.h index 5af8f4e2b..8c40b59c6 100644 --- a/src/doc/grid.h +++ b/src/doc/grid.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (c) 2019-2022 Igara Studio S.A. +// Copyright (c) 2019-2020 Igara Studio S.A. // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -15,8 +15,6 @@ namespace doc { - class Mask; - class Grid { public: Grid(const gfx::Size& sz = gfx::Size(16, 16)) @@ -67,18 +65,6 @@ namespace doc { // Returns an array of tile positions that are touching the given region in the canvas std::vector tilesInCanvasRegion(const gfx::Region& rgn) const; - // Returns a mask aligned to the current grid, starting from other not aligned mask - Mask makeAlignedMask(const Mask* mask) const; - - inline bool operator!=(const Grid& gridB) const { - return (this->tileSize() != gridB.tileSize() || - this->origin() != gridB.origin() || - this->tileOffset() != gridB.tileOffset() || - this->oddColOffset() != gridB.oddColOffset() || - this->oddRowOffset() != gridB.oddRowOffset() || - this->tileCenter() != gridB.tileCenter());// Perhaps this last condition isn't needed. - } - private: gfx::Size m_tileSize; gfx::Point m_origin;