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

View File

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

View File

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

View File

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

View File

@ -43,6 +43,7 @@
#include "app/ui_context.h"
#include "app/util/boundary.h"
#include "base/bind.h"
#include "base/convert_to.h"
#include "base/unique_ptr.h"
#include "doc/conversion_she.h"
#include "doc/doc.h"
@ -164,6 +165,7 @@ Editor::Editor(Document* document, EditorFlags flags)
, m_docView(NULL)
, m_flags(flags)
, m_secondaryButton(false)
, m_aniSpeed(1.0)
{
// Add the first state into the history.
m_statesHistory.push(m_state);
@ -1561,6 +1563,31 @@ bool Editor::isPlaying() const
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
ImageBufferPtr Editor::getRenderImageBuffer()
{

View File

@ -194,6 +194,11 @@ namespace app {
void stop();
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.
// E.g. It can be re-used by PreviewCommand
static ImageBufferPtr getRenderImageBuffer();
@ -311,6 +316,9 @@ namespace app {
bool m_secondaryButton;
// Animation speed multiplier.
double m_aniSpeed;
static doc::ImageBufferPtr m_renderBuffer;
static AppRender m_renderEngine;
};

View File

@ -50,7 +50,7 @@ void PlayState::onAfterChangeState(Editor* editor)
}
m_toScroll = false;
m_nextFrameTime = editor->sprite()->frameDuration(editor->frame());
m_nextFrameTime = getNextFrameTime();
m_curFrameTick = ui::clock();
m_pingPongForward = true;
@ -138,7 +138,7 @@ void PlayState::onPlaybackTick()
m_pingPongForward);
m_editor->setFrame(frame);
m_nextFrameTime += m_editor->sprite()->frameDuration(frame);
m_nextFrameTime += getNextFrameTime();
}
m_curFrameTick = ui::clock();
@ -169,4 +169,11 @@ void PlayState::onBeforeCommandExecution(Command* command)
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

View File

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

View File

@ -102,6 +102,8 @@ public:
bool isPlaying() const { return m_isPlaying; }
Signal0<void> Popup;
protected:
void onClick(Event& ev) override
{
@ -143,6 +145,20 @@ protected:
case kSetCursorMessage:
ui::set_mouse_cursor(kArrowCursor);
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);
@ -158,6 +174,7 @@ PreviewEditorWindow::PreviewEditorWindow()
, m_centerButton(new MiniCenterButton())
, m_playButton(new MiniPlayButton())
, m_refFrame(0)
, m_aniSpeed(1.0)
{
child_spacing = 0;
setAutoRemap(false);
@ -167,6 +184,7 @@ PreviewEditorWindow::PreviewEditorWindow()
m_centerButton->Click.connect(Bind<void>(&PreviewEditorWindow::onCenterClicked, this));
m_playButton->Click.connect(Bind<void>(&PreviewEditorWindow::onPlayClicked, this));
m_playButton->Popup.connect(Bind<void>(&PreviewEditorWindow::onPopupSpeed, this));
addChild(m_centerButton);
addChild(m_playButton);
@ -265,6 +283,16 @@ void PreviewEditorWindow::onPlayClicked()
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)
{
if (!m_isEnabled || !editor) {
@ -296,6 +324,7 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor)
miniEditor->setLayer(editor->layer());
miniEditor->setFrame(editor->frame());
miniEditor->setState(EditorStatePtr(new NavigateState));
miniEditor->setAnimationSpeedMultiplier(m_aniSpeed);
layout();
center = true;
}

View File

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