mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-11 13:14:17 +00:00
Keep timeline in sync with current editor and after commands are executed
This commit is contained in:
parent
28fe226236
commit
5141079c5f
@ -75,6 +75,10 @@ public:
|
||||
App::instance()->getMainWindow()->getMiniEditor()->updateUsingEditor(this);
|
||||
}
|
||||
|
||||
void onLayerChanged(Editor* editor) OVERRIDE {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// EditorCustomizationDelegate implementation
|
||||
tools::Tool* getQuickTool(tools::Tool* currentTool) OVERRIDE {
|
||||
return get_selected_quicktool(currentTool);
|
||||
|
@ -246,6 +246,8 @@ void Editor::backToPreviousState()
|
||||
void Editor::setLayer(const Layer* layer)
|
||||
{
|
||||
m_layer = const_cast<Layer*>(layer);
|
||||
m_observers.notifyLayerChanged(this);
|
||||
|
||||
updateStatusBar();
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,9 @@ namespace app {
|
||||
|
||||
// Called when the current frame of the editor changes.
|
||||
virtual void onFrameChanged(Editor* editor) = 0;
|
||||
|
||||
// Called when the current layer of the editor changes.
|
||||
virtual void onLayerChanged(Editor* editor) = 0;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -56,4 +56,9 @@ void EditorObservers::notifyFrameChanged(Editor* editor)
|
||||
m_observers.notifyObservers(&EditorObserver::onFrameChanged, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyLayerChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onLayerChanged, editor);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -35,6 +35,7 @@ namespace app {
|
||||
void notifyStateChanged(Editor* editor);
|
||||
void notifyScrollChanged(Editor* editor);
|
||||
void notifyFrameChanged(Editor* editor);
|
||||
void notifyLayerChanged(Editor* editor);
|
||||
|
||||
private:
|
||||
base::Observers<EditorObserver> m_observers;
|
||||
|
@ -113,6 +113,7 @@ static void icon_rect(BITMAP* icon_normal, BITMAP* icon_selected, int x1, int y1
|
||||
Timeline::Timeline()
|
||||
: Widget(kGenericWidget)
|
||||
, m_context(UIContext::instance())
|
||||
, m_editor(NULL)
|
||||
, m_document(NULL)
|
||||
{
|
||||
m_context->addObserver(this);
|
||||
@ -131,8 +132,21 @@ void Timeline::updateUsingEditor(Editor* editor)
|
||||
DocumentLocation location;
|
||||
view->getDocumentLocation(&location);
|
||||
|
||||
// Do nothing, we've already viewing this document in the timeline.
|
||||
if (m_document == location.document())
|
||||
if (m_editor)
|
||||
m_editor->removeObserver(this);
|
||||
|
||||
// We always update the editor. In this way the timeline keeps in
|
||||
// sync with the active editor.
|
||||
m_editor = editor;
|
||||
if (m_editor)
|
||||
m_editor->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() &&
|
||||
m_sprite == location.sprite() &&
|
||||
m_layer == location.layer() &&
|
||||
m_frame == location.frame())
|
||||
return;
|
||||
|
||||
detachDocument();
|
||||
@ -159,9 +173,14 @@ void Timeline::detachDocument()
|
||||
if (m_document) {
|
||||
m_document->removeObserver(this);
|
||||
m_document = NULL;
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
if (m_editor) {
|
||||
m_editor->removeObserver(this);
|
||||
m_editor = NULL;
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
bool Timeline::isMovingCel() const
|
||||
@ -171,72 +190,83 @@ bool Timeline::isMovingCel() const
|
||||
|
||||
void Timeline::setLayer(Layer* layer)
|
||||
{
|
||||
ASSERT(m_editor != NULL);
|
||||
|
||||
m_layer = layer;
|
||||
if (current_editor)
|
||||
current_editor->setLayer(m_layer);
|
||||
|
||||
if (m_editor->getLayer() != layer)
|
||||
m_editor->setLayer(m_layer);
|
||||
}
|
||||
|
||||
void Timeline::setFrame(FrameNumber frame)
|
||||
{
|
||||
ASSERT(m_editor != NULL);
|
||||
|
||||
m_frame = frame;
|
||||
if (current_editor)
|
||||
current_editor->setFrame(m_frame);
|
||||
|
||||
if (m_editor->getFrame() != frame)
|
||||
m_editor->setFrame(m_frame);
|
||||
}
|
||||
|
||||
bool Timeline::onProcessMessage(Message* msg)
|
||||
{
|
||||
if (!m_document)
|
||||
return Widget::onProcessMessage(msg);
|
||||
|
||||
switch (msg->type()) {
|
||||
|
||||
case kPaintMessage: {
|
||||
gfx::Rect clip = static_cast<PaintMessage*>(msg)->rect();
|
||||
int layer, first_layer, last_layer;
|
||||
FrameNumber frame, first_frame, last_frame;
|
||||
case kPaintMessage:
|
||||
if (m_document) {
|
||||
gfx::Rect clip = static_cast<PaintMessage*>(msg)->rect();
|
||||
int layer, first_layer, last_layer;
|
||||
FrameNumber frame, first_frame, last_frame;
|
||||
|
||||
getDrawableLayers(clip, &first_layer, &last_layer);
|
||||
getDrawableFrames(clip, &first_frame, &last_frame);
|
||||
getDrawableLayers(clip, &first_layer, &last_layer);
|
||||
getDrawableFrames(clip, &first_frame, &last_frame);
|
||||
|
||||
// Draw the header for layers.
|
||||
drawHeader(clip);
|
||||
// Draw the header for layers.
|
||||
drawHeader(clip);
|
||||
|
||||
// Draw the header for each visible frame.
|
||||
for (frame=first_frame; frame<=last_frame; ++frame)
|
||||
drawHeaderFrame(clip, frame);
|
||||
// Draw the header for each visible frame.
|
||||
for (frame=first_frame; frame<=last_frame; ++frame)
|
||||
drawHeaderFrame(clip, frame);
|
||||
|
||||
// Draw the separator.
|
||||
drawSeparator(clip);
|
||||
// Draw the separator.
|
||||
drawSeparator(clip);
|
||||
|
||||
// Draw each visible layer.
|
||||
for (layer=first_layer; layer<=last_layer; layer++) {
|
||||
drawLayer(clip, layer);
|
||||
// Draw each visible layer.
|
||||
for (layer=first_layer; layer<=last_layer; layer++) {
|
||||
drawLayer(clip, layer);
|
||||
|
||||
// Get the first CelIterator to be drawn (it is the first cel with cel->frame >= first_frame)
|
||||
CelIterator it, end;
|
||||
Layer* layerPtr = m_layers[layer];
|
||||
if (layerPtr->isImage()) {
|
||||
it = static_cast<LayerImage*>(layerPtr)->getCelBegin();
|
||||
end = static_cast<LayerImage*>(layerPtr)->getCelEnd();
|
||||
for (; it != end && (*it)->getFrame() < first_frame; ++it)
|
||||
;
|
||||
// Get the first CelIterator to be drawn (it is the first cel with cel->frame >= first_frame)
|
||||
CelIterator it, end;
|
||||
Layer* layerPtr = m_layers[layer];
|
||||
if (layerPtr->isImage()) {
|
||||
it = static_cast<LayerImage*>(layerPtr)->getCelBegin();
|
||||
end = static_cast<LayerImage*>(layerPtr)->getCelEnd();
|
||||
for (; it != end && (*it)->getFrame() < first_frame; ++it)
|
||||
;
|
||||
}
|
||||
|
||||
// Draw every visible cel for each layer.
|
||||
for (frame=first_frame; frame<=last_frame; ++frame) {
|
||||
Cel* cel = (layerPtr->isImage() && it != end && (*it)->getFrame() == frame ? *it: NULL);
|
||||
|
||||
drawCel(clip, layer, frame, cel);
|
||||
|
||||
if (cel)
|
||||
++it; // Go to next cel
|
||||
}
|
||||
}
|
||||
|
||||
// Draw every visible cel for each layer.
|
||||
for (frame=first_frame; frame<=last_frame; ++frame) {
|
||||
Cel* cel = (layerPtr->isImage() && it != end && (*it)->getFrame() == frame ? *it: NULL);
|
||||
|
||||
drawCel(clip, layer, frame, cel);
|
||||
|
||||
if (cel)
|
||||
++it; // Go to next cel
|
||||
}
|
||||
drawLayerPadding();
|
||||
}
|
||||
else {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
||||
rectfill(ji_screen,
|
||||
getBounds().x, getBounds().y,
|
||||
getBounds().x2()-1,
|
||||
getBounds().y2()-1,
|
||||
to_system(theme->getColor(ThemeColor::Face)));
|
||||
}
|
||||
|
||||
drawLayerPadding();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case kTimerMessage:
|
||||
break;
|
||||
@ -250,6 +280,9 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
break;
|
||||
|
||||
case kMouseDownMessage:
|
||||
if (!m_document)
|
||||
break;
|
||||
|
||||
if (static_cast<MouseMessage*>(msg)->middle() || m_space_pressed) {
|
||||
captureMouse();
|
||||
m_state = STATE_SCROLLING;
|
||||
@ -351,6 +384,9 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
break;
|
||||
|
||||
case kMouseMoveMessage: {
|
||||
if (!m_document)
|
||||
break;
|
||||
|
||||
int hot_part = A_PART_NOTHING;
|
||||
int hot_layer = -1;
|
||||
FrameNumber hot_frame(-1);
|
||||
@ -444,6 +480,8 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
|
||||
case kMouseUpMessage:
|
||||
if (hasCapture()) {
|
||||
ASSERT(m_document != NULL);
|
||||
|
||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||
|
||||
releaseMouse();
|
||||
@ -637,68 +675,6 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case kKeyDownMessage: {
|
||||
Command* command = NULL;
|
||||
Params* params = NULL;
|
||||
get_command_from_key_message(msg, &command, ¶ms);
|
||||
|
||||
// Undo or redo.
|
||||
if (command && (strcmp(command->short_name(), CommandId::Undo) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::Redo) == 0)) {
|
||||
if (command->isEnabled(UIContext::instance())) {
|
||||
UIContext::instance()->executeCommand(command, params);
|
||||
|
||||
destroy_thumbnails();
|
||||
regenerateLayers();
|
||||
showCurrentCel();
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// New_frame, remove_frame, new_cel, remove_cel.
|
||||
if (command != NULL) {
|
||||
if (strcmp(command->short_name(), CommandId::NewFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::RemoveCel) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::RemoveFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoFirstFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoPreviousFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoPreviousLayer) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoNextFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoNextLayer) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoLastFrame) == 0) {
|
||||
// execute the command
|
||||
UIContext::instance()->executeCommand(command, params);
|
||||
|
||||
showCurrentCel();
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(command->short_name(), CommandId::NewLayer) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::RemoveLayer) == 0) {
|
||||
// execute the command
|
||||
UIContext::instance()->executeCommand(command);
|
||||
|
||||
regenerateLayers();
|
||||
showCurrentCel();
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (static_cast<KeyMessage*>(msg)->scancode()) {
|
||||
case kKeySpace:
|
||||
m_space_pressed = true;
|
||||
setCursor(jmouse_x(0), jmouse_y(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case kKeyUpMessage:
|
||||
switch (static_cast<KeyMessage*>(msg)->scancode()) {
|
||||
|
||||
@ -715,32 +691,34 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
}
|
||||
break;
|
||||
|
||||
case kMouseWheelMessage: {
|
||||
int dz = jmouse_z(1) - jmouse_z(0);
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
case kMouseWheelMessage:
|
||||
if (m_document) {
|
||||
int dz = jmouse_z(1) - jmouse_z(0);
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
|
||||
if (msg->ctrlPressed())
|
||||
dx = dz * FRMSIZE;
|
||||
else
|
||||
dy = dz * LAYSIZE;
|
||||
if (msg->ctrlPressed())
|
||||
dx = dz * FRMSIZE;
|
||||
else
|
||||
dy = dz * LAYSIZE;
|
||||
|
||||
if (msg->shiftPressed()) {
|
||||
dx *= 3;
|
||||
dy *= 3;
|
||||
if (msg->shiftPressed()) {
|
||||
dx *= 3;
|
||||
dy *= 3;
|
||||
}
|
||||
|
||||
setScroll(m_scroll_x+dx,
|
||||
m_scroll_y+dy, true);
|
||||
}
|
||||
|
||||
setScroll(m_scroll_x+dx,
|
||||
m_scroll_y+dy, true);
|
||||
break;
|
||||
}
|
||||
|
||||
case kSetCursorMessage: {
|
||||
gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
|
||||
setCursor(mousePos.x, mousePos.y);
|
||||
return true;
|
||||
}
|
||||
|
||||
case kSetCursorMessage:
|
||||
if (m_document) {
|
||||
gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
|
||||
setCursor(mousePos.x, mousePos.y);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return Widget::onProcessMessage(msg);
|
||||
@ -752,6 +730,16 @@ void Timeline::onPreferredSize(PreferredSizeEvent& ev)
|
||||
ev.setPreferredSize(Size(32, 32));
|
||||
}
|
||||
|
||||
void Timeline::onCommandAfterExecution(Context* context)
|
||||
{
|
||||
if (!m_document)
|
||||
return;
|
||||
|
||||
regenerateLayers();
|
||||
showCurrentCel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::onRemoveDocument(Context* context, Document* document)
|
||||
{
|
||||
if (document == m_document)
|
||||
@ -761,7 +749,12 @@ void Timeline::onRemoveDocument(Context* context, Document* document)
|
||||
void Timeline::onAddLayer(DocumentEvent& ev)
|
||||
{
|
||||
ASSERT(ev.layer() != NULL);
|
||||
|
||||
setLayer(ev.layer());
|
||||
|
||||
regenerateLayers();
|
||||
showCurrentCel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::onRemoveLayer(DocumentEvent& ev)
|
||||
@ -785,11 +778,18 @@ void Timeline::onRemoveLayer(DocumentEvent& ev)
|
||||
|
||||
setLayer(layer_select);
|
||||
}
|
||||
|
||||
regenerateLayers();
|
||||
showCurrentCel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::onAddFrame(DocumentEvent& ev)
|
||||
{
|
||||
setFrame(ev.frame());
|
||||
|
||||
showCurrentCel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::onRemoveFrame(DocumentEvent& ev)
|
||||
@ -805,13 +805,21 @@ void Timeline::onRemoveFrame(DocumentEvent& ev)
|
||||
else if (getFrame() >= getSprite()->getTotalFrames()) {
|
||||
setFrame(getSprite()->getLastFrame());
|
||||
}
|
||||
|
||||
showCurrentCel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::onTotalFramesChanged(DocumentEvent& ev)
|
||||
void Timeline::onFrameChanged(Editor* editor)
|
||||
{
|
||||
if (getFrame() >= getSprite()->getTotalFrames()) {
|
||||
setFrame(getSprite()->getLastFrame());
|
||||
}
|
||||
setFrame(editor->getFrame());
|
||||
showCurrentCel();
|
||||
}
|
||||
|
||||
void Timeline::onLayerChanged(Editor* editor)
|
||||
{
|
||||
setLayer(editor->getLayer());
|
||||
showCurrentCel();
|
||||
}
|
||||
|
||||
void Timeline::setCursor(int x, int y)
|
||||
@ -1248,13 +1256,19 @@ bool Timeline::drawPart(int part, int layer, FrameNumber frame)
|
||||
|
||||
void Timeline::regenerateLayers()
|
||||
{
|
||||
m_layers.clear();
|
||||
ASSERT(m_document != NULL);
|
||||
ASSERT(m_sprite != NULL);
|
||||
|
||||
size_t nlayers = m_sprite->countLayers();
|
||||
if (nlayers > 0) {
|
||||
m_layers.resize(nlayers, NULL);
|
||||
for (size_t c=0; c<nlayers; c++)
|
||||
m_layers[c] = m_sprite->indexToLayer(LayerIndex(nlayers-c-1));
|
||||
if (m_layers.size() != nlayers) {
|
||||
if (nlayers > 0)
|
||||
m_layers.resize(nlayers, NULL);
|
||||
else
|
||||
m_layers.clear();
|
||||
}
|
||||
|
||||
for (size_t c=0; c<nlayers; c++)
|
||||
m_layers[c] = m_sprite->indexToLayer(LayerIndex(nlayers-c-1));
|
||||
}
|
||||
|
||||
void Timeline::hotThis(int hot_part, int hot_layer, FrameNumber hot_frame)
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "app/context_observer.h"
|
||||
#include "app/document_observer.h"
|
||||
#include "app/ui/editor/editor_observer.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "raster/frame_number.h"
|
||||
#include "ui/widget.h"
|
||||
@ -42,7 +43,8 @@ namespace app {
|
||||
|
||||
class Timeline : public ui::Widget
|
||||
, public ContextObserver
|
||||
, public DocumentObserver {
|
||||
, public DocumentObserver
|
||||
, public EditorObserver {
|
||||
public:
|
||||
enum State {
|
||||
STATE_STANDBY,
|
||||
@ -78,11 +80,18 @@ namespace app {
|
||||
void onRemoveLayer(DocumentEvent& ev) OVERRIDE;
|
||||
void onAddFrame(DocumentEvent& ev) OVERRIDE;
|
||||
void onRemoveFrame(DocumentEvent& ev) OVERRIDE;
|
||||
void onTotalFramesChanged(DocumentEvent& ev) OVERRIDE;
|
||||
|
||||
// ContextObserver impl.
|
||||
void onCommandAfterExecution(Context* context) OVERRIDE;
|
||||
void onRemoveDocument(Context* context, Document* document) OVERRIDE;
|
||||
|
||||
// EditorObserver impl.
|
||||
void dispose() OVERRIDE { }
|
||||
void onStateChanged(Editor* editor) OVERRIDE { }
|
||||
void onScrollChanged(Editor* editor) OVERRIDE { }
|
||||
void onFrameChanged(Editor* editor) OVERRIDE;
|
||||
void onLayerChanged(Editor* editor) OVERRIDE;
|
||||
|
||||
private:
|
||||
void detachDocument();
|
||||
void setCursor(int x, int y);
|
||||
@ -108,6 +117,7 @@ namespace app {
|
||||
int getLayerIndex(const Layer* layer);
|
||||
|
||||
Context* m_context;
|
||||
Editor* m_editor;
|
||||
Document* m_document;
|
||||
Sprite* m_sprite;
|
||||
Layer* m_layer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user