Fix crash using "play once" (fix #1337)

This commit is contained in:
David Capello 2016-11-30 12:35:01 -03:00
parent e0a017ae02
commit aa8cf94fd2
3 changed files with 20 additions and 1 deletions

View File

@ -260,6 +260,17 @@ void Editor::setStateInternal(const EditorStatePtr& newState)
else {
m_state->onBeforePopState(this);
// Save the current state into "m_deletedStates" just to keep a
// reference to it to avoid delete it right now. We'll delete it
// in the next Editor::onProcessMessage().
//
// This is necessary for PlayState because it removes itself
// calling Editor::stop() from PlayState::onPlaybackTick(). If we
// delete the PlayState inside the "Tick" timer signal, the
// program will crash (because we're iterating the
// PlayState::m_playTimer slots).
m_deletedStates.push(m_state);
m_statesHistory.pop();
m_state = m_statesHistory.top();
}
@ -1209,6 +1220,10 @@ app::Color Editor::getColorByPosition(const gfx::Point& mousePos)
bool Editor::onProcessMessage(Message* msg)
{
// Delete states
if (!m_deletedStates.empty())
m_deletedStates.clear();
switch (msg->type()) {
case kTimerMessage:
@ -1717,6 +1732,7 @@ void Editor::showAnimationSpeedMultiplierPopup(Option<bool>& playOnce,
menu.showPopup(ui::get_mouse_position());
if (isPlaying()) {
// Re-play
stop();
play(playOnce(),
playAll());

View File

@ -268,6 +268,7 @@ namespace app {
// Stack of states. The top element in the stack is the current state (m_state).
EditorStatesHistory m_statesHistory;
EditorStatesHistory m_deletedStates;
// Current editor state (it can be shared between several editors to
// the same document). This member cannot be NULL.

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -21,6 +21,8 @@ namespace app {
EditorStatesHistory();
~EditorStatesHistory();
bool empty() const { return m_states.empty(); }
// Gets the current state.
EditorStatePtr top();