mirror of https://github.com/aseprite/aseprite.git
Add right-click popup menu in play buttons to change animation speed (fix #595)
This commit is contained in:
parent
ee3d4ca63c
commit
804330788b
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue