Fix bug while moving an image in MovingCelState

Original post: https://community.aseprite.org/t/pretty-nasty-bug-specific/8290

Before this fix, if you pressed Cmd Z / Ctrl Z (undo) while moving an image holding Cmd/Ctrl key,
the moved image were gettting stuck on cursor, and console errors were shown on every click.
This commit is contained in:
Gaspar Capello 2021-03-19 16:49:55 -03:00 committed by David Capello
parent a9640a28dc
commit 42201a4783
2 changed files with 60 additions and 22 deletions

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2020 Igara Studio S.A.
// Copyright (C) 2020-2021 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -13,6 +13,7 @@
#include "app/app.h"
#include "app/cmd/set_cel_bounds.h"
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/doc_api.h"
#include "app/doc_range.h"
@ -88,6 +89,7 @@ MovingCelState::MovingCelState(Editor* editor,
, m_hasReference(false)
, m_scaled(false)
, m_handle(handle)
, m_editor(editor)
{
ContextWriter writer(m_reader);
Doc* document = editor->document();
@ -110,6 +112,11 @@ MovingCelState::MovingCelState(Editor* editor,
else
m_celStarts.push_back(cel->bounds());
}
// Hook BeforeCommandExecution signal so we know if the user wants
// to execute other command, so we can drop pixels.
m_ctxConn = UIContext::instance()->BeforeCommandExecution.connect(
&MovingCelState::onBeforeCommandExecution, this);
}
m_cursorStart = editor->screenToEditorF(msg->position());
@ -126,27 +133,7 @@ MovingCelState::MovingCelState(Editor* editor,
bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
{
Doc* document = editor->document();
bool modified = false;
// Here we put back all cels into their original coordinates (so we
// can add the undo information from the start position).
for (size_t i=0; i<m_celList.size(); ++i) {
Cel* cel = m_celList[i];
const gfx::RectF& celStart = m_celStarts[i];
if (cel->layer()->isReference()) {
if (cel->boundsF() != celStart) {
cel->setBoundsF(celStart);
modified = true;
}
}
else {
if (cel->bounds() != gfx::Rect(celStart)) {
cel->setBounds(gfx::Rect(celStart));
modified = true;
}
}
}
bool modified = restoreCelStartPosition();
if (modified) {
{
@ -326,4 +313,48 @@ gfx::Point MovingCelState::intCelOffset() const
int(std::round(m_celOffset.y)));
}
bool MovingCelState::restoreCelStartPosition() const
{
bool modified = false;
// Here we put back all cels into their original coordinates (so we
// can add the undo information from the start position).
for (size_t i=0; i<m_celList.size(); ++i) {
Cel* cel = m_celList[i];
const gfx::RectF& celStart = m_celStarts[i];
if (cel->layer()->isReference()) {
if (cel->boundsF() != celStart) {
cel->setBoundsF(celStart);
modified = true;
}
}
else {
if (cel->bounds() != gfx::Rect(celStart)) {
cel->setBounds(gfx::Rect(celStart));
modified = true;
}
}
}
return modified;
}
void MovingCelState::onBeforeCommandExecution(CommandExecutionEvent& ev)
{
if (ev.command()->id() == CommandId::Undo() ||
ev.command()->id() == CommandId::Redo() ||
ev.command()->id() == CommandId::Cancel()) {
restoreCelStartPosition();
Doc* document = m_editor->document();
// Restore the mask visibility.
if (m_maskVisible) {
document->setMaskVisible(m_maskVisible);
document->generateMaskBoundaries();
}
m_editor->backToPreviousState();
m_editor->releaseMouse();
m_editor->invalidate();
}
ev.cancel();
}
} // namespace app

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2021 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
@ -53,6 +54,9 @@ namespace app {
private:
gfx::Point intCelOffset() const;
bool restoreCelStartPosition() const;
// ContextObserver
void onBeforeCommandExecution(CommandExecutionEvent& ev);
ContextReader m_reader;
Cel* m_cel;
@ -66,6 +70,9 @@ namespace app {
bool m_hasReference;
bool m_scaled;
HandleType m_handle;
Editor* m_editor;
obs::scoped_connection m_ctxConn;
};
} // namespace app