Add option to play all frames (ignoring tags)

This commit is contained in:
David Capello 2016-11-30 10:23:29 -03:00
parent 8870c90774
commit 767976c6bc
9 changed files with 72 additions and 28 deletions

View File

@ -116,6 +116,7 @@
<option id="right_click_mode" type="RightClickMode" default="RightClickMode::PAINT_BGCOLOR" migrate="Options.RightClickMode" />
<option id="auto_select_layer" type="bool" default="false" migrate="Options.AutoSelectLayer" />
<option id="play_once" type="bool" default="false" />
<option id="play_all" type="bool" default="false" />
</section>
<section id="cursor">
<option id="use_native_cursor" type="bool" default="false" migrate="experimental.use_native_cursor" />
@ -126,6 +127,7 @@
</section>
<section id="preview" text="Preview">
<option id="play_once" type="bool" default="false" />
<option id="play_all" type="bool" default="false" />
</section>
<section id="theme" text="Theme">
<option id="selected" type="std::string" default="&quot;default&quot;" migrate="Skin.Selected" />

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -59,7 +59,8 @@ void PlayAnimationCommand::onExecute(Context* context)
if (current_editor->isPlaying())
current_editor->stop();
else
current_editor->play(Preferences::instance().editor.playOnce());
current_editor->play(Preferences::instance().editor.playOnce(),
Preferences::instance().editor.playAll());
}
Command* CommandFactory::createPlayAnimationCommand()

View File

@ -112,7 +112,8 @@ void AniControls::onRightClick(Item* item)
if (item == getItem(ACTION_PLAY) && current_editor)
current_editor->showAnimationSpeedMultiplierPopup(
Preferences::instance().editor.playOnce, true);
Preferences::instance().editor.playOnce,
Preferences::instance().editor.playAll, true);
}
const char* AniControls::getCommandId(int index) const

View File

