Skip to content

Commit

Permalink
Revert "Fix multi layer movement in tilemap mode (fix #3144)"
Browse files Browse the repository at this point in the history
This reverts commit bc050e8.
  • Loading branch information
dacap committed Mar 15, 2022
1 parent 3215051 commit c08dc44
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 223 deletions.
174 changes: 22 additions & 152 deletions src/app/ui/editor/pixels_movement.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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); }
Expand All @@ -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;
}

Expand Down Expand Up @@ -714,7 +712,6 @@ void PixelsMovement::moveImage(const gfx::PointF& pos, MoveModifier moveModifier
void PixelsMovement::getDraggedImageCopy(std::unique_ptr<Image>& outputImage,
std::unique_ptr<Mask>& outputMask)
{
ASSERT(!(m_site.tilemapMode() == TilemapMode::Tiles && !m_site.layer()->isTilemap()));
gfx::Rect bounds = m_currentData.transformedBounds();
if (bounds.isEmpty())
return;
Expand Down Expand Up @@ -762,29 +759,6 @@ void PixelsMovement::getDraggedImageCopy(std::unique_ptr<Image>& 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);
Expand Down Expand Up @@ -817,122 +791,27 @@ 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<Mask> initialMask0(new Mask(*m_initialMask0.get()));
std::unique_ptr<Mask> initialMask(new Mask(*m_initialMask.get()));
std::unique_ptr<Mask> currentMask(new Mask(*m_currentMask.get()));
std::unique_ptr<Transformation> initialData(new Transformation(m_initialData));
std::unique_ptr<Transformation> 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();
}

redrawExtraImage();
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();
}
}
Expand Down Expand Up @@ -1109,15 +988,13 @@ 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()) {
gfx::Size extraCelSize;
if (m_site.tilemapMode() == TilemapMode::Tiles) {
// Transforming tiles
extraCelSize = m_site.grid().canvasToTile(bounds).size();
bounds = m_site.grid().alignBounds(bounds);
}
else {
// Transforming pixels
Expand Down Expand Up @@ -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());

Expand Down Expand Up @@ -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) {
Expand Down
9 changes: 0 additions & 9 deletions src/app/ui/editor/pixels_movement.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
48 changes: 1 addition & 47 deletions src/doc/grid.cpp
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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"
Expand Down Expand Up @@ -184,49 +183,4 @@ std::vector<gfx::Point> 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<BitmapTraits> bits(mask->bitmap());
typename LockImageBits<BitmapTraits>::const_iterator it = bits.begin();
// We must travel thought the old bitmap and masking the new bitmap
gfx::Point previousPoint(std::numeric_limits<int>::max(), std::numeric_limits<int>::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
16 changes: 1 addition & 15 deletions src/doc/grid.h
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -15,8 +15,6 @@

namespace doc {

class Mask;

class Grid {
public:
Grid(const gfx::Size& sz = gfx::Size(16, 16))
Expand Down Expand Up @@ -67,18 +65,6 @@ namespace doc {
// Returns an array of tile positions that are touching the given region in the canvas
std::vector<gfx::Point> 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;
Expand Down

0 comments on commit c08dc44

Please sign in to comment.