Fix removing all frames results in a transparent background layer

Currently if we select all frames (as shown in
https://github.com/aseprite/aseprite/issues/3551), and we will remove
all of them - it also removes cel inside the primary frame, resulting in
a transparent background (again, as shown in issue#3551).

This patch keeps the frame number inside the cel that got deleted while
being on 0th frame, and restores it's frame number when we redo the
frame. This is needed since we don't restore the full cel in
cmd::ClearCel as we do in cmd::RemoveCel, we still use the same cel
before deletion.
This commit is contained in:
tetektoza 2023-09-23 19:58:13 +02:00
parent 27ec013f8b
commit 492c4db545
4 changed files with 33 additions and 12 deletions

View File

@ -30,7 +30,7 @@ ClearCel::ClearCel(Cel* cel)
Image* image = cel->image();
ASSERT(image);
if (image)
m_seq.add(new cmd::ClearImage(image,
m_seq.add(new cmd::ClearImage(cel,
doc->bgColor(cel->layer())));
}
else {

View File

@ -19,15 +19,16 @@ namespace cmd {
using namespace doc;
ClearImage::ClearImage(Image* image, color_t color)
: WithImage(image)
, m_color(color)
ClearImage::ClearImage(Cel* cel, color_t color)
: WithCel(cel)
, m_color(color), m_frame_copy(cel->frame())
{
}
void ClearImage::onExecute()
{
Image* image = this->image();
Cel* cel = this->cel();
Image* image = cel->image();
ASSERT(!m_copy);
m_copy.reset(Image::createCopy(image));
@ -38,7 +39,13 @@ void ClearImage::onExecute()
void ClearImage::onUndo()
{
Image* image = this->image();
Cel* cel = this->cel();
Image* image = cel->image();
// Restore frame number of the cel, since it could get displaced
// during the removal of the frame
if (cel->frame() != m_frame_copy)
cel->setFrame(m_frame_copy);
copy_image(image, m_copy.get());
m_copy.reset();

View File

@ -9,8 +9,9 @@
#pragma once
#include "app/cmd.h"
#include "app/cmd/with_image.h"
#include "app/cmd/with_cel.h"
#include "doc/color.h"
#include "doc/cel.h"
#include "doc/image_ref.h"
namespace app {
@ -18,9 +19,9 @@ namespace cmd {
using namespace doc;
class ClearImage : public Cmd
, public WithImage {
, public WithCel {
public:
ClearImage(Image* image, color_t color);
ClearImage(Cel* cel, color_t color);
protected:
void onExecute() override;
@ -32,6 +33,7 @@ namespace cmd {
private:
ImageRef m_copy;
color_t m_color;
frame_t m_frame_copy;
};
} // namespace cmd

View File

@ -9,7 +9,7 @@
#endif
#include "app/cmd/remove_frame.h"
#include "app/cmd/clear_cel.h"
#include "app/cmd/remove_cel.h"
#include "app/doc.h"
#include "app/doc_event.h"
@ -28,15 +28,20 @@ RemoveFrame::RemoveFrame(Sprite* sprite, frame_t frame)
, m_frameRemoved(false)
{
m_frameDuration = sprite->frameDuration(frame);
for (Cel* cel : sprite->cels(m_frame))
for (Cel* cel : sprite->cels(m_frame)) {
if (m_frame == 0) {
m_seq.add(new cmd::ClearCel(cel));
break;
}
m_seq.add(new cmd::RemoveCel(cel));
}
}
void RemoveFrame::onExecute()
{
Sprite* sprite = this->sprite();
Doc* doc = static_cast<Doc*>(sprite->document());
if (m_firstTime) {
m_firstTime = false;
m_seq.execute(context());
@ -44,6 +49,13 @@ void RemoveFrame::onExecute()
else
m_seq.redo();
// If the user has selected frames in a range - last frame
// will be the 0th frame, so don't displace the frame inside
// Sprite::RemoveFrame, just clear the cel inside it and bail out
// from this function
if (sprite->totalFrames() - 1 == 0)
return;
int oldTotalFrames = sprite->totalFrames();
sprite->removeFrame(m_frame);