mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-10 03:44:16 +00:00
Add new Editor PlayState so we can have several editors playing animations
With this change we share the logic to play animations between the Preview window and Enter key/play animation.
This commit is contained in:
parent
7448db3959
commit
a42d9d1c00
@ -306,6 +306,7 @@ add_library(app-lib
|
|||||||
ui/editor/moving_pixels_state.cpp
|
ui/editor/moving_pixels_state.cpp
|
||||||
ui/editor/navigate_state.cpp
|
ui/editor/navigate_state.cpp
|
||||||
ui/editor/pixels_movement.cpp
|
ui/editor/pixels_movement.cpp
|
||||||
|
ui/editor/play_state.cpp
|
||||||
ui/editor/scrolling_state.cpp
|
ui/editor/scrolling_state.cpp
|
||||||
ui/editor/select_box_state.cpp
|
ui/editor/select_box_state.cpp
|
||||||
ui/editor/standby_state.cpp
|
ui/editor/standby_state.cpp
|
||||||
|
@ -9,146 +9,16 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ui/ui.h"
|
|
||||||
|
|
||||||
#include "app/app.h"
|
|
||||||
#include "app/commands/command.h"
|
#include "app/commands/command.h"
|
||||||
#include "app/context.h"
|
#include "app/context.h"
|
||||||
#include "app/context_access.h"
|
#include "app/context_access.h"
|
||||||
#include "app/handle_anidir.h"
|
|
||||||
#include "app/loop_tag.h"
|
|
||||||
#include "app/modules/editors.h"
|
#include "app/modules/editors.h"
|
||||||
#include "app/modules/gui.h"
|
|
||||||
#include "app/modules/palettes.h"
|
|
||||||
#include "app/pref/preferences.h"
|
|
||||||
#include "app/settings/settings.h"
|
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
#include "app/ui/main_window.h"
|
|
||||||
#include "app/ui/preview_editor.h"
|
|
||||||
#include "doc/image.h"
|
|
||||||
#include "doc/palette.h"
|
|
||||||
#include "doc/sprite.h"
|
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
||||||
// TODO merge this with PreviewEditor logic and create a new Editor state
|
|
||||||
|
|
||||||
using namespace ui;
|
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_docPref(App::instance()->preferences().document(m_doc))
|
|
||||||
, m_oldOnionskinState(m_docPref.onionskin.active())
|
|
||||||
, m_playTimer(10)
|
|
||||||
{
|
|
||||||
m_editor->setEditorFlags(Editor::kNoneFlag);
|
|
||||||
|
|
||||||
// Desactivate the onionskin
|
|
||||||
m_docPref.onionskin.active(false);
|
|
||||||
|
|
||||||
// Clear extras (e.g. pen preview)
|
|
||||||
m_doc->destroyExtraCel();
|
|
||||||
|
|
||||||
setFocusStop(true); // To receive keyboard messages
|
|
||||||
|
|
||||||
m_curFrameTick = ui::clock();
|
|
||||||
m_pingPongForward = true;
|
|
||||||
m_nextFrameTime = editor->sprite()->frameDuration(editor->frame());
|
|
||||||
|
|
||||||
m_playTimer.Tick.connect(&PlayAniWindow::onPlaybackTick, this);
|
|
||||||
m_playTimer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void onPlaybackTick() {
|
|
||||||
if (m_nextFrameTime >= 0) {
|
|
||||||
m_nextFrameTime -= (ui::clock() - m_curFrameTick);
|
|
||||||
|
|
||||||
FrameTag* loopTag = get_loop_tag(m_editor->sprite());
|
|
||||||
|
|
||||||
while (m_nextFrameTime <= 0) {
|
|
||||||
frame_t frame = calculate_next_frame(
|
|
||||||
m_editor->sprite(),
|
|
||||||
m_editor->frame(), loopTag,
|
|
||||||
m_pingPongForward);
|
|
||||||
|
|
||||||
m_editor->setFrame(frame);
|
|
||||||
m_nextFrameTime += m_editor->sprite()->frameDuration(frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidate();
|
|
||||||
m_curFrameTick = ui::clock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool onProcessMessage(Message* msg) override {
|
|
||||||
switch (msg->type()) {
|
|
||||||
|
|
||||||
case kOpenMessage:
|
|
||||||
ui::set_mouse_cursor(kNoCursor);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kCloseMessage:
|
|
||||||
// Restore onionskin flag
|
|
||||||
m_docPref.onionskin.active(m_oldOnionskinState);
|
|
||||||
|
|
||||||
// Restore editor
|
|
||||||
m_editor->setFrame(m_oldFrame);
|
|
||||||
m_editor->setEditorFlags(m_oldFlags);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kMouseUpMessage: {
|
|
||||||
closeWindow(this);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case kKeyDownMessage: {
|
|
||||||
closeWindow(this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case kSetCursorMessage:
|
|
||||||
ui::set_mouse_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;
|
|
||||||
frame_t m_oldFrame;
|
|
||||||
Editor::EditorFlags m_oldFlags;
|
|
||||||
Document* m_doc;
|
|
||||||
DocumentPreferences& m_docPref;
|
|
||||||
bool m_oldOnionskinState;
|
|
||||||
bool m_pingPongForward;
|
|
||||||
|
|
||||||
int m_nextFrameTime;
|
|
||||||
int m_curFrameTick;
|
|
||||||
ui::Timer m_playTimer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PlayAnimationCommand : public Command {
|
class PlayAnimationCommand : public Command {
|
||||||
public:
|
public:
|
||||||
PlayAnimationCommand();
|
PlayAnimationCommand();
|
||||||
@ -182,18 +52,14 @@ void PlayAnimationCommand::onExecute(Context* context)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide mini editor
|
ASSERT(current_editor);
|
||||||
PreviewEditorWindow* preview =
|
if (!current_editor)
|
||||||
App::instance()->getMainWindow()->getPreviewEditor();
|
return;
|
||||||
bool enabled = (preview ? preview->isPreviewEnabled(): false);
|
|
||||||
if (enabled)
|
|
||||||
preview->setPreviewEnabled(false);
|
|
||||||
|
|
||||||
PlayAniWindow window(context, current_editor);
|
if (current_editor->isPlaying())
|
||||||
window.openWindowInForeground();
|
current_editor->stop();
|
||||||
|
else
|
||||||
if (enabled)
|
current_editor->play();
|
||||||
preview->setPreviewEnabled(enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Command* CommandFactory::createPlayAnimationCommand()
|
Command* CommandFactory::createPlayAnimationCommand()
|
||||||
|
@ -18,6 +18,14 @@ namespace app {
|
|||||||
|
|
||||||
const char* kLoopTagName = "Loop";
|
const char* kLoopTagName = "Loop";
|
||||||
|
|
||||||
|
doc::FrameTag* get_animation_tag(const doc::Sprite* sprite, doc::frame_t frame)
|
||||||
|
{
|
||||||
|
doc::FrameTag* tag = get_shortest_tag(sprite, frame);
|
||||||
|
if (!tag)
|
||||||
|
tag = get_loop_tag(sprite);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
doc::FrameTag* get_shortest_tag(const doc::Sprite* sprite, doc::frame_t frame)
|
doc::FrameTag* get_shortest_tag(const doc::Sprite* sprite, doc::frame_t frame)
|
||||||
{
|
{
|
||||||
const doc::FrameTag* found = nullptr;
|
const doc::FrameTag* found = nullptr;
|
||||||
@ -33,7 +41,7 @@ doc::FrameTag* get_shortest_tag(const doc::Sprite* sprite, doc::frame_t frame)
|
|||||||
return const_cast<doc::FrameTag*>(found);
|
return const_cast<doc::FrameTag*>(found);
|
||||||
}
|
}
|
||||||
|
|
||||||
doc::FrameTag* get_loop_tag(doc::Sprite* sprite)
|
doc::FrameTag* get_loop_tag(const doc::Sprite* sprite)
|
||||||
{
|
{
|
||||||
// Get tag with special "Loop" name
|
// Get tag with special "Loop" name
|
||||||
for (doc::FrameTag* tag : sprite->frameTags())
|
for (doc::FrameTag* tag : sprite->frameTags())
|
||||||
|
@ -18,8 +18,9 @@ namespace doc {
|
|||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
||||||
|
doc::FrameTag* get_animation_tag(const doc::Sprite* sprite, doc::frame_t frame);
|
||||||
|
doc::FrameTag* get_loop_tag(const doc::Sprite* sprite);
|
||||||
doc::FrameTag* get_shortest_tag(const doc::Sprite* sprite, doc::frame_t frame);
|
doc::FrameTag* get_shortest_tag(const doc::Sprite* sprite, doc::frame_t frame);
|
||||||
doc::FrameTag* get_loop_tag(doc::Sprite* sprite);
|
|
||||||
doc::FrameTag* create_loop_tag(doc::frame_t from, doc::frame_t to);
|
doc::FrameTag* create_loop_tag(doc::frame_t from, doc::frame_t to);
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -169,6 +169,7 @@ private:
|
|||||||
|
|
||||||
DocumentView::DocumentView(Document* document, Type type)
|
DocumentView::DocumentView(Document* document, Type type)
|
||||||
: Box(JI_VERTICAL)
|
: Box(JI_VERTICAL)
|
||||||
|
, m_type(type)
|
||||||
, m_document(document)
|
, m_document(document)
|
||||||
, m_view(new EditorView(type == Normal ? EditorView::CurrentEditorMode:
|
, m_view(new EditorView(type == Normal ? EditorView::CurrentEditorMode:
|
||||||
EditorView::AlwaysSelected))
|
EditorView::AlwaysSelected))
|
||||||
|
@ -40,6 +40,8 @@ namespace app {
|
|||||||
void getDocumentLocation(DocumentLocation* location) const;
|
void getDocumentLocation(DocumentLocation* location) const;
|
||||||
Editor* getEditor() { return m_editor; }
|
Editor* getEditor() { return m_editor; }
|
||||||
|
|
||||||
|
bool isPreview() { return m_type == Preview; }
|
||||||
|
|
||||||
// TabView implementation
|
// TabView implementation
|
||||||
std::string getTabText() override;
|
std::string getTabText() override;
|
||||||
TabIcon getTabIcon() override;
|
TabIcon getTabIcon() override;
|
||||||
@ -67,6 +69,7 @@ namespace app {
|
|||||||
bool onProcessMessage(ui::Message* msg) override;
|
bool onProcessMessage(ui::Message* msg) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Type m_type;
|
||||||
Document* m_document;
|
Document* m_document;
|
||||||
ui::View* m_view;
|
ui::View* m_view;
|
||||||
Editor* m_editor;
|
Editor* m_editor;
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "app/ui/editor/editor_decorator.h"
|
#include "app/ui/editor/editor_decorator.h"
|
||||||
#include "app/ui/editor/moving_pixels_state.h"
|
#include "app/ui/editor/moving_pixels_state.h"
|
||||||
#include "app/ui/editor/pixels_movement.h"
|
#include "app/ui/editor/pixels_movement.h"
|
||||||
|
#include "app/ui/editor/play_state.h"
|
||||||
#include "app/ui/editor/scoped_cursor.h"
|
#include "app/ui/editor/scoped_cursor.h"
|
||||||
#include "app/ui/editor/standby_state.h"
|
#include "app/ui/editor/standby_state.h"
|
||||||
#include "app/ui/main_window.h"
|
#include "app/ui/main_window.h"
|
||||||
@ -1497,6 +1498,23 @@ void Editor::notifyScrollChanged()
|
|||||||
m_observers.notifyScrollChanged(this);
|
m_observers.notifyScrollChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Editor::play()
|
||||||
|
{
|
||||||
|
if (!dynamic_cast<PlayState*>(m_state.get()))
|
||||||
|
setState(EditorStatePtr(new PlayState));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Editor::stop()
|
||||||
|
{
|
||||||
|
if (dynamic_cast<PlayState*>(m_state.get()))
|
||||||
|
backToPreviousState();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Editor::isPlaying() const
|
||||||
|
{
|
||||||
|
return (dynamic_cast<PlayState*>(m_state.get()) != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ImageBufferPtr Editor::getRenderImageBuffer()
|
ImageBufferPtr Editor::getRenderImageBuffer()
|
||||||
{
|
{
|
||||||
|
@ -188,6 +188,11 @@ namespace app {
|
|||||||
// position.
|
// position.
|
||||||
void notifyScrollChanged();
|
void notifyScrollChanged();
|
||||||
|
|
||||||
|
// Animation control
|
||||||
|
void play();
|
||||||
|
void stop();
|
||||||
|
bool isPlaying() const;
|
||||||
|
|
||||||
// Returns the buffer used to render editor viewports.
|
// Returns the buffer used to render editor viewports.
|
||||||
// E.g. It can be re-used by PreviewCommand
|
// E.g. It can be re-used by PreviewCommand
|
||||||
static ImageBufferPtr getRenderImageBuffer();
|
static ImageBufferPtr getRenderImageBuffer();
|
||||||
|
116
src/app/ui/editor/play_state.cpp
Normal file
116
src/app/ui/editor/play_state.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2001-2015 David Capello
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License version 2 as
|
||||||
|
// published by the Free Software Foundation.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "app/ui/editor/play_state.h"
|
||||||
|
|
||||||
|
#include "app/handle_anidir.h"
|
||||||
|
#include "app/loop_tag.h"
|
||||||
|
#include "app/ui/editor/editor.h"
|
||||||
|
#include "app/ui/editor/scrolling_state.h"
|
||||||
|
#include "app/ui_context.h"
|
||||||
|
#include "ui/system.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
using namespace ui;
|
||||||
|
|
||||||
|
PlayState::PlayState()
|
||||||
|
: m_playTimer(10)
|
||||||
|
, m_pingPongForward(true)
|
||||||
|
, m_nextFrameTime(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayState::onAfterChangeState(Editor* editor)
|
||||||
|
{
|
||||||
|
StateWithWheelBehavior::onAfterChangeState(editor);
|
||||||
|
|
||||||
|
m_editor = editor;
|
||||||
|
m_nextFrameTime = editor->sprite()->frameDuration(editor->frame());
|
||||||
|
m_curFrameTick = ui::clock();
|
||||||
|
m_pingPongForward = true;
|
||||||
|
m_refFrame = editor->frame();
|
||||||
|
|
||||||
|
m_playTimer.Tick.connect(&PlayState::onPlaybackTick, this);
|
||||||
|
m_playTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorState::BeforeChangeAction PlayState::onBeforeChangeState(Editor* editor, EditorState* newState)
|
||||||
|
{
|
||||||
|
m_editor->setFrame(m_refFrame);
|
||||||
|
m_playTimer.stop();
|
||||||
|
return KeepState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayState::onMouseDown(Editor* editor, MouseMessage* msg)
|
||||||
|
{
|
||||||
|
if (editor->hasCapture())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// When an editor is clicked the current view is changed.
|
||||||
|
UIContext* context = UIContext::instance();
|
||||||
|
context->setActiveView(editor->getDocumentView());
|
||||||
|
|
||||||
|
// Start scroll loop
|
||||||
|
EditorStatePtr newState(new ScrollingState());
|
||||||
|
editor->setState(newState);
|
||||||
|
newState->onMouseDown(editor, msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||||
|
{
|
||||||
|
editor->releaseMouse();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayState::onMouseMove(Editor* editor, MouseMessage* msg)
|
||||||
|
{
|
||||||
|
editor->moveDrawingCursor();
|
||||||
|
editor->updateStatusBar();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayState::onKeyDown(Editor* editor, KeyMessage* msg)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayState::onKeyUp(Editor* editor, KeyMessage* msg)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayState::onPlaybackTick()
|
||||||
|
{
|
||||||
|
if (m_nextFrameTime < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_nextFrameTime -= (ui::clock() - m_curFrameTick);
|
||||||
|
|
||||||
|
doc::Sprite* sprite = m_editor->sprite();
|
||||||
|
doc::FrameTag* tag = get_animation_tag(sprite, m_refFrame);
|
||||||
|
|
||||||
|
while (m_nextFrameTime <= 0) {
|
||||||
|
doc::frame_t frame = calculate_next_frame(
|
||||||
|
sprite,
|
||||||
|
m_editor->frame(), tag,
|
||||||
|
m_pingPongForward);
|
||||||
|
|
||||||
|
m_editor->setFrame(frame);
|
||||||
|
m_nextFrameTime += m_editor->sprite()->frameDuration(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_curFrameTick = ui::clock();
|
||||||
|
m_editor->invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
47
src/app/ui/editor/play_state.h
Normal file
47
src/app/ui/editor/play_state.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2001-2015 David Capello
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License version 2 as
|
||||||
|
// published by the Free Software Foundation.
|
||||||
|
|
||||||
|
#ifndef APP_UI_EDITOR_PLAY_STATE_H_INCLUDED
|
||||||
|
#define APP_UI_EDITOR_PLAY_STATE_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "app/ui/editor/state_with_wheel_behavior.h"
|
||||||
|
#include "doc/frame.h"
|
||||||
|
#include "ui/timer.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
class PlayState : public StateWithWheelBehavior {
|
||||||
|
public:
|
||||||
|
PlayState();
|
||||||
|
|
||||||
|
void onAfterChangeState(Editor* editor) override;
|
||||||
|
BeforeChangeAction onBeforeChangeState(Editor* editor, EditorState* newState) override;
|
||||||
|
bool onMouseDown(Editor* editor, ui::MouseMessage* msg) override;
|
||||||
|
bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
|
||||||
|
bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
|
||||||
|
bool onKeyDown(Editor* editor, ui::KeyMessage* msg) override;
|
||||||
|
bool onKeyUp(Editor* editor, ui::KeyMessage* msg) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onPlaybackTick();
|
||||||
|
|
||||||
|
Editor* m_editor;
|
||||||
|
ui::Timer m_playTimer;
|
||||||
|
|
||||||
|
// Number of milliseconds to go to the next frame if m_playTimer
|
||||||
|
// is activated.
|
||||||
|
int m_nextFrameTime;
|
||||||
|
int m_curFrameTick;
|
||||||
|
|
||||||
|
bool m_pingPongForward;
|
||||||
|
doc::frame_t m_refFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "app/document.h"
|
#include "app/document.h"
|
||||||
#include "app/handle_anidir.h"
|
|
||||||
#include "app/ini_file.h"
|
#include "app/ini_file.h"
|
||||||
#include "app/loop_tag.h"
|
#include "app/loop_tag.h"
|
||||||
#include "app/modules/editors.h"
|
#include "app/modules/editors.h"
|
||||||
@ -101,7 +100,7 @@ public:
|
|||||||
setDecorative(true);
|
setDecorative(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPlaying() { return m_isPlaying; }
|
bool isPlaying() const { return m_isPlaying; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onClick(Event& ev) override
|
void onClick(Event& ev) override
|
||||||
@ -158,8 +157,6 @@ PreviewEditorWindow::PreviewEditorWindow()
|
|||||||
, m_docView(NULL)
|
, m_docView(NULL)
|
||||||
, m_centerButton(new MiniCenterButton())
|
, m_centerButton(new MiniCenterButton())
|
||||||
, m_playButton(new MiniPlayButton())
|
, m_playButton(new MiniPlayButton())
|
||||||
, m_playTimer(10)
|
|
||||||
, m_pingPongForward(true)
|
|
||||||
, m_refFrame(0)
|
, m_refFrame(0)
|
||||||
{
|
{
|
||||||
child_spacing = 0;
|
child_spacing = 0;
|
||||||
@ -173,8 +170,6 @@ PreviewEditorWindow::PreviewEditorWindow()
|
|||||||
|
|
||||||
addChild(m_centerButton);
|
addChild(m_centerButton);
|
||||||
addChild(m_playButton);
|
addChild(m_playButton);
|
||||||
|
|
||||||
m_playTimer.Tick.connect(&PreviewEditorWindow::onPlaybackTick, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PreviewEditorWindow::~PreviewEditorWindow()
|
PreviewEditorWindow::~PreviewEditorWindow()
|
||||||
@ -259,24 +254,15 @@ void PreviewEditorWindow::onCenterClicked()
|
|||||||
void PreviewEditorWindow::onPlayClicked()
|
void PreviewEditorWindow::onPlayClicked()
|
||||||
{
|
{
|
||||||
Editor* miniEditor = (m_docView ? m_docView->getEditor(): nullptr);
|
Editor* miniEditor = (m_docView ? m_docView->getEditor(): nullptr);
|
||||||
|
if (!miniEditor || !miniEditor->document())
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_playButton->isPlaying()) {
|
if (m_playButton->isPlaying()) {
|
||||||
if (miniEditor && miniEditor->document())
|
m_refFrame = miniEditor->frame();
|
||||||
m_nextFrameTime = miniEditor->sprite()->frameDuration(miniEditor->frame());
|
miniEditor->play();
|
||||||
else
|
|
||||||
m_nextFrameTime = -1;
|
|
||||||
|
|
||||||
m_curFrameTick = ui::clock();
|
|
||||||
m_pingPongForward = true;
|
|
||||||
|
|
||||||
m_playTimer.start();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_playTimer.stop();
|
|
||||||
|
|
||||||
if (miniEditor)
|
|
||||||
miniEditor->setFrame(m_refFrame);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
miniEditor->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewEditorWindow::updateUsingEditor(Editor* editor)
|
void PreviewEditorWindow::updateUsingEditor(Editor* editor)
|
||||||
@ -286,6 +272,9 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (editor != current_editor)
|
||||||
|
return;
|
||||||
|
|
||||||
Document* document = editor->document();
|
Document* document = editor->document();
|
||||||
Editor* miniEditor = (m_docView ? m_docView->getEditor(): NULL);
|
Editor* miniEditor = (m_docView ? m_docView->getEditor(): NULL);
|
||||||
|
|
||||||
@ -304,6 +293,8 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor)
|
|||||||
|
|
||||||
miniEditor = m_docView->getEditor();
|
miniEditor = m_docView->getEditor();
|
||||||
miniEditor->setZoom(render::Zoom(1, 1));
|
miniEditor->setZoom(render::Zoom(1, 1));
|
||||||
|
miniEditor->setLayer(editor->layer());
|
||||||
|
miniEditor->setFrame(editor->frame());
|
||||||
miniEditor->setState(EditorStatePtr(new NavigateState));
|
miniEditor->setState(EditorStatePtr(new NavigateState));
|
||||||
layout();
|
layout();
|
||||||
center = true;
|
center = true;
|
||||||
@ -312,8 +303,24 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor)
|
|||||||
if (center)
|
if (center)
|
||||||
miniEditor->centerInSpritePoint(centerPoint);
|
miniEditor->centerInSpritePoint(centerPoint);
|
||||||
|
|
||||||
miniEditor->setLayer(editor->layer());
|
if (!m_playButton->isPlaying()) {
|
||||||
miniEditor->setFrame(m_refFrame = editor->frame());
|
miniEditor->stop();
|
||||||
|
miniEditor->setLayer(editor->layer());
|
||||||
|
miniEditor->setFrame(editor->frame());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (miniEditor->isPlaying()) {
|
||||||
|
doc::FrameTag* tag = get_animation_tag(editor->sprite(), editor->frame());
|
||||||
|
doc::FrameTag* playingTag = get_animation_tag(editor->sprite(), m_refFrame);
|
||||||
|
if (tag != playingTag)
|
||||||
|
miniEditor->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!miniEditor->isPlaying())
|
||||||
|
miniEditor->setFrame(m_refFrame = editor->frame());
|
||||||
|
|
||||||
|
miniEditor->play();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewEditorWindow::uncheckCenterButton()
|
void PreviewEditorWindow::uncheckCenterButton()
|
||||||
@ -331,41 +338,4 @@ void PreviewEditorWindow::hideWindow()
|
|||||||
closeWindow(NULL);
|
closeWindow(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewEditorWindow::onPlaybackTick()
|
|
||||||
{
|
|
||||||
Editor* miniEditor = (m_docView ? m_docView->getEditor(): NULL);
|
|
||||||
if (!miniEditor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
doc::Document* document = miniEditor->document();
|
|
||||||
doc::Sprite* sprite = miniEditor->sprite();
|
|
||||||
if (!document || !sprite)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_nextFrameTime >= 0) {
|
|
||||||
m_nextFrameTime -= (ui::clock() - m_curFrameTick);
|
|
||||||
|
|
||||||
// TODO get the frame tag in updateUsingEditor()
|
|
||||||
doc::FrameTag* tag = get_shortest_tag(sprite, m_refFrame);
|
|
||||||
if (!tag)
|
|
||||||
tag = get_loop_tag(sprite);
|
|
||||||
|
|
||||||
while (m_nextFrameTime <= 0) {
|
|
||||||
doc::frame_t frame = calculate_next_frame(
|
|
||||||
sprite,
|
|
||||||
miniEditor->frame(),
|
|
||||||
tag,
|
|
||||||
m_pingPongForward);
|
|
||||||
|
|
||||||
miniEditor->setFrame(frame);
|
|
||||||
|
|
||||||
m_nextFrameTime += miniEditor->sprite()->frameDuration(frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curFrameTick = ui::clock();
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include "app/ui/document_view.h"
|
#include "app/ui/document_view.h"
|
||||||
#include "doc/frame.h"
|
#include "doc/frame.h"
|
||||||
#include "ui/timer.h"
|
|
||||||
#include "ui/window.h"
|
#include "ui/window.h"
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
@ -37,21 +36,12 @@ namespace app {
|
|||||||
private:
|
private:
|
||||||
void onCenterClicked();
|
void onCenterClicked();
|
||||||
void onPlayClicked();
|
void onPlayClicked();
|
||||||
void onPlaybackTick();
|
|
||||||
void hideWindow();
|
void hideWindow();
|
||||||
|
|
||||||
bool m_isEnabled;
|
bool m_isEnabled;
|
||||||
DocumentView* m_docView;
|
DocumentView* m_docView;
|
||||||
MiniCenterButton* m_centerButton;
|
MiniCenterButton* m_centerButton;
|
||||||
MiniPlayButton* m_playButton;
|
MiniPlayButton* m_playButton;
|
||||||
ui::Timer m_playTimer;
|
|
||||||
|
|
||||||
// Number of milliseconds to go to the next frame if m_playTimer
|
|
||||||
// is activated.
|
|
||||||
int m_nextFrameTime;
|
|
||||||
int m_curFrameTick;
|
|
||||||
|
|
||||||
bool m_pingPongForward;
|
|
||||||
doc::frame_t m_refFrame;
|
doc::frame_t m_refFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,7 +74,10 @@ DocumentView* UIContext::activeView() const
|
|||||||
|
|
||||||
void UIContext::setActiveView(DocumentView* docView)
|
void UIContext::setActiveView(DocumentView* docView)
|
||||||
{
|
{
|
||||||
if (m_lastSelectedView == docView) // Do nothing case
|
// Do nothing cases: 1) the view is already selected, or 2) the view
|
||||||
|
// is the a preview.
|
||||||
|
if (m_lastSelectedView == docView ||
|
||||||
|
(docView && docView->isPreview()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setActiveDocument(docView ? docView->getDocument(): NULL);
|
setActiveDocument(docView ? docView->getDocument(): NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user