Add user data to tiles (fix #3626)

Co-authored-by: David Capello <david@igara.com>
This commit is contained in:
Gaspar Capello 2022-12-16 18:01:01 -03:00 committed by David Capello
parent ea17eae524
commit 6d6dfb96a9
8 changed files with 68 additions and 20 deletions

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -20,12 +20,14 @@ namespace app {
namespace cmd {
AddTile::AddTile(doc::Tileset* tileset,
const doc::ImageRef& image)
const doc::ImageRef& image,
const doc::UserData& userData)
: WithTileset(tileset)
, WithImage(image.get())
, m_size(0)
, m_tileIndex(doc::notile)
, m_imageRef(image)
, m_userData(userData)
{
}
@ -36,6 +38,7 @@ AddTile::AddTile(doc::Tileset* tileset,
, m_size(0)
, m_tileIndex(ti)
, m_imageRef(nullptr)
, m_userData(tileset->getTileData(ti))
{
}
@ -51,7 +54,7 @@ void AddTile::onExecute()
}
else {
ASSERT(m_imageRef);
addTile(tileset, m_imageRef);
addTile(tileset, m_imageRef, m_userData);
m_imageRef.reset();
}
}
@ -78,7 +81,7 @@ void AddTile::onRedo()
m_imageRef.reset(read_image(m_stream));
ASSERT(m_imageRef);
addTile(tileset, m_imageRef);
addTile(tileset, m_imageRef, m_userData);
m_imageRef.reset();
m_stream.str(std::string());
@ -95,12 +98,14 @@ void AddTile::onFireNotifications()
->notifyTilesetChanged(tileset);
}
void AddTile::addTile(doc::Tileset* tileset, const doc::ImageRef& image)
void AddTile::addTile(doc::Tileset* tileset,
const doc::ImageRef& image,
const doc::UserData& userData)
{
if (m_tileIndex == doc::notile)
m_tileIndex = tileset->add(image);
m_tileIndex = tileset->add(image, userData);
else
tileset->insert(m_tileIndex, image);
tileset->insert(m_tileIndex, image, userData);
tileset->sprite()->incrementVersion();
tileset->incrementVersion();

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -13,6 +13,7 @@
#include "app/cmd/with_tileset.h"
#include "doc/image_ref.h"
#include "doc/tile.h"
#include "doc/user_data.h"
#include <sstream>
@ -27,8 +28,11 @@ namespace cmd {
, public WithTileset
, public WithImage {
public:
AddTile(doc::Tileset* tileset, const doc::ImageRef& image);
AddTile(doc::Tileset* tileset, const doc::tile_index ti);
AddTile(doc::Tileset* tileset,
const doc::ImageRef& image,
const doc::UserData& userData = UserData());
AddTile(doc::Tileset* tileset,
const doc::tile_index ti);
doc::tile_index tileIndex() const { return m_tileIndex; }
@ -38,17 +42,20 @@ namespace cmd {
void onRedo() override;
void onFireNotifications() override;
size_t onMemSize() const override {
// TODO add m_userData size
return sizeof(*this) + m_size;
}
private:
void addTile(doc::Tileset* tileset,
const doc::ImageRef& image);
const doc::ImageRef& image,
const doc::UserData& userData);
size_t m_size;
std::stringstream m_stream;
doc::tile_index m_tileIndex;
doc::ImageRef m_imageRef;
doc::UserData m_userData;
};
} // namespace cmd

View File

@ -138,6 +138,7 @@ protected:
sprite()->rgbMap(0))); // TODO first frame?
newTileset->set(idx, newTileImg);
newTileset->setTileData(idx, tileset->getTileData(idx));
}
jobProgress((float)progress / img_count);

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -889,14 +889,17 @@ void copy_tiles_in_tileset(
OPS_TRACE("copy_tiles_in_tileset beforeIndex=%d npicks=%d\n", beforeIndex, picks.picks());
std::vector<ImageRef> newTiles;
std::vector<UserData> newDatas;
for (int i=0; i<picks.size(); ++i) {
if (!picks[i])
continue;
else if (i >= 0 && i < tileset->size()) {
newTiles.emplace_back(Image::createCopy(tileset->get(i).get()));
newDatas.emplace_back(tileset->getTileData(i));
}
else {
newTiles.emplace_back(tileset->makeEmptyTile());
newDatas.emplace_back(UserData());
}
}
@ -921,8 +924,8 @@ void copy_tiles_in_tileset(
// "beforeIndex" with empty tiles
while (tileset->size() < i)
cmds->executeAndAdd(new cmd::AddTile(tileset, tileset->makeEmptyTile()));
tileset->insert(i, newTiles[j++]);
tileset->insert(i, newTiles[j], newDatas[j]);
j++;
cmds->executeAndAdd(new cmd::AddTile(tileset, i));
}
}

View File

@ -752,7 +752,7 @@ void ExpandCelCanvas::copySourceTilestToDestTileset()
for (tile_index i=0; i<srcTileset->size(); ++i) {
doc::copy_image(m_dstTileset->get(i).get(),
srcTileset->get(i).get());
m_dstTileset->setTileData(i, srcTileset->getTileData(i));
// To rehash the tileset
m_dstTileset->notifyTileContentChange(i);
}

