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.
362 lines
13 KiB
362 lines
13 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 |
|
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. |
|
*/ |
|
|
|
#include <sstream> |
|
#include <Corrade/TestSuite/Tester.h> |
|
|
|
#include "Magnum/SceneGraph/Animable.h" |
|
#include "Magnum/SceneGraph/AnimableGroup.h" |
|
#include "Magnum/SceneGraph/MatrixTransformation3D.h" |
|
|
|
namespace Magnum { namespace SceneGraph { namespace Test { |
|
|
|
struct AnimableTest: TestSuite::Tester { |
|
explicit AnimableTest(); |
|
|
|
void state(); |
|
void step(); |
|
void duration(); |
|
void repeat(); |
|
void stop(); |
|
void pause(); |
|
|
|
void debug(); |
|
}; |
|
|
|
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D; |
|
|
|
AnimableTest::AnimableTest() { |
|
addTests({&AnimableTest::state, |
|
&AnimableTest::step, |
|
&AnimableTest::duration, |
|
&AnimableTest::repeat, |
|
&AnimableTest::stop, |
|
&AnimableTest::pause, |
|
|
|
&AnimableTest::debug}); |
|
} |
|
|
|
void AnimableTest::state() { |
|
class StateTrackingAnimable: public SceneGraph::Animable3D { |
|
public: |
|
StateTrackingAnimable(AbstractObject3D& object, AnimableGroup3D* group = nullptr): SceneGraph::Animable3D(object, group) { |
|
setDuration(1.0f); |
|
} |
|
|
|
std::string trackedState; |
|
|
|
protected: |
|
void animationStep(Float, Float) override {} |
|
|
|
void animationStarted() override { trackedState += "started"; } |
|
void animationPaused() override { trackedState += "paused"; } |
|
void animationResumed() override { trackedState += "resumed"; } |
|
void animationStopped() override { trackedState += "stopped"; } |
|
}; |
|
|
|
Object3D object; |
|
AnimableGroup3D group; |
|
CORRADE_COMPARE(group.runningCount(), 0); |
|
|
|
/* Verify initial state */ |
|
StateTrackingAnimable animable(object, &group); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Stopped); |
|
CORRADE_VERIFY(animable.trackedState.empty()); |
|
group.step(1.0f, 1.0f); |
|
CORRADE_VERIFY(animable.trackedState.empty()); |
|
CORRADE_COMPARE(group.runningCount(), 0); |
|
|
|
/* Stopped -> paused is not supported */ |
|
CORRADE_COMPARE(animable.state(), AnimationState::Stopped); |
|
animable.setState(AnimationState::Paused); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Stopped); |
|
|
|
/* Stopped -> running */ |
|
CORRADE_COMPARE(animable.state(), AnimationState::Stopped); |
|
animable.trackedState.clear(); |
|
animable.setState(AnimationState::Running); |
|
CORRADE_VERIFY(animable.trackedState.empty()); |
|
group.step(1.0f, 1.0f); |
|
CORRADE_COMPARE(animable.trackedState, "started"); |
|
CORRADE_COMPARE(group.runningCount(), 1); |
|
|
|
/* Running -> paused */ |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
animable.trackedState.clear(); |
|
animable.setState(AnimationState::Paused); |
|
CORRADE_VERIFY(animable.trackedState.empty()); |
|
group.step(1.0f, 1.0f); |
|
CORRADE_COMPARE(animable.trackedState, "paused"); |
|
CORRADE_COMPARE(group.runningCount(), 0); |
|
|
|
/* Paused -> running */ |
|
CORRADE_COMPARE(animable.state(), AnimationState::Paused); |
|
animable.trackedState.clear(); |
|
animable.setState(AnimationState::Running); |
|
CORRADE_VERIFY(animable.trackedState.empty()); |
|
group.step(1.0f, 1.0f); |
|
CORRADE_COMPARE(animable.trackedState, "resumed"); |
|
CORRADE_COMPARE(group.runningCount(), 1); |
|
|
|
/* Running -> stopped */ |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
animable.trackedState.clear(); |
|
animable.setState(AnimationState::Stopped); |
|
CORRADE_VERIFY(animable.trackedState.empty()); |
|
group.step(1.0f, 1.0f); |
|
CORRADE_COMPARE(animable.trackedState, "stopped"); |
|
CORRADE_COMPARE(group.runningCount(), 0); |
|
|
|
animable.setState(AnimationState::Running); |
|
group.step(1.0f, 1.0f); |
|
animable.setState(AnimationState::Paused); |
|
|
|
/* Paused -> stopped */ |
|
CORRADE_COMPARE(animable.state(), AnimationState::Paused); |
|
animable.trackedState.clear(); |
|
animable.setState(AnimationState::Stopped); |
|
CORRADE_VERIFY(animable.trackedState.empty()); |
|
group.step(1.0f, 1.0f); |
|
CORRADE_COMPARE(animable.trackedState, "stopped"); |
|
CORRADE_COMPARE(group.runningCount(), 0); |
|
|
|
/* Verify running count can go past 0/1 */ |
|
auto a = new StateTrackingAnimable(object, &group); |
|
auto b = new StateTrackingAnimable(object, &group); |
|
a->setState(AnimationState::Running); |
|
b->setState(AnimationState::Running); |
|
group.add(*a).add(*b); |
|
group.step(1.0f, 1.0f); |
|
CORRADE_COMPARE(group.runningCount(), 2); |
|
} |
|
|
|
class OneShotAnimable: public SceneGraph::Animable3D { |
|
public: |
|
OneShotAnimable(AbstractObject3D& object, AnimableGroup3D* group = nullptr): SceneGraph::Animable3D(object, group), time(-1.0f) { |
|
setDuration(10.0f); |
|
setState(AnimationState::Running); |
|
} |
|
|
|
Float time; |
|
std::string stateChanges; |
|
|
|
protected: |
|
void animationStep(Float t, Float) override { |
|
time = t; |
|
} |
|
|
|
void animationStarted() override { |
|
stateChanges += "started;"; |
|
} |
|
|
|
void animationStopped() override { |
|
stateChanges += "stopped;"; |
|
} |
|
}; |
|
|
|
void AnimableTest::step() { |
|
class InifiniteAnimable: public SceneGraph::Animable3D { |
|
public: |
|
InifiniteAnimable(AbstractObject3D& object, AnimableGroup3D* group = nullptr): SceneGraph::Animable3D(object, group), time(-1.0f), delta(0.0f) {} |
|
|
|
Float time, delta; |
|
|
|
protected: |
|
void animationStep(Float t, Float d) override { |
|
time = t; |
|
delta = d; |
|
} |
|
}; |
|
|
|
Object3D object; |
|
AnimableGroup3D group; |
|
InifiniteAnimable animable(object, &group); |
|
|
|
/* Calling step() if no object is running should do nothing */ |
|
group.step(5.0f, 0.5f); |
|
CORRADE_COMPARE(group.runningCount(), 0); |
|
CORRADE_COMPARE(animable.time, -1.0f); |
|
CORRADE_COMPARE(animable.delta, 0.0f); |
|
|
|
/* Calling step() with running animation should start it with zero |
|
absolute time */ |
|
animable.setState(AnimationState::Running); |
|
group.step(5.0f, 0.5f); |
|
CORRADE_COMPARE(group.runningCount(), 1); |
|
CORRADE_COMPARE(animable.time, 0.0f); |
|
CORRADE_COMPARE(animable.delta, 0.5f); |
|
|
|
/* Repeated call to step() will add to absolute animation time */ |
|
group.step(8.0f, 0.75f); |
|
CORRADE_COMPARE(animable.time, 3.0f); |
|
CORRADE_COMPARE(animable.delta, 0.75f); |
|
} |
|
|
|
void AnimableTest::duration() { |
|
Object3D object; |
|
AnimableGroup3D group; |
|
OneShotAnimable animable(object, &group); |
|
CORRADE_VERIFY(!animable.isRepeated()); |
|
|
|
/* First animation step is in duration, verify that animation is still |
|
running and animationStep() is called */ |
|
group.step(1.0f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
CORRADE_COMPARE(animable.stateChanges, "started;"); |
|
CORRADE_COMPARE(animable.time, 0.0f); |
|
|
|
/* Next animation step is out of duration and repeat is not enabled, |
|
animationStep() shouldn't be called and animation should be stopped */ |
|
group.step(12.75f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Stopped); |
|
CORRADE_COMPARE(animable.stateChanges, "started;stopped;"); |
|
CORRADE_COMPARE(animable.time, 0.0f); |
|
} |
|
|
|
void AnimableTest::repeat() { |
|
class RepeatingAnimable: public SceneGraph::Animable3D { |
|
public: |
|
RepeatingAnimable(AbstractObject3D& object, AnimableGroup3D* group = nullptr): SceneGraph::Animable3D(object, group), time(-1.0f) { |
|
setDuration(10.0f); |
|
setState(AnimationState::Running); |
|
setRepeated(true); |
|
} |
|
|
|
Float time; |
|
|
|
protected: |
|
void animationStep(Float t, Float) override { |
|
time = t; |
|
} |
|
}; |
|
|
|
Object3D object; |
|
AnimableGroup3D group; |
|
RepeatingAnimable animable(object, &group); |
|
CORRADE_COMPARE(animable.repeatCount(), 0); |
|
|
|
/* First animation steps is in first loop iteration */ |
|
group.step(1.0f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
CORRADE_COMPARE(animable.time, 0.0f); |
|
|
|
/* Next animation step is in second loop iteration, animation should be |
|
still running with time shifted by animation duration */ |
|
group.step(11.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
CORRADE_COMPARE(animable.time, 0.5f); |
|
|
|
/* Third loop iteration (just to be sure) */ |
|
group.step(25.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
CORRADE_COMPARE(animable.time, 4.5f); |
|
|
|
/* Cap repeat count to 3, the animation should be stopped now (and |
|
animationStep() shouldn't be called)*/ |
|
animable.setRepeatCount(3); |
|
group.step(33.0f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Stopped); |
|
CORRADE_COMPARE(animable.time, 4.5f); |
|
|
|
/* Starting the animation again, should be repeatable again */ |
|
animable.setState(AnimationState::Running); |
|
|
|
/* Three animation repeats */ |
|
group.step(1.0f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
group.step(11.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
group.step(25.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
|
|
/* Should be stopped now */ |
|
group.step(33.0f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Stopped); |
|
} |
|
|
|
void AnimableTest::stop() { |
|
Object3D object; |
|
AnimableGroup3D group; |
|
OneShotAnimable animable(object, &group); |
|
CORRADE_COMPARE(animable.repeatCount(), 0); |
|
|
|
/* Eat up some absolute time */ |
|
group.step(1.0f, 0.5f); |
|
group.step(1.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
CORRADE_COMPARE(animable.time, 0.5f); |
|
|
|
/* Stop the animable, nothing should be done */ |
|
animable.setState(AnimationState::Stopped); |
|
group.step(1.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Stopped); |
|
CORRADE_COMPARE(animable.time, 0.5f); |
|
|
|
/* Restarting the animation should start with zero absolute time */ |
|
animable.setState(AnimationState::Running); |
|
group.step(2.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
CORRADE_COMPARE(animable.time, 0.0f); |
|
} |
|
|
|
void AnimableTest::pause() { |
|
Object3D object; |
|
AnimableGroup3D group; |
|
OneShotAnimable animable(object, &group); |
|
|
|
/* First two steps, animation is running */ |
|
group.step(1.0f, 0.5f); |
|
group.step(2.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
CORRADE_COMPARE(animable.time, 1.5f); |
|
|
|
/* Pausing the animation, first step should decrease count of running |
|
animations and save paused time, next steps shouldn't affect anything */ |
|
CORRADE_COMPARE(group.runningCount(), 1); |
|
animable.setState(AnimationState::Paused); |
|
CORRADE_COMPARE(group.runningCount(), 1); |
|
group.step(3.0f, 0.5f); |
|
CORRADE_COMPARE(group.runningCount(), 0); |
|
group.step(4.5f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Paused); |
|
CORRADE_COMPARE(animable.time, 1.5f); |
|
|
|
/* Unpausing, next step should continue from absolute time when pause |
|
occured */ |
|
animable.setState(AnimationState::Running); |
|
group.step(5.0f, 0.5f); |
|
CORRADE_COMPARE(animable.state(), AnimationState::Running); |
|
CORRADE_COMPARE(animable.time, 2.0f); |
|
} |
|
|
|
void AnimableTest::debug() { |
|
std::ostringstream o; |
|
Debug(&o) << AnimationState::Running << AnimationState(0xbe); |
|
CORRADE_COMPARE(o.str(), "SceneGraph::AnimationState::Running SceneGraph::AnimationState(0xbe)\n"); |
|
} |
|
|
|
}}} |
|
|
|
CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::AnimableTest)
|
|
|