If starting a second animation of the same type then cancel the first one
parent
5a2c27d8e9
commit
dea305b324
|
@ -56,13 +56,17 @@ namespace tgui
|
|||
public:
|
||||
enum class Type
|
||||
{
|
||||
None,
|
||||
Move,
|
||||
Fade,
|
||||
Scale
|
||||
None = 0,
|
||||
Move = 1,
|
||||
Resize = 2,
|
||||
Fade = 4
|
||||
};
|
||||
|
||||
bool update(sf::Time elapsedTime);
|
||||
Type getType() const;
|
||||
|
||||
virtual bool update(sf::Time elapsedTime) = 0;
|
||||
|
||||
virtual void finish();
|
||||
|
||||
protected:
|
||||
Type m_type = Type::None;
|
||||
|
@ -71,15 +75,6 @@ namespace tgui
|
|||
sf::Time m_totalDuration;
|
||||
sf::Time m_elapsedTime;
|
||||
|
||||
sf::Vector2f m_startPos;
|
||||
sf::Vector2f m_endPos;
|
||||
|
||||
sf::Vector2f m_startSize;
|
||||
sf::Vector2f m_endSize;
|
||||
|
||||
float m_startOpacity;
|
||||
float m_endOpacity;
|
||||
|
||||
std::function<void()> m_finishedCallback;
|
||||
|
||||
friend class tgui::Widget;
|
||||
|
@ -87,26 +82,50 @@ namespace tgui
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TGUI_API FadeAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
FadeAnimation(Widget::Ptr widget, float start, float end, sf::Time duration, std::function<void()> finishedCallback = nullptr);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TGUI_API MoveAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
MoveAnimation(Widget::Ptr widget, sf::Vector2f start, sf::Vector2f end, sf::Time duration, std::function<void()> finishedCallback = nullptr);
|
||||
|
||||
virtual bool update(sf::Time elapsedTime) override;
|
||||
|
||||
virtual void finish() override;
|
||||
|
||||
private:
|
||||
sf::Vector2f m_startPos;
|
||||
sf::Vector2f m_endPos;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TGUI_API ScaleAnimation : public Animation
|
||||
class TGUI_API ResizeAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
ScaleAnimation(Widget::Ptr widget, sf::Vector2f startPos, sf::Vector2f endPos, sf::Vector2f startSize, sf::Vector2f endSize, sf::Time duration, std::function<void()> finishedCallback = nullptr);
|
||||
ResizeAnimation(Widget::Ptr widget, sf::Vector2f start, sf::Vector2f end, sf::Time duration, std::function<void()> finishedCallback = nullptr);
|
||||
|
||||
virtual bool update(sf::Time elapsedTime) override;
|
||||
|
||||
virtual void finish() override;
|
||||
|
||||
private:
|
||||
sf::Vector2f m_startSize;
|
||||
sf::Vector2f m_endSize;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TGUI_API FadeAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
FadeAnimation(Widget::Ptr widget, float start, float end, sf::Time duration, std::function<void()> finishedCallback = nullptr);
|
||||
|
||||
virtual bool update(sf::Time elapsedTime) override;
|
||||
|
||||
virtual void finish() override;
|
||||
|
||||
private:
|
||||
float m_startOpacity;
|
||||
float m_endOpacity;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -33,43 +33,17 @@ namespace tgui
|
|||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Animation::update(sf::Time elapsedTime)
|
||||
Animation::Type Animation::getType() const
|
||||
{
|
||||
m_elapsedTime += elapsedTime;
|
||||
if (m_elapsedTime > m_totalDuration)
|
||||
m_elapsedTime = m_totalDuration;
|
||||
|
||||
if (m_type == Type::Fade)
|
||||
m_widget->setOpacity(m_startOpacity + ((m_elapsedTime.asSeconds() / m_totalDuration.asSeconds()) * (m_endOpacity - m_startOpacity)));
|
||||
else if (m_type == Type::Move)
|
||||
m_widget->setPosition(m_startPos + ((m_elapsedTime.asSeconds() / m_totalDuration.asSeconds()) * (m_endPos - m_startPos)));
|
||||
else if (m_type == Type::Scale)
|
||||
{
|
||||
m_widget->setPosition(m_startPos + ((m_elapsedTime.asSeconds() / m_totalDuration.asSeconds()) * (m_endPos - m_startPos)));
|
||||
m_widget->setSize(m_startSize + ((m_elapsedTime.asSeconds() / m_totalDuration.asSeconds()) * (m_endSize - m_startSize)));
|
||||
}
|
||||
|
||||
if (m_elapsedTime == m_totalDuration)
|
||||
{
|
||||
if (m_finishedCallback != nullptr)
|
||||
m_finishedCallback();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FadeAnimation::FadeAnimation(Widget::Ptr widget, float start, float end, sf::Time duration, std::function<void()> finishedCallback)
|
||||
void Animation::finish()
|
||||
{
|
||||
m_type = Type::Fade;
|
||||
m_widget = widget;
|
||||
m_startOpacity = std::max(0.f, std::min(1.f, start));
|
||||
m_endOpacity = std::max(0.f, std::min(1.f, end));
|
||||
m_totalDuration = duration;
|
||||
m_finishedCallback = finishedCallback;
|
||||
if (m_finishedCallback != nullptr)
|
||||
m_finishedCallback();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -86,19 +60,98 @@ namespace tgui
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ScaleAnimation::ScaleAnimation(Widget::Ptr widget, sf::Vector2f startPos, sf::Vector2f endPos, sf::Vector2f startSize, sf::Vector2f endSize, sf::Time duration, std::function<void()> finishedCallback)
|
||||
bool MoveAnimation::update(sf::Time elapsedTime)
|
||||
{
|
||||
m_type = Type::Scale;
|
||||
m_elapsedTime += elapsedTime;
|
||||
if (m_elapsedTime >= m_totalDuration)
|
||||
{
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
m_widget->setPosition(m_startPos + ((m_elapsedTime.asSeconds() / m_totalDuration.asSeconds()) * (m_endPos - m_startPos)));
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MoveAnimation::finish()
|
||||
{
|
||||
m_widget->setPosition(m_endPos);
|
||||
Animation::finish();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ResizeAnimation::ResizeAnimation(Widget::Ptr widget, sf::Vector2f start, sf::Vector2f end, sf::Time duration, std::function<void()> finishedCallback)
|
||||
{
|
||||
m_type = Type::Resize;
|
||||
m_widget = widget;
|
||||
m_startPos = startPos;
|
||||
m_endPos = endPos;
|
||||
m_startSize = startSize;
|
||||
m_endSize = endSize;
|
||||
m_startSize = start;
|
||||
m_endSize = end;
|
||||
m_totalDuration = duration;
|
||||
m_finishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ResizeAnimation::update(sf::Time elapsedTime)
|
||||
{
|
||||
m_elapsedTime += elapsedTime;
|
||||
if (m_elapsedTime >= m_totalDuration)
|
||||
{
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
m_widget->setSize(m_startSize + ((m_elapsedTime.asSeconds() / m_totalDuration.asSeconds()) * (m_endSize - m_startSize)));
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ResizeAnimation::finish()
|
||||
{
|
||||
m_widget->setSize(m_endSize);
|
||||
Animation::finish();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FadeAnimation::FadeAnimation(Widget::Ptr widget, float start, float end, sf::Time duration, std::function<void()> finishedCallback)
|
||||
{
|
||||
m_type = Type::Fade;
|
||||
m_widget = widget;
|
||||
m_startOpacity = std::max(0.f, std::min(1.f, start));
|
||||
m_endOpacity = std::max(0.f, std::min(1.f, end));
|
||||
m_totalDuration = duration;
|
||||
m_finishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool FadeAnimation::update(sf::Time elapsedTime)
|
||||
{
|
||||
m_elapsedTime += elapsedTime;
|
||||
if (m_elapsedTime >= m_totalDuration)
|
||||
{
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
m_widget->setOpacity(m_startOpacity + ((m_elapsedTime.asSeconds() / m_totalDuration.asSeconds()) * (m_endOpacity - m_startOpacity)));
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FadeAnimation::finish()
|
||||
{
|
||||
m_widget->setOpacity(m_endOpacity);
|
||||
Animation::finish();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -32,6 +32,31 @@
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
void addAnimation(std::vector<std::shared_ptr<tgui::priv::Animation>>& existingAnimations, std::shared_ptr<tgui::priv::Animation> newAnimation)
|
||||
{
|
||||
auto type = newAnimation->getType();
|
||||
|
||||
// If another animation is already running with the same type then instantly finish it
|
||||
unsigned int i = 0;
|
||||
while (i < existingAnimations.size())
|
||||
{
|
||||
if (existingAnimations[i]->getType() == type)
|
||||
{
|
||||
existingAnimations[i]->finish();
|
||||
existingAnimations.erase(existingAnimations.begin() + i);
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
existingAnimations.push_back(newAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace tgui
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -204,50 +229,51 @@ namespace tgui
|
|||
{
|
||||
case ShowAnimationType::Fade:
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::FadeAnimation>(shared_from_this(), 0.f, getOpacity(), duration));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::FadeAnimation>(shared_from_this(), 0.f, getOpacity(), duration));
|
||||
setOpacity(0);
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::Scale:
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::ScaleAnimation>(shared_from_this(), getPosition() + (getSize() / 2.f), getPosition(), sf::Vector2f{0, 0}, getSize(), duration));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), getPosition() + (getSize() / 2.f), getPosition(), duration));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::ResizeAnimation>(shared_from_this(), sf::Vector2f{0, 0}, getSize(), duration));
|
||||
setPosition(getPosition() + (getSize() / 2.f));
|
||||
setSize(0, 0);
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::SlideToRight:
|
||||
case ShowAnimationType::SlideFromLeft:
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::MoveAnimation>(shared_from_this(), sf::Vector2f{-getFullSize().x, getPosition().y}, getPosition(), duration));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), sf::Vector2f{-getFullSize().x, getPosition().y}, getPosition(), duration));
|
||||
setPosition({-getFullSize().x, getPosition().y});
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::SlideToLeft:
|
||||
case ShowAnimationType::SlideFromRight:
|
||||
{
|
||||
if (getParent())
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::MoveAnimation>(shared_from_this(), sf::Vector2f{getParent()->getSize().x + getWidgetOffset().x, getPosition().y}, getPosition(), duration));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), sf::Vector2f{getParent()->getSize().x + getWidgetOffset().x, getPosition().y}, getPosition(), duration));
|
||||
setPosition({getParent()->getSize().x + getWidgetOffset().x, getPosition().y});
|
||||
}
|
||||
else
|
||||
sf::err() << "TGUI Warning: showWithEffect(SlideToLeft) does not work before widget has a parent." << std::endl;
|
||||
sf::err() << "TGUI Warning: showWithEffect(SlideFromRight) does not work before widget has a parent." << std::endl;
|
||||
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::SlideToBottom:
|
||||
case ShowAnimationType::SlideFromTop:
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::MoveAnimation>(shared_from_this(), sf::Vector2f{getPosition().x, -getFullSize().y}, getPosition(), duration));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), sf::Vector2f{getPosition().x, -getFullSize().y}, getPosition(), duration));
|
||||
setPosition({getPosition().x, -getFullSize().y});
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::SlideToTop:
|
||||
case ShowAnimationType::SlideFromBottom:
|
||||
{
|
||||
if (getParent())
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::MoveAnimation>(shared_from_this(), sf::Vector2f{getPosition().x, getParent()->getSize().y + getWidgetOffset().y}, getPosition(), duration));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), sf::Vector2f{getPosition().x, getParent()->getSize().y + getWidgetOffset().y}, getPosition(), duration));
|
||||
setPosition({getPosition().x, getParent()->getSize().y + getWidgetOffset().y});
|
||||
}
|
||||
else
|
||||
sf::err() << "TGUI Warning: showWithEffect(SlideToTop) does not work before widget has a parent." << std::endl;
|
||||
sf::err() << "TGUI Warning: showWithEffect(SlideFromBottom) does not work before widget has a parent." << std::endl;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -276,40 +302,41 @@ namespace tgui
|
|||
{
|
||||
case ShowAnimationType::Fade:
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::FadeAnimation>(shared_from_this(), opacity, 0.f, duration, [=](){ hide(); setOpacity(opacity); }));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::FadeAnimation>(shared_from_this(), opacity, 0.f, duration, [=](){ hide(); setOpacity(opacity); }));
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::Scale:
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::ScaleAnimation>(shared_from_this(), position, position + (size / 2.f), size, sf::Vector2f{0, 0}, duration, [=](){ hide(); setPosition(position); setSize(size); }));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), position, position + (size / 2.f), duration, [=](){ hide(); setPosition(position); setSize(size); }));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::ResizeAnimation>(shared_from_this(), size, sf::Vector2f{0, 0}, duration, [=](){ hide(); setPosition(position); setSize(size); }));
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::SlideToRight:
|
||||
{
|
||||
if (getParent())
|
||||
m_showAnimations.push_back(std::make_shared<priv::MoveAnimation>(shared_from_this(), position, sf::Vector2f{getParent()->getSize().x + getWidgetOffset().x, position.y}, duration, [=](){ hide(); setPosition(position); }));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), position, sf::Vector2f{getParent()->getSize().x + getWidgetOffset().x, position.y}, duration, [=](){ hide(); setPosition(position); }));
|
||||
else
|
||||
sf::err() << "TGUI Warning: showWithEffect(SlideToRight) does not work before widget has a parent." << std::endl;
|
||||
sf::err() << "TGUI Warning: hideWithEffect(SlideToRight) does not work before widget has a parent." << std::endl;
|
||||
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::SlideToLeft:
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::MoveAnimation>(shared_from_this(), position, sf::Vector2f{-getFullSize().x, position.y}, duration, [=](){ hide(); setPosition(position); }));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), position, sf::Vector2f{-getFullSize().x, position.y}, duration, [=](){ hide(); setPosition(position); }));
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::SlideToBottom:
|
||||
{
|
||||
if (getParent())
|
||||
m_showAnimations.push_back(std::make_shared<priv::MoveAnimation>(shared_from_this(), position, sf::Vector2f{position.x, getParent()->getSize().y + getWidgetOffset().y}, duration, [=](){ hide(); setPosition(position); }));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), position, sf::Vector2f{position.x, getParent()->getSize().y + getWidgetOffset().y}, duration, [=](){ hide(); setPosition(position); }));
|
||||
else
|
||||
sf::err() << "TGUI Warning: showWithEffect(SlideToBottom) does not work before widget has a parent." << std::endl;
|
||||
sf::err() << "TGUI Warning: hideWithEffect(SlideToBottom) does not work before widget has a parent." << std::endl;
|
||||
|
||||
break;
|
||||
}
|
||||
case ShowAnimationType::SlideToTop:
|
||||
{
|
||||
m_showAnimations.push_back(std::make_shared<priv::MoveAnimation>(shared_from_this(), position, sf::Vector2f{position.x, -getFullSize().y}, duration, [=](){ hide(); setPosition(position); }));
|
||||
addAnimation(m_showAnimations, std::make_shared<priv::MoveAnimation>(shared_from_this(), position, sf::Vector2f{position.x, -getFullSize().y}, duration, [=](){ hide(); setPosition(position); }));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,5 +196,7 @@ TEST_CASE("[Animation]") {
|
|||
REQUIRE(widget->getOpacity() == 0.9f);
|
||||
REQUIRE(!widget->isVisible());
|
||||
}
|
||||
|
||||
// TODO: Add tests for simultaneous animations (tests for both same type and different types)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue