mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
371 lines
13 KiB
371 lines
13 KiB
#ifndef Magnum_SceneGraph_Animable_h |
|
#define Magnum_SceneGraph_Animable_h |
|
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
/** @file |
|
* @brief Class @ref Magnum::SceneGraph::Animable, alias @ref Magnum::SceneGraph::BasicAnimable2D, @ref Magnum::SceneGraph::BasicAnimable3D, typedef @ref Magnum::SceneGraph::Animable2D, @ref Magnum::SceneGraph::Animable3D, enum @ref Magnum::SceneGraph::AnimationState |
|
*/ |
|
|
|
#include "Magnum/SceneGraph/AbstractGroupedFeature.h" |
|
#include "Magnum/SceneGraph/visibility.h" |
|
|
|
namespace Magnum { namespace SceneGraph { |
|
|
|
/** |
|
@brief Animation state |
|
|
|
@see @ref Animable::setState() |
|
*/ |
|
enum class AnimationState: UnsignedByte { |
|
/** |
|
* The animation is stopped. The animation will be started from the |
|
* beginning when state is changed to @ref AnimationState::Running. |
|
*/ |
|
Stopped, |
|
|
|
/** |
|
* The animation is stopped. The animation will continue from paused |
|
* position when state is changed to @ref AnimationState::Running. |
|
*/ |
|
Paused, |
|
|
|
/** The animation is running. */ |
|
Running |
|
}; |
|
|
|
/** @debugoperatorenum{Magnum::SceneGraph::AnimationState} */ |
|
MAGNUM_SCENEGRAPH_EXPORT Debug& operator<<(Debug& debug, AnimationState value); |
|
|
|
/** |
|
@brief Animable |
|
|
|
Adds animation feature to object. Each Animable is part of some |
|
@ref AnimableGroup, which takes care of running the animations. |
|
|
|
@section SceneGraph-Animable Usage |
|
|
|
First thing is to add @ref Animable feature to some object and implement |
|
@ref animationStep(). You can do it conveniently using multiple inheritance |
|
(see @ref scenegraph-features for introduction). Override @ref animationStep() |
|
to implement your animation, the function provides both absolute animation |
|
time and time delta. Example: |
|
|
|
@code{.cpp} |
|
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D; |
|
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D; |
|
|
|
class AnimableObject: public Object3D, SceneGraph::Animable3D { |
|
public: |
|
AnimableObject(Object3D* parent = nullptr, SceneGraph::AnimableGroup3D* group = nullptr): Object3D{parent}, SceneGraph::Animable3D{*this, group} { |
|
setDuration(10.0f); |
|
// ... |
|
} |
|
|
|
private: |
|
void animationStep(Float time, Float delta) override { |
|
rotateX(15.0_degf*delta); // rotate at 15 degrees per second |
|
} |
|
} |
|
@endcode |
|
|
|
Similarly to @ref Drawable feature, there is no way to just animate all the |
|
objects in the scene. You need to create animable group and use it to control |
|
given set of animations. You can also use @ref AnimableGroup::add() and |
|
@ref AnimableGroup::remove() instead of passing the group in the constructor. |
|
The animation is initially in stopped state and without repeat, see |
|
@ref setState(), @ref setRepeated() and @ref setRepeatCount() for more |
|
information. |
|
|
|
@code{.cpp} |
|
Scene3D scene; |
|
SceneGraph::AnimableGroup3D animables; |
|
|
|
(new AnimableObject(&scene, &animables)) |
|
->setState(SceneGraph::AnimationState::Running); |
|
// ... |
|
@endcode |
|
|
|
Animation step is performed by calling @ref AnimableGroup::step() in your draw |
|
event implementation. The function expects absolute time from relative to some |
|
fixed point in the past and time delta (i.e. duration of the frame). You can |
|
use @ref Timeline for that, see its documentation for more information. |
|
|
|
@code{.cpp} |
|
Timeline timeline; |
|
timeline.start(); |
|
|
|
void MyApplication::drawEvent() { |
|
animables.step(timeline.lastFrameTime(), timeline.lastFrameDuration()); |
|
|
|
// ... |
|
|
|
timeline.nextFrame(); |
|
} |
|
@endcode |
|
|
|
@section SceneGraph-Animable-multiple-groups Using multiple animable groups to improve performance |
|
|
|
@ref AnimableGroup is optimized for case when no animation is running --- it |
|
just puts itself to rest and waits until some animation changes its state to |
|
@ref AnimationState::Running again. If you put animations which are not |
|
pernamently running into separate group, they will not be traversed every time |
|
the @ref AnimableGroup::step() gets called, saving precious frame time. |
|
|
|
@section SceneGraph-Animable-explicit-specializations Explicit template specializations |
|
|
|
The following specializations are explicitly compiled into @ref SceneGraph |
|
library. For other specializations (e.g. using @ref Magnum::Double "Double" |
|
type) you have to use @ref Animable.hpp implementation file to avoid linker |
|
errors. See also @ref compilation-speedup-hpp for more information. |
|
|
|
- @ref Animable2D, @ref AnimableGroup2D |
|
- @ref Animable3D, @ref AnimableGroup3D |
|
|
|
@see @ref scenegraph, @ref BasicAnimable2D, @ref BasicAnimable3D, |
|
@ref Animable2D, @ref Animable3D, @ref AnimableGroup |
|
*/ |
|
template<UnsignedInt dimensions, class T> class Animable: public AbstractGroupedFeature<dimensions, Animable<dimensions, T>, T> { |
|
friend AnimableGroup<dimensions, T>; |
|
|
|
public: |
|
/** |
|
* @brief Constructor |
|
* @param object Object this animable belongs to |
|
* @param group Group this animable belongs to |
|
* |
|
* Creates stopped non-repeating animation with infinite duration, |
|
* adds the feature to the object and also to group, if specified. |
|
* @see @ref setDuration(), @ref setState(), @ref setRepeated(), |
|
* @ref AnimableGroup::add() |
|
*/ |
|
explicit Animable(AbstractObject<dimensions, T>& object, AnimableGroup<dimensions, T>* group = nullptr); |
|
|
|
~Animable(); |
|
|
|
/** @brief Animation duration */ |
|
Float duration() const { return _duration; } |
|
|
|
/** @brief Animation state */ |
|
AnimationState state() const { return _currentState; } |
|
|
|
/** |
|
* @brief Set animation state |
|
* @return Reference to self (for method chaining) |
|
* |
|
* Note that changing state from @ref AnimationState::Stopped to |
|
* @ref AnimationState::Paused is ignored and animation remains in |
|
* @ref AnimationState::Stopped state. See also @ref animationStep() |
|
* for more information. |
|
* @see @ref animationStarted(), @ref animationPaused(), |
|
* @ref animationResumed(), @ref animationStopped() |
|
*/ |
|
Animable<dimensions, T>& setState(AnimationState state); |
|
|
|
/** |
|
* @brief Whether the animation is repeated |
|
* |
|
* @see @ref repeatCount() |
|
*/ |
|
bool isRepeated() const { return _repeated; } |
|
|
|
/** |
|
* @brief Enable/disable repeated animation |
|
* @return Reference to self (for method chaining) |
|
* |
|
* Default is @cpp false @ce. |
|
* @see @ref setRepeatCount() |
|
*/ |
|
Animable<dimensions, T>& setRepeated(bool repeated) { |
|
_repeated = repeated; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Repeat count |
|
* |
|
* @see @ref isRepeated() |
|
*/ |
|
UnsignedShort repeatCount() const { return _repeatCount; } |
|
|
|
/** |
|
* @brief Set repeat count |
|
* @return Reference to self (for method chaining) |
|
* |
|
* Has effect only if repeated animation is enabled. @cpp 0 @ce means |
|
* infinitely repeated animation. Default is @cpp 0 @ce. |
|
* @see @ref setRepeated() |
|
*/ |
|
Animable<dimensions, T>& setRepeatCount(UnsignedShort count) { |
|
_repeatCount = count; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Group containing this animable |
|
* |
|
* If the animable doesn't belong to any group, returns @cpp nullptr @ce. |
|
*/ |
|
AnimableGroup<dimensions, T>* animables(); |
|
const AnimableGroup<dimensions, T>* animables() const; /**< @overload */ |
|
|
|
protected: |
|
/** |
|
* @brief Set animation duration |
|
* @return Reference to self (for method chaining) |
|
* |
|
* Sets duration of the animation cycle in seconds. Set to @cpp 0.0f @ce |
|
* for infinite non-repeating animation. Default is @cpp 0.0f @ce. |
|
*/ |
|
/* Protected so only animation implementer can change it */ |
|
Animable<dimensions, T>& setDuration(Float duration) { |
|
_duration = duration; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Perform animation step |
|
* @param time Time from start of the animation |
|
* @param delta Time delta for current frame |
|
* |
|
* This function is periodically called from @ref AnimableGroup::step() |
|
* if the animation state is set to @ref AnimationState::Running. After |
|
* animation duration is exceeded and repeat is not enabled or repeat |
|
* count is exceeded, the animation state is set to @ref AnimationState::Stopped. |
|
* |
|
* If the animation is resumed from @ref AnimationState::Paused, this |
|
* function is called with @p time continuing from the point when it |
|
* was paused. If the animation is resumed from @ref AnimationState::Stopped, |
|
* @p time starts with zero. |
|
* |
|
* @see @ref state(), @ref duration(), @ref isRepeated(), |
|
* @ref repeatCount() |
|
*/ |
|
virtual void animationStep(Float time, Float delta) = 0; |
|
|
|
/** |
|
* @brief Action on animation start |
|
* |
|
* Called from @ref AnimableGroup::step() when state is changed from |
|
* @ref AnimationState::Stopped to @ref AnimationState::Running and |
|
* before first @ref animationStep() is called. |
|
* |
|
* Default implementation does nothing. |
|
* @see @ref setState() |
|
*/ |
|
virtual void animationStarted() {} |
|
|
|
/** |
|
* @brief Action on animation pause |
|
* |
|
* Called from @ref AnimableGroup::step() when state changes from |
|
* @ref AnimationState::Running to @ref AnimationState::Paused and |
|
* after last @ref animationStep() is called. |
|
* |
|
* Default implementation does nothing. |
|
* @see @ref setState() |
|
*/ |
|
virtual void animationPaused() {} |
|
|
|
/** |
|
* @brief Action on animation resume |
|
* |
|
* Called from @ref AnimableGroup::step() when state changes from |
|
* @ref AnimationState::Paused to @ref AnimationState::Running and |
|
* before first @ref animationStep() is called. |
|
* |
|
* Default implementation does nothing. |
|
* @see @ref setState() |
|
*/ |
|
virtual void animationResumed() {} |
|
|
|
/** |
|
* @brief Action on animation stop |
|
* |
|
* Called from @ref AnimableGroup::step() when state changes from |
|
* either @ref AnimationState::Running or @ref AnimationState::Paused |
|
* to @ref AnimationState::Stopped and after last @ref animationStep() |
|
* is called. |
|
* |
|
* You may want to use this function to properly finish the animation |
|
* in case the framerate is not high enough to have @ref animationStep() |
|
* called enough times. Default implementation does nothing. |
|
* @see @ref setState() |
|
*/ |
|
virtual void animationStopped() {} |
|
|
|
private: |
|
Float _duration; |
|
Float _startTime, _pauseTime; |
|
AnimationState _previousState, _currentState; |
|
bool _repeated; |
|
UnsignedShort _repeatCount; |
|
UnsignedShort _repeats; |
|
}; |
|
|
|
/** |
|
@brief Animable for two-dimensional scenes |
|
|
|
Convenience alternative to @cpp Animable<2, T> @ce. See @ref Animable for more |
|
information. |
|
@see @ref Animable2D, @ref BasicAnimable3D |
|
*/ |
|
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ |
|
template<class T> using BasicAnimable2D = Animable<2, T>; |
|
#endif |
|
|
|
/** |
|
@brief Animable for two-dimensional float scenes |
|
|
|
@see @ref Animable3D |
|
*/ |
|
typedef BasicAnimable2D<Float> Animable2D; |
|
|
|
/** |
|
@brief Animable for three-dimensional scenes |
|
|
|
Convenience alternative to @cpp Animable<3, T> @ce. See @ref Animable for more |
|
information. |
|
@see @ref Animable3D, @ref BasicAnimable2D |
|
*/ |
|
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ |
|
template<class T> using BasicAnimable3D = Animable<3, T>; |
|
#endif |
|
|
|
/** |
|
@brief Animable for three-dimensional float scenes |
|
|
|
@see @ref Animable2D |
|
*/ |
|
typedef BasicAnimable3D<Float> Animable3D; |
|
|
|
#if defined(CORRADE_TARGET_WINDOWS) && !defined(__MINGW32__) |
|
extern template class MAGNUM_SCENEGRAPH_EXPORT Animable<2, Float>; |
|
extern template class MAGNUM_SCENEGRAPH_EXPORT Animable<3, Float>; |
|
#endif |
|
|
|
}} |
|
|
|
#endif
|
|
|