mirror of https://github.com/aseprite/aseprite.git
Compare commits
6 Commits
5242107820
...
cc15775e14
Author | SHA1 | Date |
---|---|---|
|
cc15775e14 | |
|
abd4caeac8 | |
|
11df0bc877 | |
|
41e5097c33 | |
|
cf290b7679 | |
|
d7b2faca6d |
2
laf
2
laf
|
@ -1 +1 @@
|
|||
Subproject commit de781a5066732d700ac4520ee5fc9034e92875ad
|
||||
Subproject commit 39706c11063fb53cf4c8e865102c6f71e2606906
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -15,11 +15,7 @@
|
|||
#include "app/doc_event.h"
|
||||
#include "base/serialization.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/cel_data_io.h"
|
||||
#include "doc/cel_io.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/subobjects_io.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
||||
|
@ -27,7 +23,7 @@ using namespace base::serialization;
|
|||
using namespace base::serialization::little_endian;
|
||||
using namespace doc;
|
||||
|
||||
AddCel::AddCel(Layer* layer, Cel* cel) : WithLayer(layer), WithCel(cel), m_size(0)
|
||||
AddCel::AddCel(Layer* layer, Cel* cel) : WithLayer(layer), WithCel(cel)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -48,41 +44,20 @@ void AddCel::onUndo()
|
|||
ASSERT(layer);
|
||||
ASSERT(cel);
|
||||
|
||||
// Save the CelData only if the cel isn't linked
|
||||
bool has_data = (cel->links() == 0);
|
||||
write8(m_stream, has_data ? 1 : 0);
|
||||
if (has_data) {
|
||||
write_image(m_stream, cel->image());
|
||||
write_celdata(m_stream, cel->data());
|
||||
}
|
||||
write_cel(m_stream, cel);
|
||||
m_size = size_t(m_stream.tellp());
|
||||
|
||||
// We must suspend the cel after removing the cel, we cannot trigger
|
||||
// onBeforeRemoveCel() with a cel without ID.
|
||||
removeCel(layer, cel);
|
||||
m_suspendedCel.suspend(cel);
|
||||
}
|
||||
|
||||
void AddCel::onRedo()
|
||||
{
|
||||
Layer* layer = this->layer();
|
||||
Cel* cel = m_suspendedCel.restore();
|
||||
ASSERT(layer);
|
||||
|
||||
SubObjectsFromSprite io(layer->sprite());
|
||||
bool has_data = (read8(m_stream) != 0);
|
||||
if (has_data) {
|
||||
ImageRef image(read_image(m_stream));
|
||||
io.addImageRef(image);
|
||||
|
||||
CelDataRef celdata(read_celdata(m_stream, &io));
|
||||
io.addCelDataRef(celdata);
|
||||
}
|
||||
Cel* cel = read_cel(m_stream, &io);
|
||||
ASSERT(cel);
|
||||
|
||||
addCel(layer, cel);
|
||||
|
||||
m_stream.str(std::string());
|
||||
m_stream.clear();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void AddCel::addCel(Layer* layer, Cel* cel)
|
||||
|
@ -111,8 +86,6 @@ void AddCel::removeCel(Layer* layer, Cel* cel)
|
|||
layer->incrementVersion();
|
||||
|
||||
doc->notify_observers<DocEvent&>(&DocObserver::onAfterRemoveCel, ev);
|
||||
|
||||
delete cel;
|
||||
}
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -11,11 +12,10 @@
|
|||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_cel.h"
|
||||
#include "app/cmd/with_layer.h"
|
||||
|
||||
#include <sstream>
|
||||
#include "app/cmd/with_suspended.h"
|
||||
#include "doc/cel.h"
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
class Layer;
|
||||
} // namespace doc
|
||||
|
||||
|
@ -32,14 +32,13 @@ protected:
|
|||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
void onRedo() override;
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_size; }
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_suspendedCel.size(); }
|
||||
|
||||
private:
|
||||
void addCel(Layer* layer, Cel* cel);
|
||||
void removeCel(Layer* layer, Cel* cel);
|
||||
|
||||
size_t m_size;
|
||||
std::stringstream m_stream;
|
||||
WithSuspended<doc::Cel*> m_suspendedCel;
|
||||
};
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#include "app/doc.h"
|
||||
#include "app/doc_event.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/layer_io.h"
|
||||
#include "doc/subobjects_io.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
||||
|
@ -24,7 +22,6 @@ AddLayer::AddLayer(Layer* group, Layer* newLayer, Layer* afterThis)
|
|||
: m_group(group)
|
||||
, m_newLayer(newLayer)
|
||||
, m_afterThis(afterThis)
|
||||
, m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -41,25 +38,19 @@ void AddLayer::onUndo()
|
|||
{
|
||||
Layer* group = m_group.layer();
|
||||
Layer* layer = m_newLayer.layer();
|
||||
|
||||
write_layer(m_stream, layer);
|
||||
m_size = size_t(m_stream.tellp());
|
||||
ASSERT(layer);
|
||||
|
||||
removeLayer(group, layer);
|
||||
m_suspendedLayer.suspend(layer);
|
||||
}
|
||||
|
||||
void AddLayer::onRedo()
|
||||
{
|
||||
Layer* group = m_group.layer();
|
||||
SubObjectsFromSprite io(group->sprite());
|
||||
Layer* newLayer = read_layer(m_stream, &io);
|
||||
Layer* newLayer = m_suspendedLayer.restore();
|
||||
Layer* afterThis = m_afterThis.layer();
|
||||
|
||||
addLayer(group, newLayer, afterThis);
|
||||
|
||||
m_stream.str(std::string());
|
||||
m_stream.clear();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void AddLayer::addLayer(Layer* group, Layer* newLayer, Layer* afterThis)
|
||||
|
@ -88,8 +79,6 @@ void AddLayer::removeLayer(Layer* group, Layer* layer)
|
|||
group->sprite()->incrementVersion();
|
||||
|
||||
doc->notify_observers<DocEvent&>(&DocObserver::onAfterRemoveLayer, ev);
|
||||
|
||||
delete layer;
|
||||
}
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (c) 2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -10,12 +11,8 @@
|
|||
|
||||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_layer.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace doc {
|
||||
class Layer;
|
||||
}
|
||||
#include "app/cmd/with_suspended.h"
|
||||
#include "doc/layer.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
using namespace doc;
|
||||
|
@ -28,7 +25,7 @@ protected:
|
|||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
void onRedo() override;
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_size; }
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_suspendedLayer.size(); }
|
||||
|
||||
private:
|
||||
void addLayer(Layer* group, Layer* newLayer, Layer* afterThis);
|
||||
|
@ -37,8 +34,7 @@ private:
|
|||
WithLayer m_group;
|
||||
WithLayer m_newLayer;
|
||||
WithLayer m_afterThis;
|
||||
size_t m_size;
|
||||
std::stringstream m_stream;
|
||||
WithSuspended<doc::Layer*> m_suspendedLayer;
|
||||
};
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -11,30 +11,21 @@
|
|||
#include "app/cmd/add_palette.h"
|
||||
|
||||
#include "doc/palette.h"
|
||||
#include "doc/palette_io.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
AddPalette::AddPalette(Sprite* sprite, Palette* pal)
|
||||
: WithSprite(sprite)
|
||||
, m_size(0)
|
||||
, m_frame(pal->frame())
|
||||
AddPalette::AddPalette(Sprite* sprite, Palette* pal) : WithSprite(sprite), m_palette(*pal)
|
||||
{
|
||||
write_palette(m_stream, pal);
|
||||
m_size = size_t(m_stream.tellp());
|
||||
}
|
||||
|
||||
void AddPalette::onExecute()
|
||||
{
|
||||
m_stream.seekp(0);
|
||||
|
||||
Sprite* sprite = this->sprite();
|
||||
Palette* pal = read_palette(m_stream);
|
||||
|
||||
sprite->setPalette(pal, true);
|
||||
sprite->setPalette(&m_palette, true);
|
||||
sprite->incrementVersion();
|
||||
}
|
||||
|
||||
|
@ -42,7 +33,7 @@ void AddPalette::onUndo()
|
|||
{
|
||||
Sprite* sprite = this->sprite();
|
||||
|
||||
sprite->deletePalette(m_frame);
|
||||
sprite->deletePalette(m_palette.frame());
|
||||
sprite->incrementVersion();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -10,9 +11,7 @@
|
|||
|
||||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_sprite.h"
|
||||
#include "doc/frame.h"
|
||||
|
||||
#include <sstream>
|
||||
#include "doc/palette.h"
|
||||
|
||||
namespace doc {
|
||||
class Palette;
|
||||
|
@ -30,12 +29,10 @@ public:
|
|||
protected:
|
||||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_size; }
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_palette.getMemSize(); }
|
||||
|
||||
private:
|
||||
size_t m_size;
|
||||
std::stringstream m_stream;
|
||||
frame_t m_frame;
|
||||
Palette m_palette;
|
||||
};
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -14,14 +14,13 @@
|
|||
#include "app/doc.h"
|
||||
#include "app/doc_event.h"
|
||||
#include "doc/slice.h"
|
||||
#include "doc/slice_io.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
AddSlice::AddSlice(Sprite* sprite, Slice* slice) : WithSprite(sprite), WithSlice(slice), m_size(0)
|
||||
AddSlice::AddSlice(Sprite* sprite, Slice* slice) : WithSprite(sprite), WithSlice(slice)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -37,22 +36,17 @@ void AddSlice::onUndo()
|
|||
{
|
||||
Sprite* sprite = this->sprite();
|
||||
Slice* slice = this->slice();
|
||||
write_slice(m_stream, slice);
|
||||
m_size = size_t(m_stream.tellp());
|
||||
|
||||
removeSlice(sprite, slice);
|
||||
m_suspendedSlice.suspend(slice);
|
||||
}
|
||||
|
||||
void AddSlice::onRedo()
|
||||
{
|
||||
Sprite* sprite = this->sprite();
|
||||
Slice* slice = read_slice(m_stream);
|
||||
Slice* slice = m_suspendedSlice.restore();
|
||||
|
||||
addSlice(sprite, slice);
|
||||
|
||||
m_stream.str(std::string());
|
||||
m_stream.clear();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void AddSlice::addSlice(Sprite* sprite, Slice* slice)
|
||||
|
@ -77,7 +71,6 @@ void AddSlice::removeSlice(Sprite* sprite, Slice* slice)
|
|||
|
||||
sprite->slices().remove(slice);
|
||||
sprite->incrementVersion();
|
||||
delete slice;
|
||||
}
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -12,8 +12,8 @@
|
|||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_slice.h"
|
||||
#include "app/cmd/with_sprite.h"
|
||||
|
||||
#include <sstream>
|
||||
#include "app/cmd/with_suspended.h"
|
||||
#include "doc/slice.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
using namespace doc;
|
||||
|
@ -28,14 +28,13 @@ protected:
|
|||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
void onRedo() override;
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_size; }
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_suspendedSlice.size(); }
|
||||
|
||||
private:
|
||||
void addSlice(Sprite* sprite, Slice* slice);
|
||||
void removeSlice(Sprite* sprite, Slice* slice);
|
||||
|
||||
size_t m_size;
|
||||
std::stringstream m_stream;
|
||||
WithSuspended<doc::Slice*> m_suspendedSlice;
|
||||
};
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -15,13 +15,12 @@
|
|||
#include "app/doc_event.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tag.h"
|
||||
#include "doc/tag_io.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
AddTag::AddTag(Sprite* sprite, Tag* tag) : WithSprite(sprite), WithTag(tag), m_size(0)
|
||||
AddTag::AddTag(Sprite* sprite, Tag* tag) : WithSprite(sprite), WithTag(tag)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -45,8 +44,6 @@ void AddTag::onUndo()
|
|||
{
|
||||
Sprite* sprite = this->sprite();
|
||||
Tag* tag = this->tag();
|
||||
write_tag(m_stream, tag);
|
||||
m_size = size_t(m_stream.tellp());
|
||||
|
||||
// Notify observers about the new frame.
|
||||
{
|
||||
|
@ -59,21 +56,18 @@ void AddTag::onUndo()
|
|||
|
||||
sprite->tags().remove(tag);
|
||||
sprite->incrementVersion();
|
||||
delete tag;
|
||||
|
||||
m_suspendedTag.suspend(tag);
|
||||
}
|
||||
|
||||
void AddTag::onRedo()
|
||||
{
|
||||
Sprite* sprite = this->sprite();
|
||||
Tag* tag = read_tag(m_stream);
|
||||
Tag* tag = m_suspendedTag.restore();
|
||||
|
||||
sprite->tags().add(tag);
|
||||
sprite->incrementVersion();
|
||||
|
||||
m_stream.str(std::string());
|
||||
m_stream.clear();
|
||||
m_size = 0;
|
||||
|
||||
// Notify observers about the new frame.
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
DocEvent ev(doc);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -11,9 +11,9 @@
|
|||
|
||||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_sprite.h"
|
||||
#include "app/cmd/with_suspended.h"
|
||||
#include "app/cmd/with_tag.h"
|
||||
|
||||
#include <sstream>
|
||||
#include "doc/tag.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
using namespace doc;
|
||||
|
@ -28,11 +28,10 @@ protected:
|
|||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
void onRedo() override;
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_size; }
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_suspendedTag.size(); }
|
||||
|
||||
private:
|
||||
size_t m_size;
|
||||
std::stringstream m_stream;
|
||||
WithSuspended<doc::Tag*> m_suspendedTag;
|
||||
};
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
@ -11,7 +11,6 @@
|
|||
#include "app/cmd/add_tile.h"
|
||||
|
||||
#include "app/doc.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tileset.h"
|
||||
#include "doc/tilesets.h"
|
||||
|
@ -20,8 +19,6 @@ namespace app { namespace cmd {
|
|||
|
||||
AddTile::AddTile(doc::Tileset* tileset, 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)
|
||||
|
@ -30,10 +27,8 @@ AddTile::AddTile(doc::Tileset* tileset, const doc::ImageRef& image, const doc::U
|
|||
|
||||
AddTile::AddTile(doc::Tileset* tileset, const doc::tile_index ti)
|
||||
: WithTileset(tileset)
|
||||
, WithImage(tileset->get(ti).get())
|
||||
, m_size(0)
|
||||
, m_tileIndex(ti)
|
||||
, m_imageRef(nullptr)
|
||||
, m_imageRef(tileset->get(ti))
|
||||
, m_userData(tileset->getTileData(ti))
|
||||
{
|
||||
}
|
||||
|
@ -44,14 +39,11 @@ void AddTile::onExecute()
|
|||
ASSERT(tileset);
|
||||
|
||||
if (m_tileIndex != doc::notile) {
|
||||
ASSERT(!m_imageRef);
|
||||
tileset->sprite()->incrementVersion();
|
||||
tileset->incrementVersion();
|
||||
}
|
||||
else {
|
||||
ASSERT(m_imageRef);
|
||||
addTile(tileset, m_imageRef, m_userData);
|
||||
m_imageRef.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,8 +52,9 @@ void AddTile::onUndo()
|
|||
doc::Tileset* tileset = this->tileset();
|
||||
ASSERT(tileset);
|
||||
|
||||
write_image(m_stream, image());
|
||||
m_size = size_t(m_stream.tellp());
|
||||
ASSERT(m_imageRef);
|
||||
m_suspendedImage.suspend(m_imageRef);
|
||||
m_imageRef.reset();
|
||||
|
||||
tileset->erase(m_tileIndex);
|
||||
|
||||
|
@ -74,15 +67,10 @@ void AddTile::onRedo()
|
|||
doc::Tileset* tileset = this->tileset();
|
||||
|
||||
ASSERT(!m_imageRef);
|
||||
m_imageRef.reset(read_image(m_stream));
|
||||
m_imageRef = m_suspendedImage.restore();
|
||||
ASSERT(m_imageRef);
|
||||
|
||||
addTile(tileset, m_imageRef, m_userData);
|
||||
m_imageRef.reset();
|
||||
|
||||
m_stream.str(std::string());
|
||||
m_stream.clear();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void AddTile::onFireNotifications()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
@ -9,14 +9,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_image.h"
|
||||
#include "app/cmd/with_suspended.h"
|
||||
#include "app/cmd/with_tileset.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/tile.h"
|
||||
#include "doc/user_data.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace doc {
|
||||
class Tileset;
|
||||
}
|
||||
|
@ -24,12 +22,9 @@ class Tileset;
|
|||
namespace app { namespace cmd {
|
||||
|
||||
class AddTile : public Cmd,
|
||||
public WithTileset,
|
||||
public WithImage {
|
||||
public WithTileset {
|
||||
public:
|
||||
AddTile(doc::Tileset* tileset,
|
||||
const doc::ImageRef& image,
|
||||
const doc::UserData& userData = UserData());
|
||||
AddTile(doc::Tileset* tileset, const doc::ImageRef& image, const doc::UserData& userData = {});
|
||||
AddTile(doc::Tileset* tileset, const doc::tile_index ti);
|
||||
|
||||
doc::tile_index tileIndex() const { return m_tileIndex; }
|
||||
|
@ -42,14 +37,13 @@ protected:
|
|||
size_t onMemSize() const override
|
||||
{
|
||||
// TODO add m_userData size
|
||||
return sizeof(*this) + m_size;
|
||||
return sizeof(*this) + m_suspendedImage.size();
|
||||
}
|
||||
|
||||
private:
|
||||
void addTile(doc::Tileset* tileset, const doc::ImageRef& image, const doc::UserData& userData);
|
||||
|
||||
size_t m_size;
|
||||
std::stringstream m_stream;
|
||||
WithSuspended<doc::ImageRef> m_suspendedImage;
|
||||
doc::tile_index m_tileIndex;
|
||||
doc::ImageRef m_imageRef;
|
||||
doc::UserData m_userData;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
@ -11,9 +11,7 @@
|
|||
#include "app/cmd/add_tileset.h"
|
||||
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/subobjects_io.h"
|
||||
#include "doc/tileset.h"
|
||||
#include "doc/tileset_io.h"
|
||||
#include "doc/tilesets.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
@ -23,7 +21,6 @@ using namespace doc;
|
|||
AddTileset::AddTileset(doc::Sprite* sprite, doc::Tileset* tileset)
|
||||
: WithSprite(sprite)
|
||||
, WithTileset(tileset)
|
||||
, m_size(0)
|
||||
, m_tilesetIndex(-1)
|
||||
{
|
||||
}
|
||||
|
@ -31,7 +28,6 @@ AddTileset::AddTileset(doc::Sprite* sprite, doc::Tileset* tileset)
|
|||
AddTileset::AddTileset(doc::Sprite* sprite, const doc::tileset_index tsi)
|
||||
: WithSprite(sprite)
|
||||
, WithTileset(sprite->tilesets()->get(tsi))
|
||||
, m_size(0)
|
||||
, m_tilesetIndex(tsi)
|
||||
{
|
||||
}
|
||||
|
@ -46,28 +42,20 @@ void AddTileset::onExecute()
|
|||
void AddTileset::onUndo()
|
||||
{
|
||||
doc::Tileset* tileset = this->tileset();
|
||||
write_tileset(m_stream, tileset);
|
||||
m_size = size_t(m_stream.tellp());
|
||||
m_suspendedTileset.suspend(tileset);
|
||||
|
||||
doc::Sprite* sprite = this->sprite();
|
||||
sprite->tilesets()->erase(m_tilesetIndex);
|
||||
|
||||
sprite->incrementVersion();
|
||||
sprite->tilesets()->incrementVersion();
|
||||
|
||||
delete tileset;
|
||||
}
|
||||
|
||||
void AddTileset::onRedo()
|
||||
{
|
||||
auto sprite = this->sprite();
|
||||
doc::Tileset* tileset = read_tileset(m_stream, sprite);
|
||||
doc::Tileset* tileset = m_suspendedTileset.restore();
|
||||
|
||||
addTileset(tileset);
|
||||
|
||||
m_stream.str(std::string());
|
||||
m_stream.clear();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void AddTileset::addTileset(doc::Tileset* tileset)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
@ -10,10 +10,10 @@
|
|||
|
||||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_sprite.h"
|
||||
#include "app/cmd/with_suspended.h"
|
||||
#include "app/cmd/with_tileset.h"
|
||||
#include "doc/tile.h"
|
||||
|
||||
#include <sstream>
|
||||
#include "doc/tileset.h"
|
||||
|
||||
namespace doc {
|
||||
class Tileset;
|
||||
|
@ -34,13 +34,12 @@ protected:
|
|||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
void onRedo() override;
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_size; }
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_suspendedTileset.size(); }
|
||||
|
||||
private:
|
||||
void addTileset(doc::Tileset* tileset);
|
||||
|
||||
size_t m_size;
|
||||
std::stringstream m_stream;
|
||||
WithSuspended<doc::Tileset*> m_suspendedTileset;
|
||||
doc::tileset_index m_tilesetIndex;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2023 Igara Studio S.A.
|
||||
// Copyright (C) 2023-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -14,10 +14,8 @@
|
|||
#include "doc/cel.h"
|
||||
#include "doc/cels_range.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/subobjects_io.h"
|
||||
#include "doc/tilesets.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include "app/cmd/with_sprite.h"
|
||||
#include "doc/image_ref.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace app { namespace cmd {
|
||||
using namespace doc;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2021 Igara Studio S.A.
|
||||
// Copyright (C) 2021-2025 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
@ -14,7 +14,6 @@
|
|||
#include "doc/layer_tilemap.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tileset.h"
|
||||
#include "doc/tileset_io.h"
|
||||
#include "doc/tilesets.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
@ -40,16 +39,11 @@ void ReplaceTileset::onExecute()
|
|||
m_newTileset = nullptr;
|
||||
}
|
||||
else {
|
||||
restoreTileset = doc::read_tileset(m_stream, spr, true);
|
||||
restoreTileset = m_suspendedTileset.restore();
|
||||
}
|
||||
|
||||
m_stream.str(std::string());
|
||||
m_stream.clear();
|
||||
doc::write_tileset(m_stream, actualTileset);
|
||||
m_size = size_t(m_stream.tellp());
|
||||
|
||||
replaceTileset(restoreTileset);
|
||||
delete actualTileset;
|
||||
m_suspendedTileset.suspend(actualTileset);
|
||||
}
|
||||
|
||||
void ReplaceTileset::replaceTileset(Tileset* newTileset)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2021 Igara Studio S.A.
|
||||
// Copyright (C) 2021-2025 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
@ -10,10 +10,9 @@
|
|||
|
||||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_sprite.h"
|
||||
#include "app/cmd/with_suspended.h"
|
||||
#include "doc/tileset.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
||||
class ReplaceTileset : public Cmd,
|
||||
|
@ -25,15 +24,14 @@ protected:
|
|||
void onExecute() override;
|
||||
void onUndo() override { onExecute(); }
|
||||
void onRedo() override { onExecute(); }
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_size; }
|
||||
size_t onMemSize() const override { return sizeof(*this) + m_suspendedTileset.size(); }
|
||||
|
||||
private:
|
||||
void replaceTileset(doc::Tileset* newTileset);
|
||||
|
||||
doc::tileset_index m_tsi;
|
||||
doc::Tileset* m_newTileset;
|
||||
std::stringstream m_stream;
|
||||
size_t m_size = 0;
|
||||
WithSuspended<doc::Tileset*> m_suspendedTileset;
|
||||
};
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
|
|
@ -12,11 +12,9 @@
|
|||
|
||||
#include "doc/cel.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/subobjects_io.h"
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include "app/cmd/with_cel.h"
|
||||
#include "doc/cel_data.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace app { namespace cmd {
|
||||
using namespace doc;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -13,7 +13,6 @@
|
|||
#include "app/cmd/with_document.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace doc {
|
||||
class Mask;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2025 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_CMD_WITH_SUSPEND_H_INCLUDED
|
||||
#define APP_CMD_WITH_SUSPEND_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/object.h"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace app { namespace cmd {
|
||||
|
||||
// Auxiliary class to keep a doc::Object in memory but without IDs,
|
||||
// and to restore all its IDs when it's required.
|
||||
template<typename T>
|
||||
class WithSuspended {
|
||||
public:
|
||||
~WithSuspended()
|
||||
{
|
||||
// If the object is suspended it's not included in the Sprite
|
||||
// hierarchy, so it will not be automatically deleted, thereby we
|
||||
// have to delete the object to avoid a memory leak.
|
||||
if constexpr (std::is_pointer_v<T>)
|
||||
delete m_object;
|
||||
}
|
||||
|
||||
T object() { return m_object; }
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
void suspend(T object)
|
||||
{
|
||||
ASSERT(!m_object);
|
||||
|
||||
m_object = object;
|
||||
m_size = m_object->getMemSize();
|
||||
m_object->suspendObject();
|
||||
}
|
||||
|
||||
T restore()
|
||||
{
|
||||
ASSERT(m_object);
|
||||
T object = m_object;
|
||||
|
||||
m_object->restoreObject();
|
||||
m_object = nullptr;
|
||||
m_size = 0;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_size = 0;
|
||||
T m_object = nullptr;
|
||||
};
|
||||
|
||||
}} // namespace app::cmd
|
||||
|
||||
#endif
|
|
@ -325,10 +325,15 @@ void FilterManagerImpl::applyToTarget()
|
|||
void FilterManagerImpl::initTransaction()
|
||||
{
|
||||
ASSERT(!m_tx);
|
||||
m_writer.reset(new ContextWriter(m_reader));
|
||||
m_writer = std::make_unique<ContextWriter>(m_reader);
|
||||
m_tx.reset(new Tx(*m_writer, m_filter->getName(), ModifyDocument));
|
||||
}
|
||||
|
||||
void FilterManagerImpl::updateWriterThread()
|
||||
{
|
||||
document()->updateWriterThread();
|
||||
}
|
||||
|
||||
bool FilterManagerImpl::isTransaction() const
|
||||
{
|
||||
return (m_tx != nullptr);
|
||||
|
|
|
@ -93,6 +93,7 @@ public:
|
|||
void applyToTarget();
|
||||
|
||||
void initTransaction();
|
||||
void updateWriterThread();
|
||||
bool isTransaction() const;
|
||||
void commitTransaction();
|
||||
|
||||
|
|
|
@ -118,7 +118,13 @@ FilterWorker::~FilterWorker()
|
|||
|
||||
void FilterWorker::run()
|
||||
{
|
||||
// Initialize writting transaction
|
||||
// Initialize writing transaction from the main thread. This is
|
||||
// required to get the activeSite() from the UIContext from
|
||||
// CmdTransaction::calcSpritePosition().
|
||||
//
|
||||
// The document will keep the UI thread associated as the "writer"
|
||||
// thread, but that will be updated later in
|
||||
// applyFilterInBackground() with the worker thread ID.
|
||||
m_filterMgr->initTransaction();
|
||||
|
||||
std::thread thread;
|
||||
|
@ -182,6 +188,11 @@ bool FilterWorker::isCancelled()
|
|||
void FilterWorker::applyFilterInBackground()
|
||||
{
|
||||
try {
|
||||
// This background thread is the new writer. This is required to
|
||||
// avoid read-locking from the UI thread from Editor and Timeline
|
||||
// onPaint() events.
|
||||
m_filterMgr->updateWriterThread();
|
||||
|
||||
// Apply the filter
|
||||
m_filterMgr->applyToTarget();
|
||||
|
||||
|
|
|
@ -124,6 +124,11 @@ Doc::LockResult Doc::upgradeToWrite(int timeout)
|
|||
return res;
|
||||
}
|
||||
|
||||
void Doc::updateWriterThread()
|
||||
{
|
||||
m_rwLock.updateWriterThread();
|
||||
}
|
||||
|
||||
void Doc::downgradeToRead(LockResult lockResult)
|
||||
{
|
||||
DOC_TRACE("DOC: downgradeToRead", this, (int)lockResult);
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
LockResult readLock(int timeout);
|
||||
LockResult writeLock(int timeout);
|
||||
LockResult upgradeToWrite(int timeout);
|
||||
void updateWriterThread();
|
||||
void downgradeToRead(LockResult lockResult);
|
||||
void unlock(LockResult lockResult);
|
||||
|
||||
|
|
|
@ -2810,7 +2810,7 @@ void Editor::pasteImage(const Image* image, const Mask* mask, const gfx::Point*
|
|||
ASSERT(image);
|
||||
|
||||
std::unique_ptr<Mask> temp_mask;
|
||||
if (!mask) {
|
||||
if (!mask || mask->bounds().isEmpty()) {
|
||||
gfx::Rect visibleBounds = getVisibleSpriteBounds();
|
||||
gfx::Rect imageBounds = image->bounds();
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "app/ui/workspace.h"
|
||||
#include "app/ui/workspace_tabs.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/system.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -120,6 +121,10 @@ void UIContext::setActiveView(DocView* docView)
|
|||
mainWin->getTimeline()->updateUsingEditor(editor);
|
||||
mainWin->getPreviewEditor()->updateUsingEditor(editor);
|
||||
|
||||
// Update mouse widgets immediately after changing views rather
|
||||
// than waiting for mouse movement.
|
||||
mainWin->manager()->_updateMouseWidgets();
|
||||
|
||||
// Change the image-type of color bar.
|
||||
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite Document Library
|
||||
// Copyright (c) 2019-2024 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
|
@ -27,6 +27,7 @@ Cel::Cel(frame_t frame, const ImageRef& image)
|
|||
, m_frame(frame)
|
||||
, m_data(new CelData(image))
|
||||
{
|
||||
++m_data->m_refs;
|
||||
}
|
||||
|
||||
Cel::Cel(frame_t frame, const CelDataRef& celData)
|
||||
|
@ -35,6 +36,13 @@ Cel::Cel(frame_t frame, const CelDataRef& celData)
|
|||
, m_frame(frame)
|
||||
, m_data(celData)
|
||||
{
|
||||
++m_data->m_refs;
|
||||
}
|
||||
|
||||
Cel::~Cel()
|
||||
{
|
||||
if (m_data)
|
||||
--m_data->m_refs;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -65,7 +73,11 @@ void Cel::setFrame(frame_t frame)
|
|||
void Cel::setDataRef(const CelDataRef& celData)
|
||||
{
|
||||
ASSERT(celData);
|
||||
if (m_data)
|
||||
--m_data->m_refs;
|
||||
m_data = celData;
|
||||
if (m_data)
|
||||
++m_data->m_refs;
|
||||
}
|
||||
|
||||
void Cel::setPosition(int x, int y)
|
||||
|
@ -119,10 +131,10 @@ Sprite* Cel::sprite() const
|
|||
Cel* Cel::link() const
|
||||
{
|
||||
ASSERT(m_data);
|
||||
if (m_data.get() == NULL)
|
||||
return NULL;
|
||||
if (!m_data)
|
||||
return nullptr;
|
||||
|
||||
if (!m_data.unique()) {
|
||||
if (links() > 0) {
|
||||
for (frame_t fr = 0; fr < m_frame; ++fr) {
|
||||
Cel* possible = m_layer->cel(fr);
|
||||
if (possible && possible->dataRef().get() == m_data.get())
|
||||
|
@ -135,16 +147,32 @@ Cel* Cel::link() const
|
|||
|
||||
std::size_t Cel::links() const
|
||||
{
|
||||
std::size_t links = 0;
|
||||
if (m_data)
|
||||
return std::max<std::size_t>(0, m_data->refs() - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sprite* sprite = this->sprite();
|
||||
for (frame_t fr = 0; fr < sprite->totalFrames(); ++fr) {
|
||||
Cel* cel = m_layer->cel(fr);
|
||||
if (cel && cel != this && cel->dataRef().get() == m_data.get())
|
||||
++links;
|
||||
void Cel::suspendObject()
|
||||
{
|
||||
if (m_data) {
|
||||
if (--m_data->m_refs == 0) {
|
||||
// Suspend the CelData only if this was the latest cel referencing it.
|
||||
m_data->suspendObject();
|
||||
}
|
||||
}
|
||||
|
||||
return links;
|
||||
Object::suspendObject();
|
||||
}
|
||||
|
||||
void Cel::restoreObject()
|
||||
{
|
||||
Object::restoreObject();
|
||||
|
||||
if (m_data) {
|
||||
if (++m_data->m_refs == 1) {
|
||||
m_data->restoreObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cel::setParentLayer(LayerImage* layer)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite Document Library
|
||||
// Copyright (c) 2019-2024 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
|
@ -28,6 +28,7 @@ class Cel : public Object {
|
|||
public:
|
||||
Cel(frame_t frame, const ImageRef& image);
|
||||
Cel(frame_t frame, const CelDataRef& celData);
|
||||
~Cel();
|
||||
|
||||
static Cel* MakeCopy(const frame_t newFrame, const Cel* other);
|
||||
static Cel* MakeLink(const frame_t newFrame, const Cel* other);
|
||||
|
@ -65,7 +66,9 @@ public:
|
|||
void setOpacity(int opacity);
|
||||
void setZIndex(int zindex);
|
||||
|
||||
virtual int getMemSize() const override { return sizeof(Cel) + m_data->getMemSize(); }
|
||||
int getMemSize() const override { return sizeof(Cel) + m_data->getMemSize(); }
|
||||
void suspendObject() override;
|
||||
void restoreObject() override;
|
||||
|
||||
void setParentLayer(LayerImage* layer);
|
||||
Grid grid() const;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite Document Library
|
||||
// Copyright (c) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
|
@ -23,7 +23,6 @@ namespace doc {
|
|||
CelData::CelData(const ImageRef& image)
|
||||
: WithUserData(ObjectType::CelData)
|
||||
, m_image(image)
|
||||
, m_opacity(255)
|
||||
, m_bounds(0, 0, image ? image->width() : 0, image ? image->height() : 0)
|
||||
, m_boundsF(nullptr)
|
||||
{
|
||||
|
@ -57,6 +56,20 @@ void CelData::setPosition(const gfx::Point& pos)
|
|||
m_boundsF->setOrigin(gfx::PointF(pos));
|
||||
}
|
||||
|
||||
void CelData::suspendObject()
|
||||
{
|
||||
if (m_image)
|
||||
m_image->suspendObject();
|
||||
WithUserData::suspendObject();
|
||||
}
|
||||
|
||||
void CelData::restoreObject()
|
||||
{
|
||||
WithUserData::restoreObject();
|
||||
if (m_image)
|
||||
m_image->restoreObject();
|
||||
}
|
||||
|
||||
void CelData::adjustBounds(Layer* layer)
|
||||
{
|
||||
ASSERT(m_image);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite Document Library
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
|
@ -18,10 +18,13 @@
|
|||
|
||||
namespace doc {
|
||||
|
||||
class Cel;
|
||||
class Layer;
|
||||
class Tileset;
|
||||
|
||||
class CelData : public WithUserData {
|
||||
friend class Cel;
|
||||
|
||||
public:
|
||||
CelData(const ImageRef& image);
|
||||
CelData(const CelData& celData);
|
||||
|
@ -30,7 +33,8 @@ public:
|
|||
gfx::Point position() const { return m_bounds.origin(); }
|
||||
const gfx::Rect& bounds() const { return m_bounds; }
|
||||
int opacity() const { return m_opacity; }
|
||||
Image* image() const { return const_cast<Image*>(m_image.get()); };
|
||||
std::size_t refs() const { return m_refs; }
|
||||
Image* image() const { return const_cast<Image*>(m_image.get()); }
|
||||
ImageRef imageRef() const { return m_image; }
|
||||
|
||||
// Returns a rectangle with the bounds of the image (width/height
|
||||
|
@ -79,17 +83,20 @@ public:
|
|||
|
||||
bool hasBoundsF() const { return m_boundsF != nullptr; }
|
||||
|
||||
virtual int getMemSize() const override
|
||||
int getMemSize() const override
|
||||
{
|
||||
ASSERT(m_image);
|
||||
return sizeof(CelData) + m_image->getMemSize();
|
||||
}
|
||||
void suspendObject() override;
|
||||
void restoreObject() override;
|
||||
|
||||
void adjustBounds(Layer* layer);
|
||||
|
||||
private:
|
||||
ImageRef m_image;
|
||||
int m_opacity;
|
||||
int m_opacity = 255;
|
||||
std::size_t m_refs = 0;
|
||||
gfx::Rect m_bounds;
|
||||
|
||||
// Special bounds for reference layers that can have subpixel
|
||||
|
|
|
@ -249,6 +249,28 @@ int LayerImage::getMemSize() const
|
|||
return size;
|
||||
}
|
||||
|
||||
void LayerImage::suspendObject()
|
||||
{
|
||||
CelIterator it = getCelBegin();
|
||||
CelIterator end = getCelEnd();
|
||||
for (; it != end; ++it) {
|
||||
Cel* cel = *it;
|
||||
cel->suspendObject();
|
||||
}
|
||||
Layer::suspendObject();
|
||||
}
|
||||
|
||||
void LayerImage::restoreObject()
|
||||
{
|
||||
Layer::restoreObject();
|
||||
CelIterator it = getCelBegin();
|
||||
CelIterator end = getCelEnd();
|
||||
for (; it != end; ++it) {
|
||||
Cel* cel = *it;
|
||||
cel->restoreObject();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerImage::destroyAllCels()
|
||||
{
|
||||
CelIterator it = getCelBegin();
|
||||
|
@ -430,6 +452,20 @@ int LayerGroup::getMemSize() const
|
|||
return size;
|
||||
}
|
||||
|
||||
void LayerGroup::suspendObject()
|
||||
{
|
||||
for (Layer* child : m_layers)
|
||||
child->suspendObject();
|
||||
Layer::suspendObject();
|
||||
}
|
||||
|
||||
void LayerGroup::restoreObject()
|
||||
{
|
||||
Layer::restoreObject();
|
||||
for (Layer* child : m_layers)
|
||||
child->restoreObject();
|
||||
}
|
||||
|
||||
Layer* LayerGroup::firstLayerInWholeHierarchy() const
|
||||
{
|
||||
Layer* layer = firstLayer();
|
||||
|
|
|
@ -60,7 +60,7 @@ protected:
|
|||
public:
|
||||
virtual ~Layer();
|
||||
|
||||
virtual int getMemSize() const override;
|
||||
int getMemSize() const override;
|
||||
|
||||
const std::string& name() const { return m_name; }
|
||||
void setName(const std::string& name) { m_name = name; }
|
||||
|
@ -170,7 +170,9 @@ public:
|
|||
explicit LayerImage(Sprite* sprite);
|
||||
virtual ~LayerImage();
|
||||
|
||||
virtual int getMemSize() const override;
|
||||
int getMemSize() const override;
|
||||
void suspendObject() override;
|
||||
void restoreObject() override;
|
||||
|
||||
void addCel(Cel* cel);
|
||||
void removeCel(Cel* cel);
|
||||
|
@ -207,7 +209,9 @@ public:
|
|||
explicit LayerGroup(Sprite* sprite);
|
||||
virtual ~LayerGroup();
|
||||
|
||||
virtual int getMemSize() const override;
|
||||
int getMemSize() const override;
|
||||
void suspendObject() override;
|
||||
void restoreObject() override;
|
||||
|
||||
const LayerList& layers() const { return m_layers; }
|
||||
int layersCount() const { return (int)m_layers.size(); }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite Document Library
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
|
@ -23,13 +23,14 @@ static ObjectId newId = 0;
|
|||
// TODO Profile this and see if an unordered_map is better
|
||||
static std::map<ObjectId, Object*> objects;
|
||||
|
||||
Object::Object(ObjectType type) : m_type(type), m_id(0), m_version(0)
|
||||
Object::Object(ObjectType type) : m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
Object::Object(const Object& other)
|
||||
: m_type(other.m_type)
|
||||
, m_id(0) // We don't copy the ID
|
||||
, m_id(NullId) // We don't copy the ID
|
||||
, m_suspendedId(NullId)
|
||||
, m_version(0) // We don't copy the version
|
||||
{
|
||||
}
|
||||
|
@ -37,7 +38,7 @@ Object::Object(const Object& other)
|
|||
Object::~Object()
|
||||
{
|
||||
if (m_id)
|
||||
setId(0);
|
||||
setId(NullId);
|
||||
}
|
||||
|
||||
int Object::getMemSize() const
|
||||
|
@ -47,6 +48,9 @@ int Object::getMemSize() const
|
|||
|
||||
const ObjectId Object::id() const
|
||||
{
|
||||
// We cannot ask for the ID from a "suspended" object.
|
||||
ASSERT(m_suspendedId == NullId);
|
||||
|
||||
// The first time the ID is request, we store the object in the
|
||||
// "objects" hash table.
|
||||
if (!m_id) {
|
||||
|
@ -99,6 +103,20 @@ void Object::setVersion(ObjectVersion version)
|
|||
m_version = version;
|
||||
}
|
||||
|
||||
void Object::suspendObject()
|
||||
{
|
||||
ASSERT(m_suspendedId == NullId);
|
||||
m_suspendedId = m_id;
|
||||
setId(NullId);
|
||||
}
|
||||
|
||||
void Object::restoreObject()
|
||||
{
|
||||
ASSERT(m_id == NullId);
|
||||
setId(m_suspendedId);
|
||||
m_suspendedId = NullId;
|
||||
}
|
||||
|
||||
Object* get_object(ObjectId id)
|
||||
{
|
||||
const std::lock_guard lock(g_mutex);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Aseprite Document Library
|
||||
// Copyright (c) 2025 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
|
@ -9,6 +10,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "doc/object_id.h"
|
||||
#include "doc/object_ids.h"
|
||||
#include "doc/object_type.h"
|
||||
#include "doc/object_version.h"
|
||||
|
||||
|
@ -33,14 +35,24 @@ public:
|
|||
// object use.
|
||||
virtual int getMemSize() const;
|
||||
|
||||
// Removes or restore the ID of this object (and all its children)
|
||||
// to keep this object in a "suspended" state (e.g. in the undo
|
||||
// history) or to recover the object from a suspended state.
|
||||
virtual void suspendObject();
|
||||
virtual void restoreObject();
|
||||
|
||||
private:
|
||||
ObjectType m_type;
|
||||
|
||||
// Unique identifier for this object (it is assigned by
|
||||
// Objects class).
|
||||
mutable ObjectId m_id;
|
||||
mutable ObjectId m_id = NullId;
|
||||
|
||||
ObjectVersion m_version;
|
||||
// ID saved when the objects is "deleted" but stored in the undo
|
||||
// history. It's a way to save the previous ID and restore it.
|
||||
ObjectId m_suspendedId = NullId;
|
||||
|
||||
ObjectVersion m_version = 0;
|
||||
|
||||
// Disable copy assignment
|
||||
Object& operator=(const Object&);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Aseprite Document Library
|
||||
// Copyright (c) 2025 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
|
@ -12,9 +13,9 @@
|
|||
|
||||
namespace doc {
|
||||
|
||||
typedef uint32_t ObjectId;
|
||||
using ObjectId = uint32_t;
|
||||
|
||||
const ObjectId NullId = 0;
|
||||
constexpr const ObjectId NullId = 0;
|
||||
|
||||
} // namespace doc
|
||||
|
||||
|
|
Loading…
Reference in New Issue