mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-05 18:40:37 +00:00
Use ui::Window to show the animation playback instead of a custom event loop
This commit is contained in:
parent
d23fa2230b
commit
1e84c63042
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user