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
|
// Aseprite
|
||||||
// Copyright (C) 2020 Igara Studio S.A.
|
// Copyright (C) 2020-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -15,11 +15,7 @@
|
||||||
#include "app/doc_event.h"
|
#include "app/doc_event.h"
|
||||||
#include "base/serialization.h"
|
#include "base/serialization.h"
|
||||||
#include "doc/cel.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/layer.h"
|
||||||
#include "doc/subobjects_io.h"
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
||||||
|
|
@ -27,7 +23,7 @@ using namespace base::serialization;
|
||||||
using namespace base::serialization::little_endian;
|
using namespace base::serialization::little_endian;
|
||||||
using namespace doc;
|
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(layer);
|
||||||
ASSERT(cel);
|
ASSERT(cel);
|
||||||
|
|
||||||
// Save the CelData only if the cel isn't linked
|
// We must suspend the cel after removing the cel, we cannot trigger
|
||||||
bool has_data = (cel->links() == 0);
|
// onBeforeRemoveCel() with a cel without ID.
|
||||||
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());
|
|
||||||
|
|
||||||
removeCel(layer, cel);
|
removeCel(layer, cel);
|
||||||
|
m_suspendedCel.suspend(cel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCel::onRedo()
|
void AddCel::onRedo()
|
||||||
{
|
{
|
||||||
Layer* layer = this->layer();
|
Layer* layer = this->layer();
|
||||||
|
Cel* cel = m_suspendedCel.restore();
|
||||||
ASSERT(layer);
|
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);
|
ASSERT(cel);
|
||||||
|
|
||||||
addCel(layer, cel);
|
addCel(layer, cel);
|
||||||
|
|
||||||
m_stream.str(std::string());
|
|
||||||
m_stream.clear();
|
|
||||||
m_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCel::addCel(Layer* layer, Cel* cel)
|
void AddCel::addCel(Layer* layer, Cel* cel)
|
||||||
|
|
@ -111,8 +86,6 @@ void AddCel::removeCel(Layer* layer, Cel* cel)
|
||||||
layer->incrementVersion();
|
layer->incrementVersion();
|
||||||
|
|
||||||
doc->notify_observers<DocEvent&>(&DocObserver::onAfterRemoveCel, ev);
|
doc->notify_observers<DocEvent&>(&DocObserver::onAfterRemoveCel, ev);
|
||||||
|
|
||||||
delete cel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -11,11 +12,10 @@
|
||||||
#include "app/cmd.h"
|
#include "app/cmd.h"
|
||||||
#include "app/cmd/with_cel.h"
|
#include "app/cmd/with_cel.h"
|
||||||
#include "app/cmd/with_layer.h"
|
#include "app/cmd/with_layer.h"
|
||||||
|
#include "app/cmd/with_suspended.h"
|
||||||
#include <sstream>
|
#include "doc/cel.h"
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
class Cel;
|
|
||||||
class Layer;
|
class Layer;
|
||||||
} // namespace doc
|
} // namespace doc
|
||||||
|
|
||||||
|
|
@ -32,14 +32,13 @@ protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
void onUndo() override;
|
void onUndo() override;
|
||||||
void onRedo() 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:
|
private:
|
||||||
void addCel(Layer* layer, Cel* cel);
|
void addCel(Layer* layer, Cel* cel);
|
||||||
void removeCel(Layer* layer, Cel* cel);
|
void removeCel(Layer* layer, Cel* cel);
|
||||||
|
|
||||||
size_t m_size;
|
WithSuspended<doc::Cel*> m_suspendedCel;
|
||||||
std::stringstream m_stream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@
|
||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
#include "app/doc_event.h"
|
#include "app/doc_event.h"
|
||||||
#include "doc/layer.h"
|
#include "doc/layer.h"
|
||||||
#include "doc/layer_io.h"
|
|
||||||
#include "doc/subobjects_io.h"
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
||||||
|
|
@ -24,7 +22,6 @@ AddLayer::AddLayer(Layer* group, Layer* newLayer, Layer* afterThis)
|
||||||
: m_group(group)
|
: m_group(group)
|
||||||
, m_newLayer(newLayer)
|
, m_newLayer(newLayer)
|
||||||
, m_afterThis(afterThis)
|
, m_afterThis(afterThis)
|
||||||
, m_size(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,25 +38,19 @@ void AddLayer::onUndo()
|
||||||
{
|
{
|
||||||
Layer* group = m_group.layer();
|
Layer* group = m_group.layer();
|
||||||
Layer* layer = m_newLayer.layer();
|
Layer* layer = m_newLayer.layer();
|
||||||
|
ASSERT(layer);
|
||||||
write_layer(m_stream, layer);
|
|
||||||
m_size = size_t(m_stream.tellp());
|
|
||||||
|
|
||||||
removeLayer(group, layer);
|
removeLayer(group, layer);
|
||||||
|
m_suspendedLayer.suspend(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddLayer::onRedo()
|
void AddLayer::onRedo()
|
||||||
{
|
{
|
||||||
Layer* group = m_group.layer();
|
Layer* group = m_group.layer();
|
||||||
SubObjectsFromSprite io(group->sprite());
|
Layer* newLayer = m_suspendedLayer.restore();
|
||||||
Layer* newLayer = read_layer(m_stream, &io);
|
|
||||||
Layer* afterThis = m_afterThis.layer();
|
Layer* afterThis = m_afterThis.layer();
|
||||||
|
|
||||||
addLayer(group, newLayer, afterThis);
|
addLayer(group, newLayer, afterThis);
|
||||||
|
|
||||||
m_stream.str(std::string());
|
|
||||||
m_stream.clear();
|
|
||||||
m_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddLayer::addLayer(Layer* group, Layer* newLayer, Layer* afterThis)
|
void AddLayer::addLayer(Layer* group, Layer* newLayer, Layer* afterThis)
|
||||||
|
|
@ -88,8 +79,6 @@ void AddLayer::removeLayer(Layer* group, Layer* layer)
|
||||||
group->sprite()->incrementVersion();
|
group->sprite()->incrementVersion();
|
||||||
|
|
||||||
doc->notify_observers<DocEvent&>(&DocObserver::onAfterRemoveLayer, ev);
|
doc->notify_observers<DocEvent&>(&DocObserver::onAfterRemoveLayer, ev);
|
||||||
|
|
||||||
delete layer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (c) 2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -10,12 +11,8 @@
|
||||||
|
|
||||||
#include "app/cmd.h"
|
#include "app/cmd.h"
|
||||||
#include "app/cmd/with_layer.h"
|
#include "app/cmd/with_layer.h"
|
||||||
|
#include "app/cmd/with_suspended.h"
|
||||||
#include <sstream>
|
#include "doc/layer.h"
|
||||||
|
|
||||||
namespace doc {
|
|
||||||
class Layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
using namespace doc;
|
using namespace doc;
|
||||||
|
|
@ -28,7 +25,7 @@ protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
void onUndo() override;
|
void onUndo() override;
|
||||||
void onRedo() 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:
|
private:
|
||||||
void addLayer(Layer* group, Layer* newLayer, Layer* afterThis);
|
void addLayer(Layer* group, Layer* newLayer, Layer* afterThis);
|
||||||
|
|
@ -37,8 +34,7 @@ private:
|
||||||
WithLayer m_group;
|
WithLayer m_group;
|
||||||
WithLayer m_newLayer;
|
WithLayer m_newLayer;
|
||||||
WithLayer m_afterThis;
|
WithLayer m_afterThis;
|
||||||
size_t m_size;
|
WithSuspended<doc::Layer*> m_suspendedLayer;
|
||||||
std::stringstream m_stream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -11,30 +11,21 @@
|
||||||
#include "app/cmd/add_palette.h"
|
#include "app/cmd/add_palette.h"
|
||||||
|
|
||||||
#include "doc/palette.h"
|
#include "doc/palette.h"
|
||||||
#include "doc/palette_io.h"
|
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
||||||
using namespace doc;
|
using namespace doc;
|
||||||
|
|
||||||
AddPalette::AddPalette(Sprite* sprite, Palette* pal)
|
AddPalette::AddPalette(Sprite* sprite, Palette* pal) : WithSprite(sprite), m_palette(*pal)
|
||||||
: WithSprite(sprite)
|
|
||||||
, m_size(0)
|
|
||||||
, m_frame(pal->frame())
|
|
||||||
{
|
{
|
||||||
write_palette(m_stream, pal);
|
|
||||||
m_size = size_t(m_stream.tellp());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPalette::onExecute()
|
void AddPalette::onExecute()
|
||||||
{
|
{
|
||||||
m_stream.seekp(0);
|
|
||||||
|
|
||||||
Sprite* sprite = this->sprite();
|
Sprite* sprite = this->sprite();
|
||||||
Palette* pal = read_palette(m_stream);
|
|
||||||
|
|
||||||
sprite->setPalette(pal, true);
|
sprite->setPalette(&m_palette, true);
|
||||||
sprite->incrementVersion();
|
sprite->incrementVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,7 +33,7 @@ void AddPalette::onUndo()
|
||||||
{
|
{
|
||||||
Sprite* sprite = this->sprite();
|
Sprite* sprite = this->sprite();
|
||||||
|
|
||||||
sprite->deletePalette(m_frame);
|
sprite->deletePalette(m_palette.frame());
|
||||||
sprite->incrementVersion();
|
sprite->incrementVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -10,9 +11,7 @@
|
||||||
|
|
||||||
#include "app/cmd.h"
|
#include "app/cmd.h"
|
||||||
#include "app/cmd/with_sprite.h"
|
#include "app/cmd/with_sprite.h"
|
||||||
#include "doc/frame.h"
|
#include "doc/palette.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
class Palette;
|
class Palette;
|
||||||
|
|
@ -30,12 +29,10 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
void onUndo() 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:
|
private:
|
||||||
size_t m_size;
|
Palette m_palette;
|
||||||
std::stringstream m_stream;
|
|
||||||
frame_t m_frame;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019 Igara Studio S.A.
|
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2017 David Capello
|
// Copyright (C) 2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -14,14 +14,13 @@
|
||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
#include "app/doc_event.h"
|
#include "app/doc_event.h"
|
||||||
#include "doc/slice.h"
|
#include "doc/slice.h"
|
||||||
#include "doc/slice_io.h"
|
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
||||||
using namespace doc;
|
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();
|
Sprite* sprite = this->sprite();
|
||||||
Slice* slice = this->slice();
|
Slice* slice = this->slice();
|
||||||
write_slice(m_stream, slice);
|
|
||||||
m_size = size_t(m_stream.tellp());
|
|
||||||
|
|
||||||
removeSlice(sprite, slice);
|
removeSlice(sprite, slice);
|
||||||
|
m_suspendedSlice.suspend(slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddSlice::onRedo()
|
void AddSlice::onRedo()
|
||||||
{
|
{
|
||||||
Sprite* sprite = this->sprite();
|
Sprite* sprite = this->sprite();
|
||||||
Slice* slice = read_slice(m_stream);
|
Slice* slice = m_suspendedSlice.restore();
|
||||||
|
|
||||||
addSlice(sprite, slice);
|
addSlice(sprite, slice);
|
||||||
|
|
||||||
m_stream.str(std::string());
|
|
||||||
m_stream.clear();
|
|
||||||
m_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddSlice::addSlice(Sprite* sprite, Slice* slice)
|
void AddSlice::addSlice(Sprite* sprite, Slice* slice)
|
||||||
|
|
@ -77,7 +71,6 @@ void AddSlice::removeSlice(Sprite* sprite, Slice* slice)
|
||||||
|
|
||||||
sprite->slices().remove(slice);
|
sprite->slices().remove(slice);
|
||||||
sprite->incrementVersion();
|
sprite->incrementVersion();
|
||||||
delete slice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019 Igara Studio S.A.
|
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2017 David Capello
|
// Copyright (C) 2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -12,8 +12,8 @@
|
||||||
#include "app/cmd.h"
|
#include "app/cmd.h"
|
||||||
#include "app/cmd/with_slice.h"
|
#include "app/cmd/with_slice.h"
|
||||||
#include "app/cmd/with_sprite.h"
|
#include "app/cmd/with_sprite.h"
|
||||||
|
#include "app/cmd/with_suspended.h"
|
||||||
#include <sstream>
|
#include "doc/slice.h"
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
using namespace doc;
|
using namespace doc;
|
||||||
|
|
@ -28,14 +28,13 @@ protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
void onUndo() override;
|
void onUndo() override;
|
||||||
void onRedo() 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:
|
private:
|
||||||
void addSlice(Sprite* sprite, Slice* slice);
|
void addSlice(Sprite* sprite, Slice* slice);
|
||||||
void removeSlice(Sprite* sprite, Slice* slice);
|
void removeSlice(Sprite* sprite, Slice* slice);
|
||||||
|
|
||||||
size_t m_size;
|
WithSuspended<doc::Slice*> m_suspendedSlice;
|
||||||
std::stringstream m_stream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019 Igara Studio S.A.
|
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -15,13 +15,12 @@
|
||||||
#include "app/doc_event.h"
|
#include "app/doc_event.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "doc/tag.h"
|
#include "doc/tag.h"
|
||||||
#include "doc/tag_io.h"
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
||||||
using namespace doc;
|
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();
|
Sprite* sprite = this->sprite();
|
||||||
Tag* tag = this->tag();
|
Tag* tag = this->tag();
|
||||||
write_tag(m_stream, tag);
|
|
||||||
m_size = size_t(m_stream.tellp());
|
|
||||||
|
|
||||||
// Notify observers about the new frame.
|
// Notify observers about the new frame.
|
||||||
{
|
{
|
||||||
|
|
@ -59,21 +56,18 @@ void AddTag::onUndo()
|
||||||
|
|
||||||
sprite->tags().remove(tag);
|
sprite->tags().remove(tag);
|
||||||
sprite->incrementVersion();
|
sprite->incrementVersion();
|
||||||
delete tag;
|
|
||||||
|
m_suspendedTag.suspend(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTag::onRedo()
|
void AddTag::onRedo()
|
||||||
{
|
{
|
||||||
Sprite* sprite = this->sprite();
|
Sprite* sprite = this->sprite();
|
||||||
Tag* tag = read_tag(m_stream);
|
Tag* tag = m_suspendedTag.restore();
|
||||||
|
|
||||||
sprite->tags().add(tag);
|
sprite->tags().add(tag);
|
||||||
sprite->incrementVersion();
|
sprite->incrementVersion();
|
||||||
|
|
||||||
m_stream.str(std::string());
|
|
||||||
m_stream.clear();
|
|
||||||
m_size = 0;
|
|
||||||
|
|
||||||
// Notify observers about the new frame.
|
// Notify observers about the new frame.
|
||||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||||
DocEvent ev(doc);
|
DocEvent ev(doc);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019 Igara Studio S.A.
|
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
#include "app/cmd.h"
|
#include "app/cmd.h"
|
||||||
#include "app/cmd/with_sprite.h"
|
#include "app/cmd/with_sprite.h"
|
||||||
|
#include "app/cmd/with_suspended.h"
|
||||||
#include "app/cmd/with_tag.h"
|
#include "app/cmd/with_tag.h"
|
||||||
|
#include "doc/tag.h"
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
using namespace doc;
|
using namespace doc;
|
||||||
|
|
@ -28,11 +28,10 @@ protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
void onUndo() override;
|
void onUndo() override;
|
||||||
void onRedo() 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:
|
private:
|
||||||
size_t m_size;
|
WithSuspended<doc::Tag*> m_suspendedTag;
|
||||||
std::stringstream m_stream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// 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
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
#include "app/cmd/add_tile.h"
|
#include "app/cmd/add_tile.h"
|
||||||
|
|
||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
#include "doc/image_io.h"
|
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "doc/tileset.h"
|
#include "doc/tileset.h"
|
||||||
#include "doc/tilesets.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)
|
AddTile::AddTile(doc::Tileset* tileset, const doc::ImageRef& image, const doc::UserData& userData)
|
||||||
: WithTileset(tileset)
|
: WithTileset(tileset)
|
||||||
, WithImage(image.get())
|
|
||||||
, m_size(0)
|
|
||||||
, m_tileIndex(doc::notile)
|
, m_tileIndex(doc::notile)
|
||||||
, m_imageRef(image)
|
, m_imageRef(image)
|
||||||
, m_userData(userData)
|
, 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)
|
AddTile::AddTile(doc::Tileset* tileset, const doc::tile_index ti)
|
||||||
: WithTileset(tileset)
|
: WithTileset(tileset)
|
||||||
, WithImage(tileset->get(ti).get())
|
|
||||||
, m_size(0)
|
|
||||||
, m_tileIndex(ti)
|
, m_tileIndex(ti)
|
||||||
, m_imageRef(nullptr)
|
, m_imageRef(tileset->get(ti))
|
||||||
, m_userData(tileset->getTileData(ti))
|
, m_userData(tileset->getTileData(ti))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -44,14 +39,11 @@ void AddTile::onExecute()
|
||||||
ASSERT(tileset);
|
ASSERT(tileset);
|
||||||
|
|
||||||
if (m_tileIndex != doc::notile) {
|
if (m_tileIndex != doc::notile) {
|
||||||
ASSERT(!m_imageRef);
|
|
||||||
tileset->sprite()->incrementVersion();
|
tileset->sprite()->incrementVersion();
|
||||||
tileset->incrementVersion();
|
tileset->incrementVersion();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ASSERT(m_imageRef);
|
|
||||||
addTile(tileset, m_imageRef, m_userData);
|
addTile(tileset, m_imageRef, m_userData);
|
||||||
m_imageRef.reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,8 +52,9 @@ void AddTile::onUndo()
|
||||||
doc::Tileset* tileset = this->tileset();
|
doc::Tileset* tileset = this->tileset();
|
||||||
ASSERT(tileset);
|
ASSERT(tileset);
|
||||||
|
|
||||||
write_image(m_stream, image());
|
ASSERT(m_imageRef);
|
||||||
m_size = size_t(m_stream.tellp());
|
m_suspendedImage.suspend(m_imageRef);
|
||||||
|
m_imageRef.reset();
|
||||||
|
|
||||||
tileset->erase(m_tileIndex);
|
tileset->erase(m_tileIndex);
|
||||||
|
|
||||||
|
|
@ -74,15 +67,10 @@ void AddTile::onRedo()
|
||||||
doc::Tileset* tileset = this->tileset();
|
doc::Tileset* tileset = this->tileset();
|
||||||
|
|
||||||
ASSERT(!m_imageRef);
|
ASSERT(!m_imageRef);
|
||||||
m_imageRef.reset(read_image(m_stream));
|
m_imageRef = m_suspendedImage.restore();
|
||||||
ASSERT(m_imageRef);
|
ASSERT(m_imageRef);
|
||||||
|
|
||||||
addTile(tileset, m_imageRef, m_userData);
|
addTile(tileset, m_imageRef, m_userData);
|
||||||
m_imageRef.reset();
|
|
||||||
|
|
||||||
m_stream.str(std::string());
|
|
||||||
m_stream.clear();
|
|
||||||
m_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTile::onFireNotifications()
|
void AddTile::onFireNotifications()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// 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
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
@ -9,14 +9,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "app/cmd.h"
|
#include "app/cmd.h"
|
||||||
#include "app/cmd/with_image.h"
|
#include "app/cmd/with_suspended.h"
|
||||||
#include "app/cmd/with_tileset.h"
|
#include "app/cmd/with_tileset.h"
|
||||||
#include "doc/image_ref.h"
|
#include "doc/image_ref.h"
|
||||||
#include "doc/tile.h"
|
#include "doc/tile.h"
|
||||||
#include "doc/user_data.h"
|
#include "doc/user_data.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
class Tileset;
|
class Tileset;
|
||||||
}
|
}
|
||||||
|
|
@ -24,12 +22,9 @@ class Tileset;
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
||||||
class AddTile : public Cmd,
|
class AddTile : public Cmd,
|
||||||
public WithTileset,
|
public WithTileset {
|
||||||
public WithImage {
|
|
||||||
public:
|
public:
|
||||||
AddTile(doc::Tileset* tileset,
|
AddTile(doc::Tileset* tileset, const doc::ImageRef& image, const doc::UserData& userData = {});
|
||||||
const doc::ImageRef& image,
|
|
||||||
const doc::UserData& userData = UserData());
|
|
||||||
AddTile(doc::Tileset* tileset, const doc::tile_index ti);
|
AddTile(doc::Tileset* tileset, const doc::tile_index ti);
|
||||||
|
|
||||||
doc::tile_index tileIndex() const { return m_tileIndex; }
|
doc::tile_index tileIndex() const { return m_tileIndex; }
|
||||||
|
|
@ -42,14 +37,13 @@ protected:
|
||||||
size_t onMemSize() const override
|
size_t onMemSize() const override
|
||||||
{
|
{
|
||||||
// TODO add m_userData size
|
// TODO add m_userData size
|
||||||
return sizeof(*this) + m_size;
|
return sizeof(*this) + m_suspendedImage.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addTile(doc::Tileset* tileset, const doc::ImageRef& image, const doc::UserData& userData);
|
void addTile(doc::Tileset* tileset, const doc::ImageRef& image, const doc::UserData& userData);
|
||||||
|
|
||||||
size_t m_size;
|
WithSuspended<doc::ImageRef> m_suspendedImage;
|
||||||
std::stringstream m_stream;
|
|
||||||
doc::tile_index m_tileIndex;
|
doc::tile_index m_tileIndex;
|
||||||
doc::ImageRef m_imageRef;
|
doc::ImageRef m_imageRef;
|
||||||
doc::UserData m_userData;
|
doc::UserData m_userData;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// 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
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
@ -11,9 +11,7 @@
|
||||||
#include "app/cmd/add_tileset.h"
|
#include "app/cmd/add_tileset.h"
|
||||||
|
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "doc/subobjects_io.h"
|
|
||||||
#include "doc/tileset.h"
|
#include "doc/tileset.h"
|
||||||
#include "doc/tileset_io.h"
|
|
||||||
#include "doc/tilesets.h"
|
#include "doc/tilesets.h"
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
@ -23,7 +21,6 @@ using namespace doc;
|
||||||
AddTileset::AddTileset(doc::Sprite* sprite, doc::Tileset* tileset)
|
AddTileset::AddTileset(doc::Sprite* sprite, doc::Tileset* tileset)
|
||||||
: WithSprite(sprite)
|
: WithSprite(sprite)
|
||||||
, WithTileset(tileset)
|
, WithTileset(tileset)
|
||||||
, m_size(0)
|
|
||||||
, m_tilesetIndex(-1)
|
, 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)
|
AddTileset::AddTileset(doc::Sprite* sprite, const doc::tileset_index tsi)
|
||||||
: WithSprite(sprite)
|
: WithSprite(sprite)
|
||||||
, WithTileset(sprite->tilesets()->get(tsi))
|
, WithTileset(sprite->tilesets()->get(tsi))
|
||||||
, m_size(0)
|
|
||||||
, m_tilesetIndex(tsi)
|
, m_tilesetIndex(tsi)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -46,28 +42,20 @@ void AddTileset::onExecute()
|
||||||
void AddTileset::onUndo()
|
void AddTileset::onUndo()
|
||||||
{
|
{
|
||||||
doc::Tileset* tileset = this->tileset();
|
doc::Tileset* tileset = this->tileset();
|
||||||
write_tileset(m_stream, tileset);
|
m_suspendedTileset.suspend(tileset);
|
||||||
m_size = size_t(m_stream.tellp());
|
|
||||||
|
|
||||||
doc::Sprite* sprite = this->sprite();
|
doc::Sprite* sprite = this->sprite();
|
||||||
sprite->tilesets()->erase(m_tilesetIndex);
|
sprite->tilesets()->erase(m_tilesetIndex);
|
||||||
|
|
||||||
sprite->incrementVersion();
|
sprite->incrementVersion();
|
||||||
sprite->tilesets()->incrementVersion();
|
sprite->tilesets()->incrementVersion();
|
||||||
|
|
||||||
delete tileset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTileset::onRedo()
|
void AddTileset::onRedo()
|
||||||
{
|
{
|
||||||
auto sprite = this->sprite();
|
doc::Tileset* tileset = m_suspendedTileset.restore();
|
||||||
doc::Tileset* tileset = read_tileset(m_stream, sprite);
|
|
||||||
|
|
||||||
addTileset(tileset);
|
addTileset(tileset);
|
||||||
|
|
||||||
m_stream.str(std::string());
|
|
||||||
m_stream.clear();
|
|
||||||
m_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTileset::addTileset(doc::Tileset* tileset)
|
void AddTileset::addTileset(doc::Tileset* tileset)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019 Igara Studio S.A.
|
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
@ -10,10 +10,10 @@
|
||||||
|
|
||||||
#include "app/cmd.h"
|
#include "app/cmd.h"
|
||||||
#include "app/cmd/with_sprite.h"
|
#include "app/cmd/with_sprite.h"
|
||||||
|
#include "app/cmd/with_suspended.h"
|
||||||
#include "app/cmd/with_tileset.h"
|
#include "app/cmd/with_tileset.h"
|
||||||
#include "doc/tile.h"
|
#include "doc/tile.h"
|
||||||
|
#include "doc/tileset.h"
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
class Tileset;
|
class Tileset;
|
||||||
|
|
@ -34,13 +34,12 @@ protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
void onUndo() override;
|
void onUndo() override;
|
||||||
void onRedo() 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:
|
private:
|
||||||
void addTileset(doc::Tileset* tileset);
|
void addTileset(doc::Tileset* tileset);
|
||||||
|
|
||||||
size_t m_size;
|
WithSuspended<doc::Tileset*> m_suspendedTileset;
|
||||||
std::stringstream m_stream;
|
|
||||||
doc::tileset_index m_tilesetIndex;
|
doc::tileset_index m_tilesetIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2023 Igara Studio S.A.
|
// Copyright (C) 2023-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2015 David Capello
|
// Copyright (C) 2001-2015 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -14,10 +14,8 @@
|
||||||
#include "doc/cel.h"
|
#include "doc/cel.h"
|
||||||
#include "doc/cels_range.h"
|
#include "doc/cels_range.h"
|
||||||
#include "doc/image.h"
|
#include "doc/image.h"
|
||||||
#include "doc/image_io.h"
|
|
||||||
#include "doc/image_ref.h"
|
#include "doc/image_ref.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "doc/subobjects_io.h"
|
|
||||||
#include "doc/tilesets.h"
|
#include "doc/tilesets.h"
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
#include "app/cmd/with_sprite.h"
|
#include "app/cmd/with_sprite.h"
|
||||||
#include "doc/image_ref.h"
|
#include "doc/image_ref.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
using namespace doc;
|
using namespace doc;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2021 Igara Studio S.A.
|
// Copyright (C) 2021-2025 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
@ -14,7 +14,6 @@
|
||||||
#include "doc/layer_tilemap.h"
|
#include "doc/layer_tilemap.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "doc/tileset.h"
|
#include "doc/tileset.h"
|
||||||
#include "doc/tileset_io.h"
|
|
||||||
#include "doc/tilesets.h"
|
#include "doc/tilesets.h"
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
@ -40,16 +39,11 @@ void ReplaceTileset::onExecute()
|
||||||
m_newTileset = nullptr;
|
m_newTileset = nullptr;
|
||||||
}
|
}
|
||||||
else {
|
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);
|
replaceTileset(restoreTileset);
|
||||||
delete actualTileset;
|
m_suspendedTileset.suspend(actualTileset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplaceTileset::replaceTileset(Tileset* newTileset)
|
void ReplaceTileset::replaceTileset(Tileset* newTileset)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2021 Igara Studio S.A.
|
// Copyright (C) 2021-2025 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
@ -10,10 +10,9 @@
|
||||||
|
|
||||||
#include "app/cmd.h"
|
#include "app/cmd.h"
|
||||||
#include "app/cmd/with_sprite.h"
|
#include "app/cmd/with_sprite.h"
|
||||||
|
#include "app/cmd/with_suspended.h"
|
||||||
#include "doc/tileset.h"
|
#include "doc/tileset.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
||||||
class ReplaceTileset : public Cmd,
|
class ReplaceTileset : public Cmd,
|
||||||
|
|
@ -25,15 +24,14 @@ protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
void onUndo() override { onExecute(); }
|
void onUndo() override { onExecute(); }
|
||||||
void onRedo() 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:
|
private:
|
||||||
void replaceTileset(doc::Tileset* newTileset);
|
void replaceTileset(doc::Tileset* newTileset);
|
||||||
|
|
||||||
doc::tileset_index m_tsi;
|
doc::tileset_index m_tsi;
|
||||||
doc::Tileset* m_newTileset;
|
doc::Tileset* m_newTileset;
|
||||||
std::stringstream m_stream;
|
WithSuspended<doc::Tileset*> m_suspendedTileset;
|
||||||
size_t m_size = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace app::cmd
|
}} // namespace app::cmd
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,9 @@
|
||||||
|
|
||||||
#include "doc/cel.h"
|
#include "doc/cel.h"
|
||||||
#include "doc/image.h"
|
#include "doc/image.h"
|
||||||
#include "doc/image_io.h"
|
|
||||||
#include "doc/image_ref.h"
|
#include "doc/image_ref.h"
|
||||||
#include "doc/layer.h"
|
#include "doc/layer.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "doc/subobjects_io.h"
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
#include "app/cmd/with_cel.h"
|
#include "app/cmd/with_cel.h"
|
||||||
#include "doc/cel_data.h"
|
#include "doc/cel_data.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace app { namespace cmd {
|
namespace app { namespace cmd {
|
||||||
using namespace doc;
|
using namespace doc;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019 Igara Studio S.A.
|
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
#include "app/cmd/with_document.h"
|
#include "app/cmd/with_document.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
class Mask;
|
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()
|
void FilterManagerImpl::initTransaction()
|
||||||
{
|
{
|
||||||
ASSERT(!m_tx);
|
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));
|
m_tx.reset(new Tx(*m_writer, m_filter->getName(), ModifyDocument));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FilterManagerImpl::updateWriterThread()
|
||||||
|
{
|
||||||
|
document()->updateWriterThread();
|
||||||
|
}
|
||||||
|
|
||||||
bool FilterManagerImpl::isTransaction() const
|
bool FilterManagerImpl::isTransaction() const
|
||||||
{
|
{
|
||||||
return (m_tx != nullptr);
|
return (m_tx != nullptr);
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ public:
|
||||||
void applyToTarget();
|
void applyToTarget();
|
||||||
|
|
||||||
void initTransaction();
|
void initTransaction();
|
||||||
|
void updateWriterThread();
|
||||||
bool isTransaction() const;
|
bool isTransaction() const;
|
||||||
void commitTransaction();
|
void commitTransaction();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,13 @@ FilterWorker::~FilterWorker()
|
||||||
|
|
||||||
void FilterWorker::run()
|
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();
|
m_filterMgr->initTransaction();
|
||||||
|
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
|
|
@ -182,6 +188,11 @@ bool FilterWorker::isCancelled()
|
||||||
void FilterWorker::applyFilterInBackground()
|
void FilterWorker::applyFilterInBackground()
|
||||||
{
|
{
|
||||||
try {
|
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
|
// Apply the filter
|
||||||
m_filterMgr->applyToTarget();
|
m_filterMgr->applyToTarget();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,11 @@ Doc::LockResult Doc::upgradeToWrite(int timeout)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Doc::updateWriterThread()
|
||||||
|
{
|
||||||
|
m_rwLock.updateWriterThread();
|
||||||
|
}
|
||||||
|
|
||||||
void Doc::downgradeToRead(LockResult lockResult)
|
void Doc::downgradeToRead(LockResult lockResult)
|
||||||
{
|
{
|
||||||
DOC_TRACE("DOC: downgradeToRead", this, (int)lockResult);
|
DOC_TRACE("DOC: downgradeToRead", this, (int)lockResult);
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ public:
|
||||||
LockResult readLock(int timeout);
|
LockResult readLock(int timeout);
|
||||||
LockResult writeLock(int timeout);
|
LockResult writeLock(int timeout);
|
||||||
LockResult upgradeToWrite(int timeout);
|
LockResult upgradeToWrite(int timeout);
|
||||||
|
void updateWriterThread();
|
||||||
void downgradeToRead(LockResult lockResult);
|
void downgradeToRead(LockResult lockResult);
|
||||||
void unlock(LockResult lockResult);
|
void unlock(LockResult lockResult);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2810,7 +2810,7 @@ void Editor::pasteImage(const Image* image, const Mask* mask, const gfx::Point*
|
||||||
ASSERT(image);
|
ASSERT(image);
|
||||||
|
|
||||||
std::unique_ptr<Mask> temp_mask;
|
std::unique_ptr<Mask> temp_mask;
|
||||||
if (!mask) {
|
if (!mask || mask->bounds().isEmpty()) {
|
||||||
gfx::Rect visibleBounds = getVisibleSpriteBounds();
|
gfx::Rect visibleBounds = getVisibleSpriteBounds();
|
||||||
gfx::Rect imageBounds = image->bounds();
|
gfx::Rect imageBounds = image->bounds();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "app/ui/workspace.h"
|
#include "app/ui/workspace.h"
|
||||||
#include "app/ui/workspace_tabs.h"
|
#include "app/ui/workspace_tabs.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
|
#include "ui/manager.h"
|
||||||
#include "ui/system.h"
|
#include "ui/system.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -120,6 +121,10 @@ void UIContext::setActiveView(DocView* docView)
|
||||||
mainWin->getTimeline()->updateUsingEditor(editor);
|
mainWin->getTimeline()->updateUsingEditor(editor);
|
||||||
mainWin->getPreviewEditor()->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.
|
// Change the image-type of color bar.
|
||||||
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());
|
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite Document Library
|
// 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
|
// Copyright (c) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// 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_frame(frame)
|
||||||
, m_data(new CelData(image))
|
, m_data(new CelData(image))
|
||||||
{
|
{
|
||||||
|
++m_data->m_refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cel::Cel(frame_t frame, const CelDataRef& celData)
|
Cel::Cel(frame_t frame, const CelDataRef& celData)
|
||||||
|
|
@ -35,6 +36,13 @@ Cel::Cel(frame_t frame, const CelDataRef& celData)
|
||||||
, m_frame(frame)
|
, m_frame(frame)
|
||||||
, m_data(celData)
|
, m_data(celData)
|
||||||
{
|
{
|
||||||
|
++m_data->m_refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cel::~Cel()
|
||||||
|
{
|
||||||
|
if (m_data)
|
||||||
|
--m_data->m_refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
@ -65,7 +73,11 @@ void Cel::setFrame(frame_t frame)
|
||||||
void Cel::setDataRef(const CelDataRef& celData)
|
void Cel::setDataRef(const CelDataRef& celData)
|
||||||
{
|
{
|
||||||
ASSERT(celData);
|
ASSERT(celData);
|
||||||
|
if (m_data)
|
||||||
|
--m_data->m_refs;
|
||||||
m_data = celData;
|
m_data = celData;
|
||||||
|
if (m_data)
|
||||||
|
++m_data->m_refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cel::setPosition(int x, int y)
|
void Cel::setPosition(int x, int y)
|
||||||
|
|
@ -119,10 +131,10 @@ Sprite* Cel::sprite() const
|
||||||
Cel* Cel::link() const
|
Cel* Cel::link() const
|
||||||
{
|
{
|
||||||
ASSERT(m_data);
|
ASSERT(m_data);
|
||||||
if (m_data.get() == NULL)
|
if (!m_data)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
if (!m_data.unique()) {
|
if (links() > 0) {
|
||||||
for (frame_t fr = 0; fr < m_frame; ++fr) {
|
for (frame_t fr = 0; fr < m_frame; ++fr) {
|
||||||
Cel* possible = m_layer->cel(fr);
|
Cel* possible = m_layer->cel(fr);
|
||||||
if (possible && possible->dataRef().get() == m_data.get())
|
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 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();
|
void Cel::suspendObject()
|
||||||
for (frame_t fr = 0; fr < sprite->totalFrames(); ++fr) {
|
{
|
||||||
Cel* cel = m_layer->cel(fr);
|
if (m_data) {
|
||||||
if (cel && cel != this && cel->dataRef().get() == m_data.get())
|
if (--m_data->m_refs == 0) {
|
||||||
++links;
|
// 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)
|
void Cel::setParentLayer(LayerImage* layer)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite Document Library
|
// 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
|
// Copyright (c) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
|
|
@ -28,6 +28,7 @@ class Cel : public Object {
|
||||||
public:
|
public:
|
||||||
Cel(frame_t frame, const ImageRef& image);
|
Cel(frame_t frame, const ImageRef& image);
|
||||||
Cel(frame_t frame, const CelDataRef& celData);
|
Cel(frame_t frame, const CelDataRef& celData);
|
||||||
|
~Cel();
|
||||||
|
|
||||||
static Cel* MakeCopy(const frame_t newFrame, const Cel* other);
|
static Cel* MakeCopy(const frame_t newFrame, const Cel* other);
|
||||||
static Cel* MakeLink(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 setOpacity(int opacity);
|
||||||
void setZIndex(int zindex);
|
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);
|
void setParentLayer(LayerImage* layer);
|
||||||
Grid grid() const;
|
Grid grid() const;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite Document Library
|
// 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
|
// Copyright (c) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
|
|
@ -23,7 +23,6 @@ namespace doc {
|
||||||
CelData::CelData(const ImageRef& image)
|
CelData::CelData(const ImageRef& image)
|
||||||
: WithUserData(ObjectType::CelData)
|
: WithUserData(ObjectType::CelData)
|
||||||
, m_image(image)
|
, m_image(image)
|
||||||
, m_opacity(255)
|
|
||||||
, m_bounds(0, 0, image ? image->width() : 0, image ? image->height() : 0)
|
, m_bounds(0, 0, image ? image->width() : 0, image ? image->height() : 0)
|
||||||
, m_boundsF(nullptr)
|
, m_boundsF(nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -57,6 +56,20 @@ void CelData::setPosition(const gfx::Point& pos)
|
||||||
m_boundsF->setOrigin(gfx::PointF(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)
|
void CelData::adjustBounds(Layer* layer)
|
||||||
{
|
{
|
||||||
ASSERT(m_image);
|
ASSERT(m_image);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite Document Library
|
// 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
|
// Copyright (C) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
|
|
@ -18,10 +18,13 @@
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
|
|
||||||
|
class Cel;
|
||||||
class Layer;
|
class Layer;
|
||||||
class Tileset;
|
class Tileset;
|
||||||
|
|
||||||
class CelData : public WithUserData {
|
class CelData : public WithUserData {
|
||||||
|
friend class Cel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CelData(const ImageRef& image);
|
CelData(const ImageRef& image);
|
||||||
CelData(const CelData& celData);
|
CelData(const CelData& celData);
|
||||||
|
|
@ -30,7 +33,8 @@ public:
|
||||||
gfx::Point position() const { return m_bounds.origin(); }
|
gfx::Point position() const { return m_bounds.origin(); }
|
||||||
const gfx::Rect& bounds() const { return m_bounds; }
|
const gfx::Rect& bounds() const { return m_bounds; }
|
||||||
int opacity() const { return m_opacity; }
|
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; }
|
ImageRef imageRef() const { return m_image; }
|
||||||
|
|
||||||
// Returns a rectangle with the bounds of the image (width/height
|
// Returns a rectangle with the bounds of the image (width/height
|
||||||
|
|
@ -79,17 +83,20 @@ public:
|
||||||
|
|
||||||
bool hasBoundsF() const { return m_boundsF != nullptr; }
|
bool hasBoundsF() const { return m_boundsF != nullptr; }
|
||||||
|
|
||||||
virtual int getMemSize() const override
|
int getMemSize() const override
|
||||||
{
|
{
|
||||||
ASSERT(m_image);
|
ASSERT(m_image);
|
||||||
return sizeof(CelData) + m_image->getMemSize();
|
return sizeof(CelData) + m_image->getMemSize();
|
||||||
}
|
}
|
||||||
|
void suspendObject() override;
|
||||||
|
void restoreObject() override;
|
||||||
|
|
||||||
void adjustBounds(Layer* layer);
|
void adjustBounds(Layer* layer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ImageRef m_image;
|
ImageRef m_image;
|
||||||
int m_opacity;
|
int m_opacity = 255;
|
||||||
|
std::size_t m_refs = 0;
|
||||||
gfx::Rect m_bounds;
|
gfx::Rect m_bounds;
|
||||||
|
|
||||||
// Special bounds for reference layers that can have subpixel
|
// Special bounds for reference layers that can have subpixel
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,28 @@ int LayerImage::getMemSize() const
|
||||||
return size;
|
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()
|
void LayerImage::destroyAllCels()
|
||||||
{
|
{
|
||||||
CelIterator it = getCelBegin();
|
CelIterator it = getCelBegin();
|
||||||
|
|
@ -430,6 +452,20 @@ int LayerGroup::getMemSize() const
|
||||||
return size;
|
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* LayerGroup::firstLayerInWholeHierarchy() const
|
||||||
{
|
{
|
||||||
Layer* layer = firstLayer();
|
Layer* layer = firstLayer();
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
virtual ~Layer();
|
virtual ~Layer();
|
||||||
|
|
||||||
virtual int getMemSize() const override;
|
int getMemSize() const override;
|
||||||
|
|
||||||
const std::string& name() const { return m_name; }
|
const std::string& name() const { return m_name; }
|
||||||
void setName(const std::string& name) { m_name = name; }
|
void setName(const std::string& name) { m_name = name; }
|
||||||
|
|
@ -170,7 +170,9 @@ public:
|
||||||
explicit LayerImage(Sprite* sprite);
|
explicit LayerImage(Sprite* sprite);
|
||||||
virtual ~LayerImage();
|
virtual ~LayerImage();
|
||||||
|
|
||||||
virtual int getMemSize() const override;
|
int getMemSize() const override;
|
||||||
|
void suspendObject() override;
|
||||||
|
void restoreObject() override;
|
||||||
|
|
||||||
void addCel(Cel* cel);
|
void addCel(Cel* cel);
|
||||||
void removeCel(Cel* cel);
|
void removeCel(Cel* cel);
|
||||||
|
|
@ -207,7 +209,9 @@ public:
|
||||||
explicit LayerGroup(Sprite* sprite);
|
explicit LayerGroup(Sprite* sprite);
|
||||||
virtual ~LayerGroup();
|
virtual ~LayerGroup();
|
||||||
|
|
||||||
virtual int getMemSize() const override;
|
int getMemSize() const override;
|
||||||
|
void suspendObject() override;
|
||||||
|
void restoreObject() override;
|
||||||
|
|
||||||
const LayerList& layers() const { return m_layers; }
|
const LayerList& layers() const { return m_layers; }
|
||||||
int layersCount() const { return (int)m_layers.size(); }
|
int layersCount() const { return (int)m_layers.size(); }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite Document Library
|
// 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
|
// Copyright (C) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// 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
|
// TODO Profile this and see if an unordered_map is better
|
||||||
static std::map<ObjectId, Object*> objects;
|
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)
|
Object::Object(const Object& other)
|
||||||
: m_type(other.m_type)
|
: 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
|
, m_version(0) // We don't copy the version
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +38,7 @@ Object::Object(const Object& other)
|
||||||
Object::~Object()
|
Object::~Object()
|
||||||
{
|
{
|
||||||
if (m_id)
|
if (m_id)
|
||||||
setId(0);
|
setId(NullId);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Object::getMemSize() const
|
int Object::getMemSize() const
|
||||||
|
|
@ -47,6 +48,9 @@ int Object::getMemSize() const
|
||||||
|
|
||||||
const ObjectId Object::id() 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
|
// The first time the ID is request, we store the object in the
|
||||||
// "objects" hash table.
|
// "objects" hash table.
|
||||||
if (!m_id) {
|
if (!m_id) {
|
||||||
|
|
@ -99,6 +103,20 @@ void Object::setVersion(ObjectVersion version)
|
||||||
m_version = 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)
|
Object* get_object(ObjectId id)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(g_mutex);
|
const std::lock_guard lock(g_mutex);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// Aseprite Document Library
|
// Aseprite Document Library
|
||||||
|
// Copyright (c) 2025 Igara Studio S.A.
|
||||||
// Copyright (c) 2001-2015 David Capello
|
// Copyright (c) 2001-2015 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
|
|
@ -9,6 +10,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "doc/object_id.h"
|
#include "doc/object_id.h"
|
||||||
|
#include "doc/object_ids.h"
|
||||||
#include "doc/object_type.h"
|
#include "doc/object_type.h"
|
||||||
#include "doc/object_version.h"
|
#include "doc/object_version.h"
|
||||||
|
|
||||||
|
|
@ -33,14 +35,24 @@ public:
|
||||||
// object use.
|
// object use.
|
||||||
virtual int getMemSize() const;
|
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:
|
private:
|
||||||
ObjectType m_type;
|
ObjectType m_type;
|
||||||
|
|
||||||
// Unique identifier for this object (it is assigned by
|
// Unique identifier for this object (it is assigned by
|
||||||
// Objects class).
|
// 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
|
// Disable copy assignment
|
||||||
Object& operator=(const Object&);
|
Object& operator=(const Object&);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// Aseprite Document Library
|
// Aseprite Document Library
|
||||||
|
// Copyright (c) 2025 Igara Studio S.A.
|
||||||
// Copyright (c) 2001-2016 David Capello
|
// Copyright (c) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
|
|
@ -12,9 +13,9 @@
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
|
|
||||||
typedef uint32_t ObjectId;
|
using ObjectId = uint32_t;
|
||||||
|
|
||||||
const ObjectId NullId = 0;
|
constexpr const ObjectId NullId = 0;
|
||||||
|
|
||||||
} // namespace doc
|
} // namespace doc
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue