Add right-click popup menu in play buttons to change animation speed (fix #595)

This commit is contained in:
David Capello 2015-05-07 19:08:24 -03:00
parent ee3d4ca63c
commit 804330788b
10 changed files with 106 additions and 6 deletions

View File

@ -105,4 +105,12 @@ void AniControls::onPlayButton()
} }
} }
void AniControls::onRightClick(Item* item)
{
ButtonSet::onRightClick(item);
if (item == getItem(ACTION_PLAY) && current_editor)
current_editor->showAnimationSpeedMultiplierPopup();
}
} // namespace app } // namespace app

View File

@ -24,6 +24,9 @@ namespace app {
void updateUsingEditor(Editor* editor); void updateUsingEditor(Editor* editor);
protected:
void onRightClick(Item* item) override;
private: private:
void onPlayButton(); void onPlayButton();
}; };

View File

@ -110,8 +110,10 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg)
buttonSet()->setSelectedItem(this); buttonSet()->setSelectedItem(this);
invalidate(); invalidate();
if (!buttonSet()->m_triggerOnMouseUp) if (static_cast<MouseMessage*>(msg)->left() &&
!buttonSet()->m_triggerOnMouseUp) {
buttonSet()->onItemChange(); buttonSet()->onItemChange();
}
break; break;
case ui::kMouseUpMessage: case ui::kMouseUpMessage:
@ -119,8 +121,13 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg)
releaseMouse(); releaseMouse();
invalidate(); invalidate();
if (buttonSet()->m_triggerOnMouseUp) if (static_cast<MouseMessage*>(msg)->left()) {
buttonSet()->onItemChange(); if (buttonSet()->m_triggerOnMouseUp)
buttonSet()->onItemChange();
}
else if (static_cast<MouseMessage*>(msg)->right()) {
buttonSet()->onRightClick(this);
}
} }
break; break;
@ -229,6 +236,11 @@ void ButtonSet::onItemChange()
ItemChange(); ItemChange();
} }
void ButtonSet::onRightClick(Item* item)
{
RightClick(item);
}
ButtonSet::Item* ButtonSet::findSelectedItem() const ButtonSet::Item* ButtonSet::findSelectedItem() const
{ {
for (Widget* child : getChildren()) { for (Widget* child : getChildren()) {

View File

@ -47,9 +47,11 @@ namespace app {
void setTriggerOnMouseUp(bool state); void setTriggerOnMouseUp(bool state);
Signal0<void> ItemChange; Signal0<void> ItemChange;
Signal1<void, Item*> RightClick;
protected: protected:
virtual void onItemChange(); virtual void onItemChange();
virtual void onRightClick(Item* item);
private: private:
Item* findSelectedItem() const; Item* findSelectedItem() const;

View File

@ -43,6 +43,7 @@
#include "app/ui_context.h" #include "app/ui_context.h"
#include "app/util/boundary.h" #include "app/util/boundary.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/convert_to.h"
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "doc/conversion_she.h" #include "doc/conversion_she.h"
#include "doc/doc.h" #include "doc/doc.h"
@ -164,6 +165,7 @@ Editor::Editor(Document* document, EditorFlags flags)
, m_docView(NULL) , m_docView(NULL)
, m_flags(flags) , m_flags(flags)
, m_secondaryButton(false) , m_secondaryButton(false)
, m_aniSpeed(1.0)
{ {
// Add the first state into the history. // Add the first state into the history.
m_statesHistory.push(m_state); m_statesHistory.push(m_state);
@ -1561,6 +1563,31 @@ bool Editor::isPlaying() const
return (dynamic_cast<PlayState*>(m_state.get()) != nullptr); return (dynamic_cast<PlayState*>(m_state.get()) != nullptr);
} }
void Editor::showAnimationSpeedMultiplierPopup()
{
double options[] = { 0.25, 0.5, 1.0, 1.5, 2.0, 3.0 };
Menu menu;
for (double option : options) {
MenuItem* item = new MenuItem("x" + base::convert_to<std::string>(option));
item->Click.connect(Bind<void>(&Editor::setAnimationSpeedMultiplier, this, option));
item->setSelected(m_aniSpeed == option);
menu.addChild(item);
}
menu.showPopup(ui::get_mouse_position());
}
double Editor::getAnimationSpeedMultiplier() const
{
return m_aniSpeed;
}
void Editor::setAnimationSpeedMultiplier(double speed)
{
m_aniSpeed = speed;
}
// static // static
ImageBufferPtr Editor::getRenderImageBuffer() ImageBufferPtr Editor::getRenderImageBuffer()
{ {

View File

@ -194,6 +194,11 @@ namespace app {
void stop(); void stop();
bool isPlaying() const; bool isPlaying() const;
// Shows a popup menu to change the editor animation speed.
void showAnimationSpeedMultiplierPopup();
double getAnimationSpeedMultiplier() const;
void setAnimationSpeedMultiplier(double speed);
// 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();
@ -311,6 +316,9 @@ namespace app {
bool m_secondaryButton; bool m_secondaryButton;
// Animation speed multiplier.
double m_aniSpeed;
static doc::ImageBufferPtr m_renderBuffer; static doc::ImageBufferPtr m_renderBuffer;
static AppRender m_renderEngine; static AppRender m_renderEngine;
}; };

View File

@ -50,7 +50,7 @@ void PlayState::onAfterChangeState(Editor* editor)
} }
m_toScroll = false; m_toScroll = false;
m_nextFrameTime = editor->sprite()->frameDuration(editor->frame()); m_nextFrameTime = getNextFrameTime();
m_curFrameTick = ui::clock(); m_curFrameTick = ui::clock();
m_pingPongForward = true; m_pingPongForward = true;
@ -138,7 +138,7 @@ void PlayState::onPlaybackTick()
m_pingPongForward); m_pingPongForward);
m_editor->setFrame(frame); m_editor->setFrame(frame);
m_nextFrameTime += m_editor->sprite()->frameDuration(frame); m_nextFrameTime += getNextFrameTime();
} }
m_curFrameTick = ui::clock(); m_curFrameTick = ui::clock();
@ -169,4 +169,11 @@ void PlayState::onBeforeCommandExecution(Command* command)
m_editor->stop(); m_editor->stop();
} }
double PlayState::getNextFrameTime()
{
return
m_editor->sprite()->frameDuration(m_editor->frame())
/ m_editor->getAnimationSpeedMultiplier(); // The "speed multiplier" is a "duration divider"
}
} // namespace app } // namespace app

View File

@ -35,13 +35,15 @@ namespace app {
// ContextObserver // ContextObserver
void onBeforeCommandExecution(Command* command); void onBeforeCommandExecution(Command* command);
double getNextFrameTime();
Editor* m_editor; Editor* m_editor;
bool m_toScroll; bool m_toScroll;
ui::Timer m_playTimer; ui::Timer m_playTimer;
// Number of milliseconds to go to the next frame if m_playTimer // Number of milliseconds to go to the next frame if m_playTimer
// is activated. // is activated.
int m_nextFrameTime; double m_nextFrameTime;
int m_curFrameTick; int m_curFrameTick;
bool m_pingPongForward; bool m_pingPongForward;

View File

@ -102,6 +102,8 @@ public:
bool isPlaying() const { return m_isPlaying; } bool isPlaying() const { return m_isPlaying; }
Signal0<void> Popup;
protected: protected:
void onClick(Event& ev) override void onClick(Event& ev) override
{ {
@ -143,6 +145,20 @@ protected:
case kSetCursorMessage: case kSetCursorMessage:
ui::set_mouse_cursor(kArrowCursor); ui::set_mouse_cursor(kArrowCursor);
return true; return true;
case kMouseUpMessage: {
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
if (mouseMsg->right()) {
if (hasCapture()) {
releaseMouse();
Popup();
setSelected(false);
return true;
}
}
break;
}
} }
return SkinButton<Button>::onProcessMessage(msg); return SkinButton<Button>::onProcessMessage(msg);
@ -158,6 +174,7 @@ PreviewEditorWindow::PreviewEditorWindow()
, m_centerButton(new MiniCenterButton()) , m_centerButton(new MiniCenterButton())
, m_playButton(new MiniPlayButton()) , m_playButton(new MiniPlayButton())
, m_refFrame(0) , m_refFrame(0)
, m_aniSpeed(1.0)
{ {
child_spacing = 0; child_spacing = 0;
setAutoRemap(false); setAutoRemap(false);
@ -167,6 +184,7 @@ PreviewEditorWindow::PreviewEditorWindow()
m_centerButton->Click.connect(Bind<void>(&PreviewEditorWindow::onCenterClicked, this)); m_centerButton->Click.connect(Bind<void>(&PreviewEditorWindow::onCenterClicked, this));
m_playButton->Click.connect(Bind<void>(&PreviewEditorWindow::onPlayClicked, this)); m_playButton->Click.connect(Bind<void>(&PreviewEditorWindow::onPlayClicked, this));
m_playButton->Popup.connect(Bind<void>(&PreviewEditorWindow::onPopupSpeed, this));
addChild(m_centerButton); addChild(m_centerButton);
addChild(m_playButton); addChild(m_playButton);
@ -265,6 +283,16 @@ void PreviewEditorWindow::onPlayClicked()
miniEditor->stop(); miniEditor->stop();
} }
void PreviewEditorWindow::onPopupSpeed()
{
Editor* miniEditor = (m_docView ? m_docView->getEditor(): nullptr);
if (!miniEditor || !miniEditor->document())
return;
miniEditor->showAnimationSpeedMultiplierPopup();
m_aniSpeed = miniEditor->getAnimationSpeedMultiplier();
}
void PreviewEditorWindow::updateUsingEditor(Editor* editor) void PreviewEditorWindow::updateUsingEditor(Editor* editor)
{ {
if (!m_isEnabled || !editor) { if (!m_isEnabled || !editor) {
@ -296,6 +324,7 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor)
miniEditor->setLayer(editor->layer()); miniEditor->setLayer(editor->layer());
miniEditor->setFrame(editor->frame()); miniEditor->setFrame(editor->frame());
miniEditor->setState(EditorStatePtr(new NavigateState)); miniEditor->setState(EditorStatePtr(new NavigateState));
miniEditor->setAnimationSpeedMultiplier(m_aniSpeed);
layout(); layout();
center = true; center = true;
} }

View File

@ -36,6 +36,7 @@ namespace app {
private: private:
void onCenterClicked(); void onCenterClicked();
void onPlayClicked(); void onPlayClicked();
void onPopupSpeed();
void hideWindow(); void hideWindow();
bool m_isEnabled; bool m_isEnabled;
@ -43,6 +44,7 @@ namespace app {
MiniCenterButton* m_centerButton; MiniCenterButton* m_centerButton;
MiniPlayButton* m_playButton; MiniPlayButton* m_playButton;
doc::frame_t m_refFrame; doc::frame_t m_refFrame;
double m_aniSpeed;
}; };
} // namespace app } // namespace app