Use ui::Window to show the animation playback instead of a custom event loop

This commit is contained in:
David Capello 2014-08-09 17:14:56 -03:00
parent d23fa2230b
commit 1e84c63042
6 changed files with 169 additions and 140 deletions

View File

@ -1,5 +1,5 @@
/* Aseprite
* Copyright (C) 2001-2013 David Capello
* Copyright (C) 2001-2014 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,8 +20,6 @@
#include "config.h"
#endif
#include <allegro.h>
#include "ui/ui.h"
#include "app/app.h"
@ -44,6 +42,126 @@
namespace app {
// TODO merge this with MiniEditor logic and create a new Editor state
using namespace ui;
class PlayAniWindow : public Window {
public:
PlayAniWindow(Context* context, Editor* editor)
: Window(DesktopWindow)
, m_editor(editor)
, m_oldFrame(editor->frame())
, m_oldFlags(m_editor->editorFlags())
, m_doc(editor->document())
, m_docSettings(context->settings()->getDocumentSettings(m_doc))
, m_oldOnionskinState(m_docSettings->getUseOnionskin())
, m_playTimer(10)
{
m_editor->setEditorFlags(Editor::kNoneFlag);
// Desactivate the onionskin
m_docSettings->setUseOnionskin(false);
// Clear extras (e.g. pen preview)
m_doc->destroyExtraCel();
setFocusStop(true); // To receive keyboard messages
m_curFrameTick = ji_clock;
m_pingPongForward = true;
m_nextFrameTime = editor->sprite()->getFrameDuration(editor->frame());
m_playTimer.Tick.connect(&PlayAniWindow::onPlaybackTick, this);
m_playTimer.start();
}
protected:
void onPlaybackTick() {
if (m_nextFrameTime >= 0) {
m_nextFrameTime -= (ji_clock - m_curFrameTick);
while (m_nextFrameTime <= 0) {
FrameNumber frame = calculate_next_frame(
m_editor->sprite(),
m_editor->frame(),
m_docSettings,
m_pingPongForward);
m_editor->setFrame(frame);
m_nextFrameTime += m_editor->sprite()->getFrameDuration(frame);
invalidate();
}
m_curFrameTick = ji_clock;
}
}
virtual bool onProcessMessage(Message* msg) OVERRIDE {
switch (msg->type()) {
case kOpenMessage:
jmouse_set_cursor(kNoCursor);
break;
case kCloseMessage:
// Restore onionskin flag
m_docSettings->setUseOnionskin(m_oldOnionskinState);
// Restore editor
m_editor->setFrame(m_oldFrame);
m_editor->setEditorFlags(m_oldFlags);
break;
case kMouseUpMessage: {
closeWindow(this);
break;
}
case kKeyDownMessage: {
KeyMessage* keyMsg = static_cast<KeyMessage*>(msg);
closeWindow(this);
return true;
}
case kSetCursorMessage:
jmouse_set_cursor(kNoCursor);
return true;
}
return Window::onProcessMessage(msg);
}
virtual void onPaint(PaintEvent& ev) OVERRIDE {
Graphics* g = ev.getGraphics();
g->fillRect(gfx::rgba(0, 0, 0), getClientBounds());
Graphics subG(g->getInternalSurface(),
m_editor->getBounds().x + g->getInternalDeltaY(),
m_editor->getBounds().y + g->getInternalDeltaY());
m_editor->drawSpriteUnclippedRect(&subG,
gfx::Rect(0, 0,
m_editor->sprite()->width(),
m_editor->sprite()->height()));
}
private:
Editor* m_editor;
FrameNumber m_oldFrame;
Editor::EditorFlags m_oldFlags;
Document* m_doc;
IDocumentSettings* m_docSettings;
bool m_oldOnionskinState;
bool m_pingPongForward;
int m_nextFrameTime;
int m_curFrameTick;
ui::Timer m_playTimer;
};
class PlayAnimationCommand : public Command {
public:
PlayAnimationCommand();
@ -54,15 +172,6 @@ protected:
void onExecute(Context* context);
};
static int speed_timer;
static void speed_timer_callback()
{
speed_timer++;
}
END_OF_STATIC_FUNCTION(speed_timer_callback);
PlayAnimationCommand::PlayAnimationCommand()
: Command("PlayAnimation",
"Play Animation",
@ -78,108 +187,27 @@ bool PlayAnimationCommand::onEnabled(Context* context)
void PlayAnimationCommand::onExecute(Context* context)
{
// Do not play one-frame images
{
ContextReader writer(context);
Sprite* sprite(writer.sprite());
if (!sprite || sprite->totalFrames() < 2)
return;
}
// Hide mini editor
MiniEditorWindow* miniEditor = App::instance()->getMainWindow()->getMiniEditor();
bool visibleMiniEditor = (miniEditor ? miniEditor->isVisible(): false);
ContextWriter writer(context);
Document* document(writer.document());
Sprite* sprite(writer.sprite());
int msecs;
bool done = false;
IDocumentSettings* docSettings = context->settings()->getDocumentSettings(document);
bool onionskin_state = docSettings->getUseOnionskin();
Palette *oldpal, *newpal;
bool pingPongForward = true;
if (sprite->totalFrames() < 2)
return;
if (visibleMiniEditor)
miniEditor->closeWindow(NULL);
// desactivate the onionskin
docSettings->setUseOnionskin(false);
ui::jmouse_hide();
FrameNumber oldFrame = current_editor->frame();
LOCK_VARIABLE(speed_timer);
LOCK_FUNCTION(speed_timer_callback);
clear_keybuf();
// Clear all the screen
clear_bitmap(ui::ji_screen);
// Clear extras (e.g. pen preview)
document->destroyExtraCel();
// Do animation
oldpal = NULL;
speed_timer = 0;
while (!done) {
msecs = sprite->getFrameDuration(current_editor->frame());
install_int_ex(speed_timer_callback, MSEC_TO_TIMER(msecs));
newpal = sprite->getPalette(current_editor->frame());
if (oldpal != newpal) {
PALETTE rgbpal;
raster::convert_palette_to_allegro(newpal, rgbpal);
set_palette(rgbpal);
oldpal = newpal;
}
current_editor->drawSpriteClipped
(gfx::Region(gfx::Rect(0, 0, sprite->width(), sprite->height())));
ui::dirty_display_flag = true;
do {
poll_mouse();
poll_keyboard();
if (keypressed() || mouse_b)
done = true;
gui_feedback();
} while (!done && (speed_timer <= 0));
if (!done) {
current_editor->setFrame(
calculate_next_frame(
sprite,
current_editor->frame(),
docSettings,
pingPongForward));
speed_timer--;
}
gui_feedback();
bool enabled = (miniEditor ? miniEditor->isMiniEditorEnabled(): false);
if (enabled) {
miniEditor->setVisible(false);
miniEditor->setMiniEditorEnabled(false);
}
// Restore onionskin flag
docSettings->setUseOnionskin(onionskin_state);
PlayAniWindow window(context, current_editor);
window.openWindowInForeground();
// If right-click or ESC
if (mouse_b == 2 || (keypressed() && (readkey()>>8) == KEY_ESC)) {
// Return to the old frame position
current_editor->setFrame(oldFrame);
}
// Refresh all
newpal = sprite->getPalette(current_editor->frame());
set_current_palette(newpal, true);
ui::Manager::getDefault()->invalidate();
gui_feedback();
while (mouse_b)
poll_mouse();
clear_keybuf();
remove_int(speed_timer_callback);
ui::jmouse_show();
if (visibleMiniEditor)
miniEditor->openWindow();
if (enabled)
miniEditor->setMiniEditorEnabled(enabled);
}
Command* CommandFactory::createPlayAnimationCommand()

View File

@ -93,8 +93,8 @@ void UndoCommand::onExecute(Context* context)
// Draw the current layer/frame (which is not undone yet) so the
// user can see the doUndo/doRedo effect.
current_editor->drawSpriteClipped
(gfx::Region(gfx::Rect(0, 0, sprite->width(), sprite->height())));
current_editor->drawSpriteClipped(
gfx::Region(gfx::Rect(0, 0, sprite->width(), sprite->height())));
ui::dirty_display_flag = true;
gui_feedback();

View File

@ -136,7 +136,7 @@ DocumentView::DocumentView(Document* document, Type type)
EditorView::AlwaysSelected))
, m_editor(type == Normal ?
new AppEditor(document):
new Editor(document, Editor::kNoneFlag)) // Don't show grid/mask in mini preview
new Editor(document, Editor::kShowOutside)) // Don't show grid/mask in mini preview
{
addChild(m_view);

View File

@ -392,7 +392,7 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc, in
if (rendered) {
// Pre-render decorator.
if (m_decorator) {
if ((m_flags & kShowDecorators) && m_decorator) {
EditorPreRenderImpl preRender(this, rendered,
Point(-source_x, -source_y), m_zoom);
m_decorator->preRenderDecorator(&preRender);
@ -457,41 +457,39 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc)
// Fill the outside (parts of the editor that aren't covered by the
// sprite).
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
g->fillRegion(theme->getColor(ThemeColor::EditorFace), outside);
if (m_flags & kShowOutside) {
g->fillRegion(theme->getColor(ThemeColor::EditorFace), outside);
}
// Draw the pixel grid
if (docSettings->getPixelGridVisible()) {
if (m_zoom > 1)
drawGrid(g, enclosingRect, Rect(0, 0, 1, 1), docSettings->getPixelGridColor());
if ((m_zoom > 1) && docSettings->getPixelGridVisible()) {
drawGrid(g, enclosingRect, Rect(0, 0, 1, 1), docSettings->getPixelGridColor());
}
// Draw the grid
if (docSettings->getGridVisible())
drawGrid(g, enclosingRect, docSettings->getGridBounds(), docSettings->getGridColor());
// Draw the borders that enclose the sprite.
enclosingRect.enlarge(1);
g->drawRect(theme->getColor(ThemeColor::EditorSpriteBorder), enclosingRect);
g->drawHLine(
theme->getColor(ThemeColor::EditorSpriteBottomBorder),
enclosingRect.x, enclosingRect.y+enclosingRect.h, enclosingRect.w);
if (m_flags & kShowOutside) {
// Draw the borders that enclose the sprite.
enclosingRect.enlarge(1);
g->drawRect(theme->getColor(ThemeColor::EditorSpriteBorder), enclosingRect);
g->drawHLine(
theme->getColor(ThemeColor::EditorSpriteBottomBorder),
enclosingRect.x, enclosingRect.y+enclosingRect.h, enclosingRect.w);
}
// Draw the mask
if (m_document->getBoundariesSegments())
drawMask(g);
// Post-render decorator.
if (m_decorator) {
if ((m_flags & kShowDecorators) && m_decorator) {
EditorPostRenderImpl postRender(this);
m_decorator->postRenderDecorator(&postRender);
}
}
void Editor::drawSpriteUnclippedRect(const gfx::Rect& rc)
{
drawSpriteUnclippedRect(getGraphics(getClientBounds()), rc);
}
void Editor::drawSpriteClipped(const gfx::Region& updateRegion)
{
Region region;
@ -507,7 +505,7 @@ void Editor::drawSpriteClipped(const gfx::Region& updateRegion)
if (clip) {
for (Region::const_iterator
it2=updateRegion.begin(), end2=updateRegion.end(); it2 != end2; ++it2) {
drawSpriteUnclippedRect(*it2);
drawSpriteUnclippedRect(getGraphics(getClientBounds()), *it2);
}
}
}
@ -522,7 +520,7 @@ void Editor::drawSpriteClipped(const gfx::Region& updateRegion)
*/
void Editor::drawMask(Graphics* g)
{
if ((m_flags & kShowMaskFlag) == 0)
if ((m_flags & kShowMask) == 0)
return;
int x1, y1, x2, y2;
@ -576,7 +574,7 @@ void Editor::drawMask(Graphics* g)
void Editor::drawMaskSafe()
{
if ((m_flags & kShowMaskFlag) == 0)
if ((m_flags & kShowMask) == 0)
return;
if (isVisible() &&
@ -612,7 +610,7 @@ void Editor::drawMaskSafe()
void Editor::drawGrid(Graphics* g, const gfx::Rect& spriteBounds, const Rect& gridBounds, const app::Color& color)
{
if ((m_flags & kShowGridFlag) == 0)
if ((m_flags & kShowGrid) == 0)
return;
// Copy the grid bounds

View File

@ -69,10 +69,13 @@ namespace app {
enum EditorFlags {
kNoneFlag = 0,
kShowGridFlag = 1,
kShowMaskFlag = 2,
kShowGrid = 1,
kShowMask = 2,
kShowOnionskin = 4,
kDefaultEditorFlags = kShowGridFlag | kShowMaskFlag | kShowOnionskin,
kShowOutside = 8,
kShowDecorators = 16,
kDefaultEditorFlags = (kShowGrid | kShowMask |
kShowOnionskin | kShowOutside | kShowDecorators),
};
enum ZoomBehavior {
@ -102,6 +105,7 @@ namespace app {
void setDecorator(EditorDecorator* decorator) { m_decorator = decorator; }
EditorFlags editorFlags() const { return m_flags; }
void setEditorFlags(EditorFlags flags) { m_flags = flags; }
Document* document() { return m_document; }
Sprite* sprite() { return m_sprite; }
@ -131,6 +135,7 @@ namespace app {
// Draws the sprite taking care of the whole clipping region.
void drawSpriteClipped(const gfx::Region& updateRegion);
void drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc);
void flashCurrentLayer();
@ -228,8 +233,6 @@ namespace app {
// You should setup the clip of the screen before calling this
// routine.
void drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc, int dx, int dy);
void drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc);
void drawSpriteUnclippedRect(const gfx::Rect& rc);
// Stack of states. The top element in the stack is the current state (m_state).
EditorStatesHistory m_statesHistory;

View File

@ -660,7 +660,7 @@ void StandbyState::Decorator::postRenderDecorator(EditorPostRender* render)
Editor* editor = render->getEditor();
// Draw transformation handles (if the mask is visible and isn't frozen).
if (editor->editorFlags() & Editor::kShowMaskFlag &&
if (editor->editorFlags() & Editor::kShowMask &&
editor->document()->isMaskVisible() &&
!editor->document()->mask()->isFrozen()) {
// And draw only when the user has a selection tool as active tool.