View File

@ -534,8 +534,10 @@ void Sprite::replaceImage(ObjectId curImageId, const ImageRef& newImage)
for (Tileset* tileset : *tilesets()) {
for (tile_index i=0; i<tileset->size(); ++i) {
ImageRef image = tileset->get(i);
if (image && image->id() == curImageId)
if (image && image->id() == curImageId) {
// Change only the tile image (not its user data)
tileset->set(i, newImage);
}
}
}
}

View File

@ -27,6 +27,7 @@ Tileset::Tileset(Sprite* sprite,
, m_sprite(sprite)
, m_grid(grid)
, m_tiles(ntiles)
, m_datas(ntiles)
{
// The origin of tileset grids must be 0,0 (the origin is then
// specified by each cel position)
@ -64,6 +65,7 @@ Tileset* Tileset::MakeCopyWithSameImages(const Tileset* tileset)
ImageRef image = tileset->get(ti);
ASSERT(image);
copy->set(ti, image);
copy->setTileData(ti, tileset->getTileData(ti));
}
return copy.release();
}
@ -77,6 +79,7 @@ Tileset* Tileset::MakeCopyCopyingImages(const Tileset* tileset)
ASSERT(image);
// TODO can we avoid making a copy of this image
copy->set(ti, ImageRef(Image::createCopy(image.get())));
copy->setTileData(ti, tileset->getTileData(ti));
}
return copy.release();
}
@ -95,6 +98,7 @@ void Tileset::resize(const tile_index ntiles)
{
int oldSize = m_tiles.size();
m_tiles.resize(ntiles);
m_datas.resize(ntiles);
for (tile_index ti=oldSize; ti<ntiles; ++ti)
m_tiles[ti] = makeEmptyTile();
}
@ -102,6 +106,7 @@ void Tileset::resize(const tile_index ntiles)
void Tileset::remap(const Remap& remap)
{
Tiles tmp = m_tiles;
Datas tmpUD = m_datas;
// The notile cannot be remapped
ASSERT(remap[0] == 0);
@ -116,12 +121,19 @@ void Tileset::remap(const Remap& remap)
ASSERT(remap[ti] != notile);
m_tiles[remap[ti]] = tmp[ti];
m_datas[remap[ti]] = tmpUD[ti];
}
}
rehash();
}
void Tileset::setTileData(const tile_index ti,
const UserData& userData)
{
m_datas[ti] = userData;
}
void Tileset::set(const tile_index ti,
const ImageRef& image)
{
@ -144,7 +156,8 @@ void Tileset::set(const tile_index ti,
hashImage(ti, image);
}
tile_index Tileset::add(const ImageRef& image)
tile_index Tileset::add(const ImageRef& image,
const UserData& userData)
{
ASSERT(image);
ASSERT(image->width() == m_grid.tileSize().w);
@ -152,6 +165,7 @@ tile_index Tileset::add(const ImageRef& image)
preprocess_transparent_pixels(image.get());
m_tiles.push_back(image);
m_datas.push_back(userData);
const tile_index newIndex = tile_index(m_tiles.size()-1);
if (!m_hash.empty())
@ -160,7 +174,8 @@ tile_index Tileset::add(const ImageRef& image)
}
void Tileset::insert(const tile_index ti,
const ImageRef& image)
const ImageRef& image,
const UserData& userData)
{
ASSERT(image);
ASSERT(image->width() == m_grid.tileSize().w);
@ -175,6 +190,7 @@ void Tileset::insert(const tile_index ti,
ASSERT(ti >= 0 && ti <= m_tiles.size()+1);
preprocess_transparent_pixels(image.get());
m_tiles.insert(m_tiles.begin()+ti, image);
m_datas.insert(m_datas.begin()+ti, userData);
if (!m_hash.empty()) {
// Fix all indexes in the hash that are greater than "ti"
@ -194,6 +210,7 @@ void Tileset::erase(const tile_index ti)
//removeFromHash(ti, true);
m_tiles.erase(m_tiles.begin()+ti);
m_datas.erase(m_datas.begin()+ti);
rehash();
}

View File

@ -26,6 +26,7 @@ namespace doc {
class Tileset : public WithUserData {
public:
typedef std::vector<ImageRef> Tiles;
typedef std::vector<UserData> Datas;
typedef Tiles::iterator iterator;
typedef Tiles::const_iterator const_iterator;
@ -68,9 +69,20 @@ namespace doc {
void set(const tile_index ti,
const ImageRef& image);
tile_index add(const ImageRef& image);
UserData getTileData(const tile_index ti) const {
if (ti >= 0 && ti < size())
return m_datas[ti];
else
return UserData();
}
void setTileData(const tile_index ti,
const UserData& userData);
tile_index add(const ImageRef& image,
const UserData& userData = UserData());
void insert(const tile_index ti,
const ImageRef& image);
const ImageRef& image,
const UserData& userData = UserData());
void erase(const tile_index ti);
// Linked with an external file
@ -126,6 +138,7 @@ namespace doc {
Sprite* m_sprite;
Grid m_grid;
Tiles m_tiles;
Datas m_datas;
TilesetHashTable m_hash;
std::string m_name;
int m_baseIndex = 1;