mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-03 21:46:20 +00:00
Fix copying irregular areas of tiles in "tiles mode"
Now we can use the lasso tool in tiles mode, select an irregular (non-rectangular) area and move that area of tiles correctly.
This commit is contained in:
parent
5cd66b58f1
commit
726065164f
@ -1032,10 +1032,16 @@ void PixelsMovement::drawImage(
|
||||
dst->setMaskColor(doc::notile);
|
||||
dst->clear(dst->maskColor());
|
||||
|
||||
if (renderOriginalLayer && m_site.cel()) {
|
||||
doc::Grid grid = m_site.grid();
|
||||
dst->copy(m_site.cel()->image(),
|
||||
gfx::Clip(0, 0, grid.canvasToTile(bounds)));
|
||||
}
|
||||
|
||||
drawTransformedTilemap(
|
||||
transformation,
|
||||
dst, m_originalImage.get(),
|
||||
m_initialMask.get(), corners, pt);
|
||||
m_initialMask.get());
|
||||
}
|
||||
else {
|
||||
dst->setMaskColor(m_site.sprite()->transparentColor());
|
||||
@ -1163,11 +1169,31 @@ retry:; // In case that we don't have enough memory for RotSprite
|
||||
}
|
||||
}
|
||||
|
||||
static void merge_tilemaps(Image* dst, const Image* src, gfx::Clip area)
|
||||
{
|
||||
if (!area.clip(dst->width(), dst->height(), src->width(), src->height()))
|
||||
return;
|
||||
|
||||
ImageConstIterator<TilemapTraits> src_it(src, area.srcBounds(), area.src.x, area.src.y);
|
||||
ImageIterator<TilemapTraits> dst_it(dst, area.dstBounds(), area.dst.x, area.dst.y);
|
||||
|
||||
int end_x = area.dst.x+area.size.w;
|
||||
|
||||
for (int end_y=area.dst.y+area.size.h;
|
||||
area.dst.y<end_y;
|
||||
++area.dst.y, ++area.src.y) {
|
||||
for (int x=area.dst.x; x<end_x; ++x) {
|
||||
if (*src_it != doc::notile)
|
||||
*dst_it = *src_it;
|
||||
++src_it;
|
||||
++dst_it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PixelsMovement::drawTransformedTilemap(
|
||||
const Transformation& transformation,
|
||||
doc::Image* dst, const doc::Image* src, const doc::Mask* mask,
|
||||
const Transformation::Corners& corners,
|
||||
const gfx::PointF& leftTop)
|
||||
doc::Image* dst, const doc::Image* src, const doc::Mask* mask)
|
||||
{
|
||||
const int boxw = std::max(1, src->width()-2);
|
||||
const int boxh = std::max(1, src->height()-2);
|
||||
@ -1175,13 +1201,13 @@ void PixelsMovement::drawTransformedTilemap(
|
||||
// Function to copy a whole row of tiles (h=number of tiles in Y axis)
|
||||
auto draw_row =
|
||||
[dst, src, boxw](int y, int v, int h) {
|
||||
dst->copy(src, gfx::Clip(0, y, 0, v, 1, h));
|
||||
merge_tilemaps(dst, src, gfx::Clip(0, y, 0, v, 1, h));
|
||||
if (boxw) {
|
||||
const int u = std::min(1, src->width()-1);
|
||||
for (int x=1; x<dst->width()-1; x+=boxw)
|
||||
dst->copy(src, gfx::Clip(x, y, u, v, boxw, h));
|
||||
merge_tilemaps(dst, src, gfx::Clip(x, y, u, v, boxw, h));
|
||||
}
|
||||
dst->copy(src, gfx::Clip(dst->width()-1, y, src->width()-1, v, 1, h));
|
||||
merge_tilemaps(dst, src, gfx::Clip(dst->width()-1, y, src->width()-1, v, 1, h));
|
||||
};
|
||||
|
||||
draw_row(0, 0, 1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2020 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
|
||||
@ -140,7 +140,7 @@ namespace app {
|
||||
void redrawCurrentMask();
|
||||
void drawImage(
|
||||
const Transformation& transformation,
|
||||
doc::Image* dst, const gfx::PointF& pos,
|
||||
doc::Image* dst, const gfx::PointF& pt,
|
||||
const bool renderOriginalLayer);
|
||||
void drawMask(doc::Mask* dst, bool shrink);
|
||||
void drawParallelogram(
|
||||
@ -150,9 +150,7 @@ namespace app {
|
||||
const gfx::PointF& leftTop);
|
||||
void drawTransformedTilemap(
|
||||
const Transformation& transformation,
|
||||
doc::Image* dst, const doc::Image* src, const doc::Mask* mask,
|
||||
const Transformation::Corners& corners,
|
||||
const gfx::PointF& leftTop);
|
||||
doc::Image* dst, const doc::Image* src, const doc::Mask* mask);
|
||||
void updateDocumentMask();
|
||||
void hideDocumentMask();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2020 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
|
||||
@ -123,6 +123,10 @@ doc::Image* new_tilemap_from_mask(const Site& site,
|
||||
ASSERT(srcSprite);
|
||||
ASSERT(srcMask);
|
||||
|
||||
const Cel* srcCel = site.cel();
|
||||
if (!srcCel)
|
||||
return nullptr;
|
||||
|
||||
const doc::Grid grid = site.grid();
|
||||
const Image* srcMaskBitmap = srcMask->bitmap();
|
||||
const gfx::Rect& srcBounds = srcMask->bounds();
|
||||
@ -141,28 +145,32 @@ doc::Image* new_tilemap_from_mask(const Site& site,
|
||||
// Clear the new tilemap
|
||||
clear_image(dst.get(), dst->maskColor());
|
||||
|
||||
if (auto cel = site.cel()) {
|
||||
// Just copy tilemap data
|
||||
dst->copy(cel->image(), gfx::Clip(0, 0, srcTilesBounds));
|
||||
}
|
||||
|
||||
// Copy the masked zones
|
||||
if (srcMaskBitmap) {
|
||||
// Copy active layer with mask
|
||||
const LockImageBits<BitmapTraits> maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h));
|
||||
LockImageBits<BitmapTraits>::const_iterator mask_it = maskBits.begin();
|
||||
auto mask_it = maskBits.begin();
|
||||
const gfx::Point originPt = grid.canvasToTile(srcBounds.origin());
|
||||
|
||||
for (int v=0; v<srcBounds.h; ++v) {
|
||||
for (int u=0; u<srcBounds.w; ++u, ++mask_it) {
|
||||
ASSERT(mask_it != maskBits.end());
|
||||
if (!*mask_it) {
|
||||
gfx::Point pt = grid.canvasToTile(gfx::Point(srcBounds.x+u, srcBounds.y+v));
|
||||
if (dst->bounds().contains(pt))
|
||||
dst->putPixel(pt.x, pt.y, dst->maskColor());
|
||||
if (*mask_it) {
|
||||
gfx::Point srcPt = grid.canvasToTile(gfx::Point(srcBounds.x+u, srcBounds.y+v));
|
||||
gfx::Point dstPt = srcPt - originPt;
|
||||
|
||||
if (dst->bounds().contains(dstPt) &&
|
||||
srcCel->image()->bounds().contains(srcPt)) {
|
||||
dst->putPixel(dstPt.x, dstPt.y, srcCel->image()->getPixel(srcPt.x, srcPt.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Just copy tilemap data
|
||||
dst->copy(srcCel->image(), gfx::Clip(0, 0, srcTilesBounds));
|
||||
}
|
||||
|
||||
return dst.release();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user