|
|
|
|
/*
|
|
|
|
|
This file is part of Magnum.
|
|
|
|
|
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
|
|
|
|
2020, 2021, 2022 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 <Corrade/Utility/DebugStl.h>
|
|
|
|
|
|
|
|
|
|
#include "Magnum/Math/CubicHermite.h"
|
|
|
|
|
#include "Magnum/Math/Quaternion.h"
|
|
|
|
|
#include "Magnum/Trade/AnimationData.h"
|
|
|
|
|
|
|
|
|
|
namespace Magnum { namespace Trade { namespace Test { namespace {
|
|
|
|
|
|
|
|
|
|
struct AnimationDataTest: TestSuite::Tester {
|
|
|
|
|
explicit AnimationDataTest();
|
|
|
|
|
|
|
|
|
|
void debugTrackType();
|
|
|
|
|
void debugTrackTypePacked();
|
|
|
|
|
|
|
|
|
|
void customTrackTarget();
|
|
|
|
|
void customTrackTargetTooLarge();
|
|
|
|
|
void customTrackTargetNotCustom();
|
|
|
|
|
void debugTrackTarget();
|
|
|
|
|
void debugTrackTargetPacked();
|
|
|
|
|
|
|
|
|
|
void constructTrack();
|
|
|
|
|
void constructTrackResultType();
|
|
|
|
|
void constructTrackTemplate();
|
|
|
|
|
void constructTrackDefault();
|
|
|
|
|
#ifndef CORRADE_TARGET_32BIT
|
|
|
|
|
void constructTrackWrongSize();
|
|
|
|
|
#endif
|
|
|
|
|
void constructTrackWrongStride();
|
|
|
|
|
|
|
|
|
|
void construct();
|
|
|
|
|
void constructNotOwned();
|
|
|
|
|
void constructImplicitDuration();
|
|
|
|
|
void constructImplicitDurationEmpty();
|
|
|
|
|
void constructImplicitDurationNotOwned();
|
|
|
|
|
void constructNotOwnedFlagOwned();
|
|
|
|
|
void constructImplicitDurationNotOwnedFlagOwned();
|
|
|
|
|
|
|
|
|
|
void constructCopy();
|
|
|
|
|
void constructMove();
|
|
|
|
|
|
|
|
|
|
void mutableAccessNotAllowed();
|
|
|
|
|
|
|
|
|
|
void trackCustomResultType();
|
|
|
|
|
void trackWrongIndex();
|
|
|
|
|
void trackWrongType();
|
|
|
|
|
void trackWrongResultType();
|
|
|
|
|
|
|
|
|
|
void release();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
const char* name;
|
|
|
|
|
DataFlags dataFlags;
|
|
|
|
|
} NotOwnedData[] {
|
|
|
|
|
{"", {}},
|
|
|
|
|
{"mutable", DataFlag::Mutable},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
AnimationDataTest::AnimationDataTest() {
|
|
|
|
|
addTests({&AnimationDataTest::debugTrackType,
|
|
|
|
|
&AnimationDataTest::debugTrackTypePacked,
|
|
|
|
|
|
|
|
|
|
&AnimationDataTest::customTrackTarget,
|
|
|
|
|
&AnimationDataTest::customTrackTargetTooLarge,
|
|
|
|
|
&AnimationDataTest::customTrackTargetNotCustom,
|
|
|
|
|
&AnimationDataTest::debugTrackTarget,
|
|
|
|
|
&AnimationDataTest::debugTrackTargetPacked,
|
|
|
|
|
|
|
|
|
|
&AnimationDataTest::constructTrack,
|
|
|
|
|
&AnimationDataTest::constructTrackResultType,
|
|
|
|
|
&AnimationDataTest::constructTrackTemplate,
|
|
|
|
|
&AnimationDataTest::constructTrackDefault,
|
|
|
|
|
#ifndef CORRADE_TARGET_32BIT
|
|
|
|
|
&AnimationDataTest::constructTrackWrongSize,
|
|
|
|
|
#endif
|
|
|
|
|
&AnimationDataTest::constructTrackWrongStride,
|
|
|
|
|
|
|
|
|
|
&AnimationDataTest::construct,
|
|
|
|
|
&AnimationDataTest::constructImplicitDuration,
|
|
|
|
|
&AnimationDataTest::constructImplicitDurationEmpty});
|
|
|
|
|
|
|
|
|
|
addInstancedTests({&AnimationDataTest::constructNotOwned,
|
|
|
|
|
&AnimationDataTest::constructImplicitDurationNotOwned},
|
|
|
|
|
Containers::arraySize(NotOwnedData));
|
|
|
|
|
|
|
|
|
|
addTests({&AnimationDataTest::constructNotOwnedFlagOwned,
|
|
|
|
|
&AnimationDataTest::constructImplicitDurationNotOwnedFlagOwned,
|
|
|
|
|
|
|
|
|
|
&AnimationDataTest::constructCopy,
|
|
|
|
|
&AnimationDataTest::constructMove,
|
|
|
|
|
|
|
|
|
|
&AnimationDataTest::mutableAccessNotAllowed,
|
|
|
|
|
|
|
|
|
|
&AnimationDataTest::trackCustomResultType,
|
|
|
|
|
&AnimationDataTest::trackWrongIndex,
|
|
|
|
|
&AnimationDataTest::trackWrongType,
|
|
|
|
|
&AnimationDataTest::trackWrongResultType,
|
|
|
|
|
|
|
|
|
|
&AnimationDataTest::release});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using namespace Math::Literals;
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::debugTrackType() {
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
|
|
|
|
|
Debug{&out} << AnimationTrackType::DualQuaternion << AnimationTrackType(0xde);
|
|
|
|
|
CORRADE_COMPARE(out.str(), "Trade::AnimationTrackType::DualQuaternion Trade::AnimationTrackType(0xde)\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::debugTrackTypePacked() {
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
/* Second is not packed, the first should not make any flags persistent */
|
|
|
|
|
Debug{&out} << Debug::packed << AnimationTrackType::DualQuaternion << Debug::packed << AnimationTrackType(0xde) << AnimationTrackType::Float;
|
|
|
|
|
CORRADE_COMPARE(out.str(), "DualQuaternion 0xde Trade::AnimationTrackType::Float\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::customTrackTarget() {
|
|
|
|
|
CORRADE_VERIFY(!isAnimationTrackTargetCustom(AnimationTrackTarget::Rotation3D));
|
|
|
|
|
CORRADE_VERIFY(!isAnimationTrackTargetCustom(AnimationTrackTarget(32767)));
|
|
|
|
|
CORRADE_VERIFY(isAnimationTrackTargetCustom(AnimationTrackTarget(Implementation::AnimationTrackTargetCustom)));
|
|
|
|
|
CORRADE_VERIFY(isAnimationTrackTargetCustom(AnimationTrackTarget(65535)));
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(UnsignedShort(animationTrackTargetCustom(0)), 32768);
|
|
|
|
|
CORRADE_COMPARE(UnsignedShort(animationTrackTargetCustom(8290)), 41058);
|
|
|
|
|
CORRADE_COMPARE(UnsignedShort(animationTrackTargetCustom(32767)), 65535);
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(animationTrackTargetCustom(AnimationTrackTarget(Implementation::AnimationTrackTargetCustom)), 0);
|
|
|
|
|
CORRADE_COMPARE(animationTrackTargetCustom(AnimationTrackTarget(41058)), 8290);
|
|
|
|
|
CORRADE_COMPARE(animationTrackTargetCustom(AnimationTrackTarget(65535)), 32767);
|
|
|
|
|
|
|
|
|
|
constexpr bool is = isAnimationTrackTargetCustom(AnimationTrackTarget(41058));
|
|
|
|
|
CORRADE_VERIFY(is);
|
|
|
|
|
constexpr AnimationTrackTarget a = animationTrackTargetCustom(8290);
|
|
|
|
|
CORRADE_COMPARE(UnsignedShort(a), 41058);
|
|
|
|
|
constexpr UnsignedShort b = animationTrackTargetCustom(a);
|
|
|
|
|
CORRADE_COMPARE(b, 8290);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::customTrackTargetTooLarge() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
animationTrackTargetCustom(32768);
|
|
|
|
|
CORRADE_COMPARE(out.str(), "Trade::animationTrackTargetCustom(): index 32768 too large\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::customTrackTargetNotCustom() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
animationTrackTargetCustom(AnimationTrackTarget::Translation2D);
|
|
|
|
|
CORRADE_COMPARE(out.str(), "Trade::animationTrackTargetCustom(): Trade::AnimationTrackTarget::Translation2D is not custom\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::debugTrackTarget() {
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
|
|
|
|
|
Debug{&out} << AnimationTrackTarget::Rotation3D << animationTrackTargetCustom(9) << AnimationTrackTarget(0x4242);
|
|
|
|
|
CORRADE_COMPARE(out.str(), "Trade::AnimationTrackTarget::Rotation3D Trade::AnimationTrackTarget::Custom(9) Trade::AnimationTrackTarget(0x4242)\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::debugTrackTargetPacked() {
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
/* Last is not packed, ones before should not make any flags persistent */
|
|
|
|
|
Debug{&out} << Debug::packed << AnimationTrackTarget::Rotation3D << Debug::packed << animationTrackTargetCustom(120) << Debug::packed << AnimationTrackTarget(0x4242) << AnimationTrackType::Float;
|
|
|
|
|
CORRADE_COMPARE(out.str(), "Rotation3D Custom(120) 0x4242 Trade::AnimationTrackType::Float\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructTrack() {
|
|
|
|
|
AnimationTrackData data{
|
|
|
|
|
AnimationTrackType::Vector3,
|
|
|
|
|
AnimationTrackTarget::Translation3D, 42,
|
|
|
|
|
Animation::TrackView<const Float, const Vector3>{
|
|
|
|
|
nullptr,
|
|
|
|
|
Animation::Interpolation::Linear,
|
|
|
|
|
animationInterpolatorFor<Vector3>(Animation::Interpolation::Linear)}};
|
|
|
|
|
CORRADE_COMPARE(data.type(), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Translation3D);
|
|
|
|
|
CORRADE_COMPARE(data.target(), 42);
|
|
|
|
|
CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Linear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructTrackResultType() {
|
|
|
|
|
AnimationTrackData data{
|
|
|
|
|
AnimationTrackType::CubicHermite3D,
|
|
|
|
|
AnimationTrackType::Vector3,
|
|
|
|
|
AnimationTrackTarget::Translation3D, 42,
|
|
|
|
|
Animation::TrackView<const Float, const CubicHermite3D>{
|
|
|
|
|
nullptr,
|
|
|
|
|
Animation::Interpolation::Linear,
|
|
|
|
|
animationInterpolatorFor<CubicHermite3D>(Animation::Interpolation::Linear)}};
|
|
|
|
|
CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite3D);
|
|
|
|
|
CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Translation3D);
|
|
|
|
|
CORRADE_COMPARE(data.target(), 42);
|
|
|
|
|
CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Linear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructTrackTemplate() {
|
|
|
|
|
AnimationTrackData data{
|
|
|
|
|
AnimationTrackTarget::Translation3D, 42,
|
|
|
|
|
Animation::TrackView<const Float, const CubicHermite3D>{
|
|
|
|
|
nullptr,
|
|
|
|
|
Animation::Interpolation::Linear,
|
|
|
|
|
animationInterpolatorFor<CubicHermite3D>(Animation::Interpolation::Linear)}};
|
|
|
|
|
CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite3D);
|
|
|
|
|
CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Translation3D);
|
|
|
|
|
CORRADE_COMPARE(data.target(), 42);
|
|
|
|
|
CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Linear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructTrackDefault() {
|
|
|
|
|
AnimationTrackData data;
|
|
|
|
|
CORRADE_COMPARE(data.type(), AnimationTrackType{});
|
|
|
|
|
CORRADE_COMPARE(data.resultType(), AnimationTrackType{});
|
|
|
|
|
CORRADE_COMPARE(data.targetName(), AnimationTrackTarget{});
|
|
|
|
|
CORRADE_COMPARE(data.target(), 0);
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::Extrapolated);
|
|
|
|
|
CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::Extrapolated);
|
|
|
|
|
CORRADE_COMPARE(data.track().size(), 0);
|
|
|
|
|
CORRADE_COMPARE(data.track().interpolator(), nullptr);
|
|
|
|
|
CORRADE_COMPARE(data.track().keys().data(), nullptr);
|
|
|
|
|
CORRADE_COMPARE(data.track().values().data(), nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef CORRADE_TARGET_32BIT
|
|
|
|
|
void AnimationDataTest::constructTrackWrongSize() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
/* This should be fine */
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Rotation3D, 16, Animation::TrackView<const Float, const Quaternion>{
|
|
|
|
|
{nullptr, 0xffffffffu},
|
|
|
|
|
{nullptr, 0xffffffffu},
|
|
|
|
|
Animation::Interpolation::Constant
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Rotation3D, 16, Animation::TrackView<const Float, const Quaternion>{
|
|
|
|
|
{nullptr, 0x100000000ull},
|
|
|
|
|
{nullptr, 0x100000000ull},
|
|
|
|
|
Animation::Interpolation::Constant
|
|
|
|
|
}};
|
|
|
|
|
CORRADE_COMPARE(out.str(),
|
|
|
|
|
"Trade::AnimationTrackData: expected keyframe count to fit into 32 bits but got 4294967296\n");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructTrackWrongStride() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
char toomuch[2*(32768 + sizeof(Vector2))];
|
|
|
|
|
|
|
|
|
|
/* These should be fine */
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Scaling2D, 1, Animation::TrackView<const Float, const Vector2>{
|
|
|
|
|
Containers::StridedArrayView1D<Float>{Containers::arrayCast<Float>(toomuch), 2, 32767},
|
|
|
|
|
Containers::StridedArrayView1D<Vector2>{Containers::arrayCast<Vector2>(toomuch), 2, 32768}.flipped<0>(),
|
|
|
|
|
Animation::Interpolation::Constant
|
|
|
|
|
}};
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Scaling2D, 1, Animation::TrackView<const Float, const Vector2>{
|
|
|
|
|
Containers::StridedArrayView1D<Float>{Containers::arrayCast<Float>(toomuch), 2, 32768}.flipped<0>(),
|
|
|
|
|
Containers::StridedArrayView1D<Vector2>{Containers::arrayCast<Vector2>(toomuch), 2, 32767},
|
|
|
|
|
Animation::Interpolation::Constant
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Scaling2D, 1, Animation::TrackView<const Float, const Vector2>{
|
|
|
|
|
Containers::StridedArrayView1D<Float>{Containers::arrayCast<Float>(toomuch), 2, 32768},
|
|
|
|
|
Containers::StridedArrayView1D<Vector2>{Containers::arrayCast<Vector2>(toomuch), 2, 32767},
|
|
|
|
|
Animation::Interpolation::Constant
|
|
|
|
|
}};
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Scaling2D, 1, Animation::TrackView<const Float, const Vector2>{
|
|
|
|
|
Containers::StridedArrayView1D<Float>{Containers::arrayCast<Float>(toomuch), 2, 32769}.flipped<0>(),
|
|
|
|
|
Containers::StridedArrayView1D<Vector2>{Containers::arrayCast<Vector2>(toomuch), 2, 32767},
|
|
|
|
|
Animation::Interpolation::Constant
|
|
|
|
|
}};
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Scaling2D, 1, Animation::TrackView<const Float, const Vector2>{
|
|
|
|
|
Containers::StridedArrayView1D<Float>{Containers::arrayCast<Float>(toomuch), 2, 32767},
|
|
|
|
|
Containers::StridedArrayView1D<Vector2>{Containers::arrayCast<Vector2>(toomuch), 2, 32768},
|
|
|
|
|
Animation::Interpolation::Constant
|
|
|
|
|
}};
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Scaling2D, 1, Animation::TrackView<const Float, const Vector2>{
|
|
|
|
|
Containers::StridedArrayView1D<Float>{Containers::arrayCast<Float>(toomuch), 2, 32767},
|
|
|
|
|
Containers::StridedArrayView1D<Vector2>{Containers::arrayCast<Vector2>(toomuch), 2, 32769}.flipped<0>(),
|
|
|
|
|
Animation::Interpolation::Constant
|
|
|
|
|
}};
|
|
|
|
|
CORRADE_COMPARE(out.str(),
|
|
|
|
|
"Trade::AnimationTrackData: expected key stride to fit into 16 bits but got 32768\n"
|
|
|
|
|
"Trade::AnimationTrackData: expected key stride to fit into 16 bits but got -32769\n"
|
|
|
|
|
"Trade::AnimationTrackData: expected value stride to fit into 16 bits but got 32768\n"
|
|
|
|
|
"Trade::AnimationTrackData: expected value stride to fit into 16 bits but got -32769\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::construct() {
|
|
|
|
|
struct Data {
|
|
|
|
|
Float time;
|
|
|
|
|
Vector3 position;
|
|
|
|
|
Quaternion rotation;
|
|
|
|
|
};
|
|
|
|
|
Containers::Array<char> buffer{sizeof(Data)*3};
|
|
|
|
|
auto view = Containers::arrayCast<Data>(buffer);
|
|
|
|
|
view[0] = {0.0f, {3.0f, 1.0f, 0.1f}, Quaternion::rotation(45.0_degf, Vector3::yAxis())};
|
|
|
|
|
view[1] = {5.0f, {0.3f, 0.6f, 1.0f}, Quaternion::rotation(20.0_degf, Vector3::yAxis())};
|
|
|
|
|
view[2] = {7.5f, {1.0f, 0.3f, 2.1f}, Quaternion{}};
|
|
|
|
|
|
|
|
|
|
const int state = 5;
|
|
|
|
|
AnimationData data{std::move(buffer), {
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Translation3D, 42,
|
|
|
|
|
Animation::TrackView<const Float, const Vector3>{
|
|
|
|
|
{view, &view[0].time, view.size(), sizeof(Data)},
|
|
|
|
|
{view, &view[0].position, view.size(), sizeof(Data)},
|
|
|
|
|
Animation::Interpolation::Constant,
|
|
|
|
|
animationInterpolatorFor<Vector3>(Animation::Interpolation::Constant)}},
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Rotation3D, 1337,
|
|
|
|
|
Animation::TrackView<const Float, const Quaternion>{
|
|
|
|
|
{view, &view[0].time, view.size(), sizeof(Data)},
|
|
|
|
|
{view, &view[0].rotation, view.size(), sizeof(Data)},
|
|
|
|
|
Animation::Interpolation::Linear,
|
|
|
|
|
animationInterpolatorFor<Quaternion>(Animation::Interpolation::Linear)}}
|
|
|
|
|
}, {-1.0f, 7.0f}, &state};
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(data.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
|
|
|
|
|
CORRADE_COMPARE(data.duration(), (Range1D{-1.0f, 7.0f}));
|
|
|
|
|
CORRADE_COMPARE(static_cast<const void*>(data.data().data()), view.data());
|
|
|
|
|
CORRADE_COMPARE(static_cast<void*>(data.mutableData().data()), view.data());
|
|
|
|
|
CORRADE_COMPARE(data.trackCount(), 2);
|
|
|
|
|
CORRADE_COMPARE(data.importerState(), &state);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CORRADE_COMPARE(data.trackType(0), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(data.trackResultType(0), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(data.trackTargetName(0), AnimationTrackTarget::Translation3D);
|
|
|
|
|
CORRADE_COMPARE(data.trackTarget(0), 42);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const Vector3> track = data.track<Vector3>(0);
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(track.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f}));
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<Float, Vector3> mutableTrack = data.mutableTrack<Vector3>(0);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.keys().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.values().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f}));
|
|
|
|
|
} {
|
|
|
|
|
CORRADE_COMPARE(data.trackType(1), AnimationTrackType::Quaternion);
|
|
|
|
|
CORRADE_COMPARE(data.trackResultType(1), AnimationTrackType::Quaternion);
|
|
|
|
|
CORRADE_COMPARE(data.trackTargetName(1), AnimationTrackTarget::Rotation3D);
|
|
|
|
|
CORRADE_COMPARE(data.trackTarget(1), 1337);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const Quaternion> track = data.track<Quaternion>(1);
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Linear);
|
|
|
|
|
CORRADE_COMPARE(track.at(2.5f), Quaternion::rotation(32.5_degf, Vector3::yAxis()));
|
|
|
|
|
|
|
|
|
|
/* Testing the mutable track just once is enough */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructImplicitDuration() {
|
|
|
|
|
struct Data {
|
|
|
|
|
Float time;
|
|
|
|
|
bool value;
|
|
|
|
|
};
|
|
|
|
|
Containers::Array<char> buffer{sizeof(Data)*4};
|
|
|
|
|
auto view = Containers::arrayCast<Data>(buffer);
|
|
|
|
|
view[0] = {1.0f, true};
|
|
|
|
|
view[1] = {5.0f, false};
|
|
|
|
|
view[2] = {3.0f, true};
|
|
|
|
|
view[3] = {7.0f, false};
|
|
|
|
|
|
|
|
|
|
const int state = 5;
|
|
|
|
|
AnimationData data{std::move(buffer), {
|
|
|
|
|
AnimationTrackData{animationTrackTargetCustom(1), 0,
|
|
|
|
|
Animation::TrackView<const Float, const bool>{
|
|
|
|
|
{view, &view[0].time, 2, sizeof(Data)},
|
|
|
|
|
{view, &view[0].value, 2, sizeof(Data)},
|
|
|
|
|
Animation::Interpolation::Constant}},
|
|
|
|
|
AnimationTrackData{animationTrackTargetCustom(2), 1,
|
|
|
|
|
Animation::TrackView<const Float, const bool>{
|
|
|
|
|
{view, &view[2].time, 2, sizeof(Data)},
|
|
|
|
|
{view, &view[2].value, 2, sizeof(Data)},
|
|
|
|
|
Animation::Interpolation::Linear}}
|
|
|
|
|
}, &state};
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(data.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
|
|
|
|
|
CORRADE_COMPARE(data.duration(), (Range1D{1.0f, 7.0f}));
|
|
|
|
|
CORRADE_COMPARE(data.trackCount(), 2);
|
|
|
|
|
CORRADE_COMPARE(data.importerState(), &state);
|
|
|
|
|
{
|
|
|
|
|
CORRADE_COMPARE(data.trackType(0), AnimationTrackType::Bool);
|
|
|
|
|
CORRADE_COMPARE(data.trackResultType(0), AnimationTrackType::Bool);
|
|
|
|
|
CORRADE_COMPARE(data.trackTargetName(0), animationTrackTargetCustom(1));
|
|
|
|
|
CORRADE_COMPARE(data.trackTarget(0), 0);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const bool> track = data.track<bool>(0);
|
|
|
|
|
CORRADE_COMPARE(track.duration(), (Range1D{1.0f, 5.0f}));
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(track.at(6.0f), false);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<Float, bool> mutableTrack = data.mutableTrack<bool>(0);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.duration(), (Range1D{1.0f, 5.0f}));
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.keys().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.values().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.at(6.0f), false);
|
|
|
|
|
} {
|
|
|
|
|
CORRADE_COMPARE(data.trackType(1), AnimationTrackType::Bool);
|
|
|
|
|
CORRADE_COMPARE(data.trackResultType(1), AnimationTrackType::Bool);
|
|
|
|
|
CORRADE_COMPARE(data.trackTargetName(1), animationTrackTargetCustom(2));
|
|
|
|
|
CORRADE_COMPARE(data.trackTarget(1), 1);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const bool> track = data.track<bool>(1);
|
|
|
|
|
CORRADE_COMPARE(track.duration(), (Range1D{3.0f, 7.0f}));
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Linear);
|
|
|
|
|
CORRADE_COMPARE(track.at(4.5f), true);
|
|
|
|
|
|
|
|
|
|
/* Testing the mutable track just once is enough */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructImplicitDurationEmpty() {
|
|
|
|
|
AnimationData data{nullptr, nullptr};
|
|
|
|
|
CORRADE_COMPARE(data.duration(), Range1D{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructNotOwned() {
|
|
|
|
|
auto&& instanceData = NotOwnedData[testCaseInstanceId()];
|
|
|
|
|
setTestCaseDescription(instanceData.name);
|
|
|
|
|
|
|
|
|
|
std::pair<Float, Vector3> keyframes[] {
|
|
|
|
|
{0.0f, {3.0f, 1.0f, 0.1f}},
|
|
|
|
|
{5.0f, {0.3f, 0.6f, 1.0f}}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const int state = 5;
|
|
|
|
|
AnimationData data{instanceData.dataFlags, keyframes, {
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Translation3D, 42,
|
|
|
|
|
Animation::TrackView<const Float, const Vector3>{
|
|
|
|
|
keyframes,
|
|
|
|
|
Animation::Interpolation::Constant,
|
|
|
|
|
animationInterpolatorFor<Vector3>(Animation::Interpolation::Constant)}}
|
|
|
|
|
}, {-1.0f, 7.0f}, &state};
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(data.dataFlags(), instanceData.dataFlags);
|
|
|
|
|
CORRADE_COMPARE(data.duration(), (Range1D{-1.0f, 7.0f}));
|
|
|
|
|
CORRADE_COMPARE(static_cast<const void*>(data.data().data()), keyframes);
|
|
|
|
|
if(instanceData.dataFlags & DataFlag::Mutable)
|
|
|
|
|
CORRADE_COMPARE(static_cast<const void*>(data.mutableData().data()), keyframes);
|
|
|
|
|
CORRADE_COMPARE(data.trackCount(), 1);
|
|
|
|
|
CORRADE_COMPARE(data.importerState(), &state);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CORRADE_COMPARE(data.trackType(0), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(data.trackResultType(0), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(data.trackTargetName(0), AnimationTrackTarget::Translation3D);
|
|
|
|
|
CORRADE_COMPARE(data.trackTarget(0), 42);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const Vector3> track = data.track<Vector3>(0);
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(track.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f}));
|
|
|
|
|
|
|
|
|
|
if(instanceData.dataFlags & DataFlag::Mutable) {
|
|
|
|
|
Animation::TrackView<Float, Vector3> mutableTrack = data.mutableTrack<Vector3>(0);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.keys().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.values().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructImplicitDurationNotOwned() {
|
|
|
|
|
auto&& instanceData = NotOwnedData[testCaseInstanceId()];
|
|
|
|
|
setTestCaseDescription(instanceData.name);
|
|
|
|
|
|
|
|
|
|
std::pair<Float, bool> keyframes[] {
|
|
|
|
|
{1.0f, true},
|
|
|
|
|
{5.0f, false}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const int state = 5;
|
|
|
|
|
AnimationData data{instanceData.dataFlags, keyframes, {
|
|
|
|
|
AnimationTrackData{animationTrackTargetCustom(1), 0,
|
|
|
|
|
Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}},
|
|
|
|
|
}, &state};
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(data.dataFlags(), instanceData.dataFlags);
|
|
|
|
|
CORRADE_COMPARE(data.duration(), (Range1D{1.0f, 5.0f}));
|
|
|
|
|
CORRADE_COMPARE(static_cast<const void*>(data.data().data()), keyframes);
|
|
|
|
|
if(instanceData.dataFlags & DataFlag::Mutable)
|
|
|
|
|
CORRADE_COMPARE(static_cast<const void*>(data.mutableData().data()), keyframes);
|
|
|
|
|
CORRADE_COMPARE(data.trackCount(), 1);
|
|
|
|
|
CORRADE_COMPARE(data.importerState(), &state);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CORRADE_COMPARE(data.trackType(0), AnimationTrackType::Bool);
|
|
|
|
|
CORRADE_COMPARE(data.trackResultType(0), AnimationTrackType::Bool);
|
|
|
|
|
CORRADE_COMPARE(data.trackTargetName(0), animationTrackTargetCustom(1));
|
|
|
|
|
CORRADE_COMPARE(data.trackTarget(0), 0);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const bool> track = data.track<bool>(0);
|
|
|
|
|
CORRADE_COMPARE(track.duration(), (Range1D{1.0f, 5.0f}));
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(track.at(3.0f), true);
|
|
|
|
|
|
|
|
|
|
if(instanceData.dataFlags & DataFlag::Mutable) {
|
|
|
|
|
Animation::TrackView<Float, bool> mutableTrack = data.mutableTrack<bool>(0);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.duration(), (Range1D{1.0f, 5.0f}));
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.keys().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.values().size(), 2);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(mutableTrack.at(3.0f), true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructNotOwnedFlagOwned() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
AnimationData data{DataFlag::Owned, nullptr, {}, {-1.0f, 7.0f}};
|
|
|
|
|
CORRADE_COMPARE(out.str(),
|
|
|
|
|
"Trade::AnimationData: can't construct a non-owned instance with Trade::DataFlag::Owned\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructImplicitDurationNotOwnedFlagOwned() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
AnimationData data{DataFlag::Owned, nullptr, {}};
|
|
|
|
|
CORRADE_COMPARE(out.str(),
|
|
|
|
|
"Trade::AnimationData: can't construct a non-owned instance with Trade::DataFlag::Owned\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructCopy() {
|
|
|
|
|
CORRADE_VERIFY(!std::is_copy_constructible<AnimationData>{});
|
|
|
|
|
CORRADE_VERIFY(!std::is_copy_assignable<AnimationData>{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::constructMove() {
|
|
|
|
|
/* Ugh and here we go again! */
|
|
|
|
|
struct Data {
|
|
|
|
|
Float time;
|
|
|
|
|
Vector3 position;
|
|
|
|
|
Quaternion rotation;
|
|
|
|
|
};
|
|
|
|
|
Containers::Array<char> buffer{sizeof(Data)*3};
|
|
|
|
|
auto view = Containers::arrayCast<Data>(buffer);
|
|
|
|
|
view[0] = {0.0f, {3.0f, 1.0f, 0.1f}, Quaternion::rotation(45.0_degf, Vector3::yAxis())};
|
|
|
|
|
view[1] = {5.0f, {0.3f, 0.6f, 1.0f}, Quaternion::rotation(20.0_degf, Vector3::yAxis())};
|
|
|
|
|
view[2] = {7.5f, {1.0f, 0.3f, 2.1f}, Quaternion{}};
|
|
|
|
|
|
|
|
|
|
const int state = 5;
|
|
|
|
|
AnimationData a{std::move(buffer), {
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Translation3D, 42,
|
|
|
|
|
Animation::TrackView<const Float, const Vector3>{
|
|
|
|
|
{view, &view[0].time, view.size(), sizeof(Data)},
|
|
|
|
|
{view, &view[0].position, view.size(), sizeof(Data)},
|
|
|
|
|
Animation::Interpolation::Constant,
|
|
|
|
|
animationInterpolatorFor<Vector3>(Animation::Interpolation::Constant)}},
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Rotation3D, 1337,
|
|
|
|
|
Animation::TrackView<const Float, const Quaternion>{
|
|
|
|
|
{view, &view[0].time, view.size(), sizeof(Data)},
|
|
|
|
|
{view, &view[0].rotation, view.size(), sizeof(Data)},
|
|
|
|
|
Animation::Interpolation::Linear,
|
|
|
|
|
animationInterpolatorFor<Quaternion>(Animation::Interpolation::Linear)}}
|
|
|
|
|
}, {-1.0f, 7.0f}, &state};
|
|
|
|
|
|
|
|
|
|
AnimationData b{std::move(a)};
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(b.duration(), (Range1D{-1.0f, 7.0f}));
|
|
|
|
|
CORRADE_COMPARE(b.data().size(), sizeof(Data)*3);
|
|
|
|
|
CORRADE_COMPARE(b.trackCount(), 2);
|
|
|
|
|
CORRADE_COMPARE(b.importerState(), &state);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CORRADE_COMPARE(b.trackType(0), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(b.trackResultType(0), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(b.trackTargetName(0), AnimationTrackTarget::Translation3D);
|
|
|
|
|
CORRADE_COMPARE(b.trackTarget(0), 42);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const Vector3> track = b.track<Vector3>(0);
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(track.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f}));
|
|
|
|
|
} {
|
|
|
|
|
CORRADE_COMPARE(b.trackType(1), AnimationTrackType::Quaternion);
|
|
|
|
|
CORRADE_COMPARE(b.trackResultType(1), AnimationTrackType::Quaternion);
|
|
|
|
|
CORRADE_COMPARE(b.trackTargetName(1), AnimationTrackTarget::Rotation3D);
|
|
|
|
|
CORRADE_COMPARE(b.trackTarget(1), 1337);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const Quaternion> track = b.track<Quaternion>(1);
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Linear);
|
|
|
|
|
CORRADE_COMPARE(track.at(2.5f), Quaternion::rotation(32.5_degf, Vector3::yAxis()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int other;
|
|
|
|
|
AnimationData c{nullptr, nullptr, &other};
|
|
|
|
|
c = std::move(b);
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(c.duration(), (Range1D{-1.0f, 7.0f}));
|
|
|
|
|
CORRADE_COMPARE(c.data().size(), sizeof(Data)*3);
|
|
|
|
|
CORRADE_COMPARE(c.trackCount(), 2);
|
|
|
|
|
CORRADE_COMPARE(c.importerState(), &state);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CORRADE_COMPARE(c.trackType(0), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(c.trackResultType(0), AnimationTrackType::Vector3);
|
|
|
|
|
CORRADE_COMPARE(c.trackTargetName(0), AnimationTrackTarget::Translation3D);
|
|
|
|
|
CORRADE_COMPARE(c.trackTarget(0), 42);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const Vector3> track = c.track<Vector3>(0);
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant);
|
|
|
|
|
CORRADE_COMPARE(track.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f}));
|
|
|
|
|
} {
|
|
|
|
|
CORRADE_COMPARE(c.trackType(1), AnimationTrackType::Quaternion);
|
|
|
|
|
CORRADE_COMPARE(c.trackResultType(1), AnimationTrackType::Quaternion);
|
|
|
|
|
CORRADE_COMPARE(c.trackTargetName(1), AnimationTrackTarget::Rotation3D);
|
|
|
|
|
CORRADE_COMPARE(c.trackTarget(1), 1337);
|
|
|
|
|
|
|
|
|
|
Animation::TrackView<const Float, const Quaternion> track = c.track<Quaternion>(1);
|
|
|
|
|
CORRADE_COMPARE(track.keys().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.values().size(), 3);
|
|
|
|
|
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Linear);
|
|
|
|
|
CORRADE_COMPARE(track.at(2.5f), Quaternion::rotation(32.5_degf, Vector3::yAxis()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CORRADE_VERIFY(std::is_nothrow_move_constructible<AnimationData>::value);
|
|
|
|
|
CORRADE_VERIFY(std::is_nothrow_move_assignable<AnimationData>::value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::mutableAccessNotAllowed() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
const std::pair<Float, bool> keyframes[] {
|
|
|
|
|
{1.0f, true},
|
|
|
|
|
{5.0f, false}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
AnimationData data{{}, keyframes, {
|
|
|
|
|
AnimationTrackData{animationTrackTargetCustom(1), 0,
|
|
|
|
|
Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}},
|
|
|
|
|
}};
|
|
|
|
|
CORRADE_COMPARE(data.dataFlags(), DataFlags{});
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
data.mutableData();
|
|
|
|
|
data.mutableTrack(0);
|
|
|
|
|
data.mutableTrack<bool>(0);
|
|
|
|
|
CORRADE_COMPARE(out.str(),
|
|
|
|
|
"Trade::AnimationData::mutableData(): the animation is not mutable\n"
|
|
|
|
|
"Trade::AnimationData::mutableTrack(): the animation is not mutable\n"
|
|
|
|
|
"Trade::AnimationData::mutableTrack(): the animation is not mutable\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::trackCustomResultType() {
|
|
|
|
|
using namespace Math::Literals;
|
|
|
|
|
|
|
|
|
|
struct Data {
|
|
|
|
|
Float time;
|
|
|
|
|
Vector3i position;
|
|
|
|
|
};
|
|
|
|
|
Containers::Array<char> buffer{sizeof(Data)*3};
|
|
|
|
|
auto view = Containers::arrayCast<Data>(buffer);
|
|
|
|
|
view[0] = {0.0f, {300, 100, 10}};
|
|
|
|
|
view[1] = {5.0f, {30, 60, 100}};
|
|
|
|
|
|
|
|
|
|
AnimationData data{std::move(buffer), {
|
|
|
|
|
AnimationTrackData{AnimationTrackTarget::Scaling3D, 0,
|
|
|
|
|
Animation::TrackView<const Float, const Vector3i, Vector3>{
|
|
|
|
|
{view, &view[0].time, view.size(), sizeof(Data)},
|
|
|
|
|
{view, &view[0].position, view.size(), sizeof(Data)},
|
|
|
|
|
[](const Vector3i& a, const Vector3i& b, Float t) -> Vector3 {
|
|
|
|
|
return Math::lerp(Vector3{a}*0.01f, Vector3{b}*0.01f, t);
|
|
|
|
|
}}}
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE((data.track<Vector3i, Vector3>(0).at(2.5f)), (Vector3{1.65f, 0.8f, 0.55f}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::trackWrongIndex() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
|
|
|
|
|
AnimationData data{nullptr, {
|
|
|
|
|
AnimationTrackData{AnimationTrackType::Vector3,
|
|
|
|
|
AnimationTrackTarget::Scaling3D, 0, {}}
|
|
|
|
|
}};
|
|
|
|
|
data.trackType(1);
|
|
|
|
|
data.trackResultType(1);
|
|
|
|
|
data.trackTargetName(1);
|
|
|
|
|
data.trackTarget(1);
|
|
|
|
|
data.track(1);
|
|
|
|
|
data.mutableTrack(1);
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(out.str(),
|
|
|
|
|
"Trade::AnimationData::trackType(): index 1 out of range for 1 tracks\n"
|
|
|
|
|
"Trade::AnimationData::trackResultType(): index 1 out of range for 1 tracks\n"
|
|
|
|
|
"Trade::AnimationData::trackTargetName(): index 1 out of range for 1 tracks\n"
|
|
|
|
|
"Trade::AnimationData::trackTarget(): index 1 out of range for 1 tracks\n"
|
|
|
|
|
"Trade::AnimationData::track(): index 1 out of range for 1 tracks\n"
|
|
|
|
|
"Trade::AnimationData::mutableTrack(): index 1 out of range for 1 tracks\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::trackWrongType() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
|
|
|
|
|
AnimationData data{nullptr, {
|
|
|
|
|
AnimationTrackData{AnimationTrackType::Vector3i,
|
|
|
|
|
AnimationTrackType::Vector3,
|
|
|
|
|
AnimationTrackTarget::Scaling3D, 0, {}}
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
data.track<Vector3>(0);
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(out.str(), "Trade::AnimationData::track(): improper type requested for Trade::AnimationTrackType::Vector3i\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::trackWrongResultType() {
|
|
|
|
|
CORRADE_SKIP_IF_NO_ASSERT();
|
|
|
|
|
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
Error redirectError{&out};
|
|
|
|
|
|
|
|
|
|
AnimationData data{nullptr, {
|
|
|
|
|
AnimationTrackData{AnimationTrackType::Vector3i,
|
|
|
|
|
AnimationTrackType::Vector3,
|
|
|
|
|
AnimationTrackTarget::Scaling3D, 0, {}}
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
data.track<Vector3i, Vector2>(0);
|
|
|
|
|
|
|
|
|
|
CORRADE_COMPARE(out.str(), "Trade::AnimationData::track(): improper result type requested for Trade::AnimationTrackType::Vector3\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AnimationDataTest::release() {
|
|
|
|
|
const std::pair<Float, bool> keyframes[] {
|
|
|
|
|
{1.0f, true},
|
|
|
|
|
{5.0f, false}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
AnimationData data{{}, keyframes, {
|
|
|
|
|
AnimationTrackData{animationTrackTargetCustom(1), 0,
|
|
|
|
|
Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}},
|
|
|
|
|
}};
|
|
|
|
|
CORRADE_COMPARE(data.trackCount(), 1);
|
|
|
|
|
|
|
|
|
|
Containers::Array<char> released = data.release();
|
|
|
|
|
CORRADE_COMPARE(data.data(), static_cast<const void*>(nullptr));
|
|
|
|
|
CORRADE_COMPARE(data.trackCount(), 0);
|
|
|
|
|
CORRADE_COMPARE(static_cast<const void*>(released.data()), keyframes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}}}}
|
|
|
|
|
|
|
|
|
|
CORRADE_TEST_MAIN(Magnum::Trade::Test::AnimationDataTest)
|