@ -1638,14 +1638,15 @@ void Editor::notifyZoomChanged()
m_observers.notifyZoomChanged(this);
}
void Editor::play(bool playOnce)
void Editor::play(const bool playOnce,
const bool playAll)
{
ASSERT(m_state);
if (!m_state)
return;
if (!dynamic_cast<PlayState*>(m_state.get()))
setState(EditorStatePtr(new PlayState(playOnce)));
setState(EditorStatePtr(new PlayState(playOnce, playAll)));
}
void Editor::stop()
@ -1664,9 +1665,10 @@ bool Editor::isPlaying() const
}
void Editor::showAnimationSpeedMultiplierPopup(Option<bool>& playOnce,
bool withStopBehaviorOptions)
Option<bool>& playAll,
const bool withStopBehaviorOptions)
{
double options[] = { 0.25, 0.5, 1.0, 1.5, 2.0, 3.0 };
const double options[] = { 0.25, 0.5, 1.0, 1.5, 2.0, 3.0 };
Menu menu;
for (double option : options) {
@ -1689,6 +1691,17 @@ void Editor::showAnimationSpeedMultiplierPopup(Option<bool>& playOnce,
menu.addChild(item);
}
// Play all option
{
MenuItem* item = new MenuItem("Play All Frames (Ignore Tags)");
item->Click.connect(
[&playAll]() {
playAll(!playAll());
});
item->setSelected(playAll());
menu.addChild(item);
}
if (withStopBehaviorOptions) {
MenuItem* item = new MenuItem("Rewind on Stop");
item->Click.connect(
@ -1702,6 +1715,12 @@ void Editor::showAnimationSpeedMultiplierPopup(Option<bool>& playOnce,
}
menu.showPopup(ui::get_mouse_position());
if (isPlaying()) {
stop();
play(playOnce(),
playAll());
}
}
double Editor::getAnimationSpeedMultiplier() const

View File

@ -202,13 +202,15 @@ namespace app {
void notifyZoomChanged();
// Animation control
void play(bool playOnce);
void play(const bool playOnce,
const bool playAll);
void stop();
bool isPlaying() const;
// Shows a popup menu to change the editor animation speed.
void showAnimationSpeedMultiplierPopup(Option<bool>& playOnce,
bool withStopBehaviorOptions);
Option<bool>& playAll,
const bool withStopBehaviorOptions);
double getAnimationSpeedMultiplier() const;
void setAnimationSpeedMultiplier(double speed);

View File

@ -27,13 +27,17 @@ namespace app {
using namespace ui;
PlayState::PlayState(bool playOnce)
PlayState::PlayState(const bool playOnce,
const bool playAll)
: m_editor(nullptr)
, m_playOnce(playOnce)
, m_playAll(playAll)
, m_toScroll(false)
, m_playTimer(10)
, m_nextFrameTime(-1)
, m_pingPongForward(true)
, m_refFrame(0)
, m_tag(nullptr)
{
m_playTimer.Tick.connect(&PlayState::onPlaybackTick, this);
@ -52,16 +56,18 @@ void PlayState::onEnterState(Editor* editor)
m_refFrame = editor->frame();
}
// Get the tag
if (!m_playAll)
m_tag = get_animation_tag(m_editor->sprite(), m_refFrame);
// Go to the first frame of the animation or active frame tag
if (m_playOnce) {
frame_t frame = 0;
doc::FrameTag* tag = get_animation_tag(
m_editor->sprite(), m_refFrame);
if (tag) {
frame = (tag->aniDir() == AniDir::REVERSE ?
tag->toFrame():
tag->fromFrame());
if (m_tag) {
frame = (m_tag->aniDir() == AniDir::REVERSE ?
m_tag->toFrame():
m_tag->fromFrame());
}
m_editor->setFrame(frame);
@ -147,24 +153,23 @@ void PlayState::onPlaybackTick()
m_nextFrameTime -= (base::current_tick() - 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 = m_editor->frame();
if (m_playOnce) {
bool atEnd = false;
if (tag) {
switch (tag->aniDir()) {
if (m_tag) {
switch (m_tag->aniDir()) {
case AniDir::FORWARD:
atEnd = (frame == tag->toFrame());
atEnd = (frame == m_tag->toFrame());
break;
case AniDir::REVERSE:
atEnd = (frame == tag->fromFrame());
atEnd = (frame == m_tag->fromFrame());
break;
case AniDir::PING_PONG:
atEnd = (!m_pingPongForward &&
frame == tag->fromFrame());
frame == m_tag->fromFrame());
break;
}
}
@ -178,7 +183,7 @@ void PlayState::onPlaybackTick()
}
frame = calculate_next_frame(
sprite, frame, frame_t(1), tag,
sprite, frame, frame_t(1), m_tag,
m_pingPongForward);
m_editor->setFrame(frame);

View File

@ -14,13 +14,18 @@
#include "obs/connection.h"
#include "ui/timer.h"
namespace doc {
class FrameTag;
}
namespace app {
class CommandExecutionEvent;
class PlayState : public StateWithWheelBehavior {
public:
PlayState(bool playOnce);
PlayState(const bool playOnce,
const bool playAll);
void onEnterState(Editor* editor) override;
LeaveAction onLeaveState(Editor* editor, EditorState* newState) override;
@ -40,6 +45,7 @@ namespace app {
Editor* m_editor;
bool m_playOnce;
bool m_playAll;
bool m_toScroll;
ui::Timer m_playTimer;
@ -50,6 +56,7 @@ namespace app {
bool m_pingPongForward;
doc::frame_t m_refFrame;
doc::FrameTag* m_tag;
obs::scoped_connection m_ctxConn;
};

View File

@ -299,7 +299,8 @@ void PreviewEditorWindow::onPlayClicked()
if (m_playButton->isPlaying()) {
m_refFrame = miniEditor->frame();
miniEditor->play(Preferences::instance().preview.playOnce());
miniEditor->play(Preferences::instance().preview.playOnce(),
Preferences::instance().preview.playAll());
}
else
miniEditor->stop();
@ -311,8 +312,12 @@ void PreviewEditorWindow::onPopupSpeed()
if (!miniEditor || !miniEditor->document())
return;
auto& pref = Preferences::instance();
miniEditor->showAnimationSpeedMultiplierPopup(
Preferences::instance().preview.playOnce, false);
pref.preview.playOnce,
pref.preview.playAll,
false);
m_aniSpeed = miniEditor->getAnimationSpeedMultiplier();
}
@ -383,7 +388,8 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor)
if (!miniEditor->isPlaying())
miniEditor->setFrame(m_refFrame = editor->frame());
miniEditor->play(Preferences::instance().preview.playOnce());
miniEditor->play(Preferences::instance().preview.playOnce(),
Preferences::instance().preview.playAll());
}
}

View File

@ -272,7 +272,8 @@ void Timeline::setFrame(frame_t frame, bool byUser)
m_editor->setFrame(m_frame);
if (isPlaying)
m_editor->play(false);
m_editor->play(false,
Preferences::instance().editor.playAll());
}
}