mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-20 18:40:57 +00:00
Fix issue #310 - crash on export sprite sheet
The timeline wasn't being added as a Document observer, so it wasn't getting notifications about layers modifications. In this way the timeline wasn't able to update its m_layers[] internal field and was accessing to removed layers/invalid memory.
This commit is contained in:
parent
03020d7bcf
commit
395be62b03
@ -632,7 +632,7 @@ void DocumentApi::removeLayer(Layer* layer)
|
||||
DocumentEvent ev(m_document);
|
||||
ev.sprite(layer->getSprite());
|
||||
ev.layer(layer);
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onRemoveLayer, ev);
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onBeforeRemoveLayer, ev);
|
||||
|
||||
// Add undoers.
|
||||
if (undoEnabled())
|
||||
@ -640,6 +640,9 @@ void DocumentApi::removeLayer(Layer* layer)
|
||||
|
||||
// Do the action.
|
||||
layer->getParent()->removeLayer(layer);
|
||||
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onAfterRemoveLayer, ev);
|
||||
|
||||
delete layer;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,8 @@ namespace app {
|
||||
|
||||
virtual void onRemoveSprite(DocumentEvent& ev) { }
|
||||
|
||||
virtual void onRemoveLayer(DocumentEvent& ev) { }
|
||||
virtual void onBeforeRemoveLayer(DocumentEvent& ev) { }
|
||||
virtual void onAfterRemoveLayer(DocumentEvent& ev) { }
|
||||
|
||||
// Called when a frame is removed. It's called after the frame was
|
||||
// removed, and the sprite's total number of frames is modified.
|
||||
|
@ -218,7 +218,7 @@ void DocumentView::onAddLayer(DocumentEvent& ev)
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentView::onRemoveLayer(DocumentEvent& ev)
|
||||
void DocumentView::onBeforeRemoveLayer(DocumentEvent& ev)
|
||||
{
|
||||
Sprite* sprite = ev.sprite();
|
||||
Layer* layer = ev.layer();
|
||||
|
@ -64,7 +64,7 @@ namespace app {
|
||||
void onSpritePixelsModified(DocumentEvent& ev) OVERRIDE;
|
||||
void onLayerMergedDown(DocumentEvent& ev) OVERRIDE;
|
||||
void onAddLayer(DocumentEvent& ev) OVERRIDE;
|
||||
void onRemoveLayer(DocumentEvent& ev) OVERRIDE;
|
||||
void onBeforeRemoveLayer(DocumentEvent& ev) OVERRIDE;
|
||||
void onAddFrame(DocumentEvent& ev) OVERRIDE;
|
||||
void onRemoveFrame(DocumentEvent& ev) OVERRIDE;
|
||||
void onTotalFramesChanged(DocumentEvent& ev) OVERRIDE;
|
||||
|
@ -180,6 +180,8 @@ void Timeline::updateUsingEditor(Editor* editor)
|
||||
DocumentView* view = m_editor->getDocumentView();
|
||||
view->getDocumentLocation(&location);
|
||||
|
||||
location.document()->addObserver(this);
|
||||
|
||||
// If we are already in the same position as the "editor", we don't
|
||||
// need to update the at all timeline.
|
||||
if (m_document == location.document() &&
|
||||
@ -859,11 +861,13 @@ void Timeline::onPreferredSize(PreferredSizeEvent& ev)
|
||||
void Timeline::onPaint(ui::PaintEvent& ev)
|
||||
{
|
||||
Graphics* g = ev.getGraphics();
|
||||
bool noDoc = (m_document == NULL);
|
||||
if (noDoc)
|
||||
goto paintNoDoc;
|
||||
|
||||
if (!m_document) {
|
||||
drawPart(g, getClientBounds(), NULL, m_timelinePaddingStyle);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Lock the sprite to read/render it.
|
||||
const DocumentReader documentReader(m_document);
|
||||
|
||||
int layer, first_layer, last_layer;
|
||||
FrameNumber frame, first_frame, last_frame;
|
||||
@ -925,6 +929,14 @@ void Timeline::onPaint(ui::PaintEvent& ev)
|
||||
}
|
||||
|
||||
drawPaddings(g);
|
||||
}
|
||||
catch (const LockedDocumentException&) {
|
||||
noDoc = true;
|
||||
}
|
||||
|
||||
paintNoDoc:;
|
||||
if (noDoc)
|
||||
drawPart(g, getClientBounds(), NULL, m_timelinePaddingStyle);
|
||||
}
|
||||
|
||||
void Timeline::onCommandAfterExecution(Context* context)
|
||||
@ -954,7 +966,7 @@ void Timeline::onAddLayer(DocumentEvent& ev)
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::onRemoveLayer(DocumentEvent& ev)
|
||||
void Timeline::onAfterRemoveLayer(DocumentEvent& ev)
|
||||
{
|
||||
Sprite* sprite = ev.sprite();
|
||||
Layer* layer = ev.layer();
|
||||
|
@ -114,7 +114,7 @@ namespace app {
|
||||
|
||||
// DocumentObserver impl.
|
||||
void onAddLayer(DocumentEvent& ev) OVERRIDE;
|
||||
void onRemoveLayer(DocumentEvent& ev) OVERRIDE;
|
||||
void onAfterRemoveLayer(DocumentEvent& ev) OVERRIDE;
|
||||
void onAddFrame(DocumentEvent& ev) OVERRIDE;
|
||||
void onRemoveFrame(DocumentEvent& ev) OVERRIDE;
|
||||
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
// collection and will be destroyed calling the T::dispose() member
|
||||
// function.
|
||||
void addObserver(observer_type* observer) {
|
||||
ASSERT(std::find(m_observers.begin(), m_observers.end(), observer) == m_observers.end() && "You've tried to add an observer that already is in the collection");
|
||||
m_observers.push_back(observer);
|
||||
}
|
||||
|
||||
@ -48,6 +49,9 @@ public:
|
||||
iterator it = std::find(m_observers.begin(), m_observers.end(), observer);
|
||||
if (it != end())
|
||||
m_observers.erase(it);
|
||||
else {
|
||||
ASSERT(false && "You've tried to remove an observer that isn't in the collection");
|
||||
}
|
||||
}
|
||||
|
||||
void notifyObservers(void (observer_type::*method)()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user