From 94e9961a309692fcbc0bbe15e356009f4bfb84e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Apr 2023 19:44:33 +0200 Subject: [PATCH] Trade: provide better AnimationTrackData constructors. Taking Animation::TrackViewStorage wasn't really a good idea, as it wasn't solving anything -- in order to create it, there needs to be a TrackView of a concrete type first anyway, and even then it required a lot of additional verbose typing. The new constructors take basically what TrackView takes, plus there's additionally a constructor that takes a typeless value view together with explicitly specified value and result types, allowing a truly type-erased usage. On the other hand, the templated variants directly deduce the types without any additional typing, making the construction similarly straightforward to e.g. SceneFieldData. In case of the type-erased constructors, if the interpolator function isn't supplied explicitly, an implicit one is picked based on the value type, result type and interpolation. Not all combinations make sense of course, so this is a new assertion point, however compared to the previous way where the interpolator was picked from a *typed* TrackView, this doesn't add any new restriction -- what asserted there, asserts now as well, and additionally you can't have e.g. a Quaternion track with a boolean result. I may also be eventually adding assertions to check that the target name matches the result type -- so e.g. a rotation isn't specified as an integer and such. Compared to newer APIs like MeshData, MaterialData or SceneData the AnimationData API has a significant lack of sanity asserts like this. --- doc/changelog.dox | 8 + src/Magnum/Trade/AnimationData.cpp | 75 +++- src/Magnum/Trade/AnimationData.h | 250 +++++++++++- .../Trade/Test/AbstractImporterTest.cpp | 5 +- src/Magnum/Trade/Test/AnimationDataTest.cpp | 379 ++++++++++++++++-- 5 files changed, 658 insertions(+), 59 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 13941357a..eda6723fd 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -1053,6 +1053,14 @@ See also: - @cpp Trade::AbstractMaterialData @ce as well as its containing header `Magnum/Trade/AbstractMaterialData.h` is now a deprecated alias to the new and more flexible @ref Trade::MaterialData. +- @ref Trade::AnimationTrackData constructors taking + @ref Animation::TrackViewStorage are deprecated in favor of significantly + less verbose variants that take key/value views and other track parameters + directly, allowing them to either directly deduce the value type or be + truly type-erased, no longer requiring user code to manually handle all + possible cases. The variant taking an @ref Animation::TrackView is kept + however as it may be convenient when exporting already-populated animation + instances. - @cpp Trade::LightData::Type::Infinite @ce, originally adapted from the OpenGEX specification, is deprecated in favor of @ref Trade::LightData::Type::Directional as that's the more commonly used diff --git a/src/Magnum/Trade/AnimationData.cpp b/src/Magnum/Trade/AnimationData.cpp index d10995562..e6b3f7e58 100644 --- a/src/Magnum/Trade/AnimationData.cpp +++ b/src/Magnum/Trade/AnimationData.cpp @@ -33,17 +33,78 @@ namespace Magnum { namespace Trade { -AnimationTrackData::AnimationTrackData(const AnimationTrackType type, const AnimationTrackType resultType, const AnimationTrackTarget targetName, const UnsignedLong target, const Animation::TrackViewStorage& view) noexcept: _type{type}, _resultType{resultType}, _targetName{targetName}, _interpolation{view.interpolation()}, _before{view.before()}, _after{view.after()}, _target{target}, _size{UnsignedInt(view.size())}, _keysStride{Short(view.keys().stride())}, _valuesStride{Short(view.values().stride())}, _keysData{view.keys().data()}, _valuesData{view.values().data()}, _interpolator{view.interpolator()} { +namespace { + +auto animationInterpolatorFor(const Animation::Interpolation interpolation, const AnimationTrackType type, const AnimationTrackType resultType) -> void(*)() { + switch(type) { + /* LCOV_EXCL_START */ + #define _ct(value, type_) \ + case AnimationTrackType::value: \ + if(type == resultType) \ + return reinterpret_cast(Trade::animationInterpolatorFor(interpolation)); \ + break; + #define _c(type_) _ct(type_, type_) + _ct(Bool, bool) + _c(Float) + _c(UnsignedInt) + _c(Int) + _c(BitVector2) + _c(BitVector3) + _c(BitVector4) + _c(Vector2) + _c(Vector2ui) + _c(Vector2i) + _c(Vector3) + _c(Vector3ui) + _c(Vector3i) + _c(Vector4) + _c(Vector4ui) + _c(Vector4i) + _c(Complex) + _c(Quaternion) + _c(DualQuaternion) + #undef _c + #undef _ct + /* LCOV_EXCL_STOP */ + + /* LCOV_EXCL_START */ + #define _cr(type_, resultType_) \ + case AnimationTrackType::type_: \ + if(resultType == AnimationTrackType::resultType_) \ + return reinterpret_cast(Trade::animationInterpolatorFor(interpolation)); \ + break; + _cr(CubicHermite1D, Float) + _cr(CubicHermite2D, Vector2) + _cr(CubicHermite3D, Vector3) + _cr(CubicHermiteComplex, Complex) + _cr(CubicHermiteQuaternion, Quaternion) + #undef _cr + /* LCOV_EXCL_STOP */ + } + + /** @todo this doesn't print the types when e.g. a spline interpolation is + requested for bool, how to fix? */ + CORRADE_ASSERT_UNREACHABLE("Trade::AnimationTrackData: can't deduce interpolator function for" << type << Debug::nospace << "," << resultType << "and" << interpolation, {}); +} + +} + +AnimationTrackData::AnimationTrackData(const AnimationTrackTarget targetName, const UnsignedLong target, const AnimationTrackType type, const AnimationTrackType resultType, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, const Animation::Interpolation interpolation, void(*const interpolator)(), const Animation::Extrapolation before, const Animation::Extrapolation after) noexcept: _type{type}, _resultType{resultType}, _targetName{targetName}, _interpolation{interpolation}, _before{before}, _after{after}, _target{target}, _size{UnsignedInt(keys.size())}, _keysStride{Short(keys.stride())}, _valuesStride{Short(values.stride())}, _keysData{keys.data()}, _valuesData{values.data()}, _interpolator{interpolator} { + CORRADE_ASSERT(keys.size() == values.size(), + "Trade::AnimationTrackData: expected key and value view to have the same size but got" << keys.size() << "and" << values.size(), ); #ifndef CORRADE_TARGET_32BIT - CORRADE_ASSERT(view.size() <= 0xffffffffu, - "Trade::AnimationTrackData: expected keyframe count to fit into 32 bits but got" << view.size(), ); + CORRADE_ASSERT(keys.size() <= 0xffffffffu, + "Trade::AnimationTrackData: expected keyframe count to fit into 32 bits but got" << keys.size(), ); #endif - CORRADE_ASSERT(view.keys().stride() >= -32768 && view.keys().stride() <= 32767, - "Trade::AnimationTrackData: expected key stride to fit into 16 bits but got" << view.keys().stride(), ); - CORRADE_ASSERT(view.values().stride() >= -32768 && view.values().stride() <= 32767, - "Trade::AnimationTrackData: expected value stride to fit into 16 bits but got" << view.values().stride(), ); + CORRADE_ASSERT(keys.stride() >= -32768 && keys.stride() <= 32767, + "Trade::AnimationTrackData: expected key stride to fit into 16 bits but got" << keys.stride(), ); + CORRADE_ASSERT(values.stride() >= -32768 && values.stride() <= 32767, + "Trade::AnimationTrackData: expected value stride to fit into 16 bits but got" << values.stride(), ); } + +AnimationTrackData::AnimationTrackData(const AnimationTrackTarget targetName, const UnsignedLong target, const AnimationTrackType type, const AnimationTrackType resultType, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, const Animation::Interpolation interpolation, const Animation::Extrapolation before, const Animation::Extrapolation after) noexcept: AnimationTrackData{targetName, target, type, resultType, keys, values, interpolation, animationInterpolatorFor(interpolation, type, resultType), before, after} {} + Animation::TrackViewStorage AnimationTrackData::track() const { return Animation::TrackViewStorage{ /* We're sure the views are correct, circumventing the asserts */ diff --git a/src/Magnum/Trade/AnimationData.h b/src/Magnum/Trade/AnimationData.h index 6590ed075..b53badcfa 100644 --- a/src/Magnum/Trade/AnimationData.h +++ b/src/Magnum/Trade/AnimationData.h @@ -349,6 +349,150 @@ class MAGNUM_TRADE_EXPORT AnimationTrackData { */ explicit AnimationTrackData() noexcept: _type{}, _resultType{}, _targetName{}, _interpolation{}, _before{}, _after{}, _target{}, _size{}, _keysStride{}, _valuesStride{}, _keysData{}, _valuesData{}, _interpolator{} {} + /** + * @brief Type-erased constructor with generic interpolation behavior + * @param targetName Track target name + * @param target Track target ID + * @param type Value type + * @param resultType Result type + * @param keys Frame keys + * @param values Frame values + * @param interpolation Interpolation behavior + * @param before Extrapolation behavior before + * @param after Extrapolation behavior after + * @m_since_latest + * + * The keyframe data are assumed to be stored in sorted order. It's not + * an error to have two successive keyframes with the same frame value. + * Expects that @p keys and @p values strides both fit into signed + * 16-bit values, that they both have the same size and that keyframe + * count fits into 32 bits. + * + * The interpolator function is picked implicitly for given + * @p interpolation, @p type and @p resultType and the combination is + * expected to make sense. Use + * @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, void(*)(), Animation::Extrapolation, Animation::Extrapolation) + * to supply it explicitly. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, AnimationTrackType resultType, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, Animation::Extrapolation before, Animation::Extrapolation after) noexcept; + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, Animation::Extrapolation, Animation::Extrapolation) + * with both @p type and @p resultType set to @p type. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, Animation::Extrapolation before, Animation::Extrapolation after) noexcept: AnimationTrackData{targetName, target, type, type, keys, values, interpolation, before, after} {} + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, Animation::Extrapolation, Animation::Extrapolation) + * with both @p before and @p after set to @p extrapolation. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, AnimationTrackType resultType, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, type, resultType, keys, values, interpolation, extrapolation, extrapolation} {} + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, Animation::Extrapolation, Animation::Extrapolation) + * with both @p type and @p resultType set to @p type, and both + * @p before and @p after set to @p extrapolation. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, type, keys, values, interpolation, extrapolation, extrapolation} {} + + /** + * @brief Type-erased constructor with both generic and custom interpolator + * @param targetName Track target name + * @param target Track target ID + * @param type Value type + * @param resultType Result type + * @param keys Frame keys + * @param values Frame values + * @param interpolation Interpolation behavior + * @param interpolator Interpolator function + * @param before Extrapolation behavior before + * @param after Extrapolation behavior after + * @m_since_latest + * + * Compared to @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, Animation::Extrapolation, Animation::Extrapolation) + * which picks an interpolator function based on the value of + * @p interpolation, @p type and @p resultType, here it's taken + * explicitly. Even though it accepts the function cast to a + * @cpp void(*)() @ce, it's expected to be of a right type for @p type + * and @p resultType. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, AnimationTrackType resultType, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, void(*interpolator)(), Animation::Extrapolation before, Animation::Extrapolation after) noexcept; + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, void(*)(), Animation::Extrapolation, Animation::Extrapolation) + * with both @p type and @p resultType set to @p type. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, void(*interpolator)(), Animation::Extrapolation before, Animation::Extrapolation after) noexcept: AnimationTrackData{targetName, target, type, type, keys, values, interpolation, interpolator, before, after} {} + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, void(*)(), Animation::Extrapolation, Animation::Extrapolation) + * with both @p before and @p after set to @p extrapolation. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, AnimationTrackType resultType, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, void(*interpolator)(), Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, type, resultType, keys, values, interpolation, interpolator, extrapolation, extrapolation} {} + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, void(*)(), Animation::Extrapolation, Animation::Extrapolation) + * with both @p type and @p resultType set to @p type, and both + * @p before and @p after set to @p extrapolation. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, void(*interpolator)(), Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, type, keys, values, interpolation, interpolator, extrapolation, extrapolation} {} + + /** + * @brief Type-erased constructor with custom interpolator + * @param targetName Track target name + * @param target Track target ID + * @param type Value type + * @param resultType Result type + * @param keys Frame keys + * @param values Frame values + * @param interpolator Interpolator function + * @param before Extrapolation behavior before + * @param after Extrapolation behavior after + * @m_since_latest + * + * Calls @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, void(*)(), Animation::Extrapolation, Animation::Extrapolation) + * with @p interpolation set to @ref Animation::Interpolation::Custom. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, AnimationTrackType resultType, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, void(*interpolator)(), Animation::Extrapolation before, Animation::Extrapolation after) noexcept: AnimationTrackData{targetName, target, type, resultType, keys, values, Animation::Interpolation::Custom, interpolator, before, after} {} + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, void(*)(), Extrapolation, Extrapolation) + * with both @p type and @p resultType set to @p type. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, void(*interpolator)(), Animation::Extrapolation before, Animation::Extrapolation after) noexcept: AnimationTrackData{targetName, target, type, type, keys, values, interpolator, before, after} {} + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, void(*)(), Extrapolation, Extrapolation) + * with both @p before and @p after set to @p extrapolation. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, AnimationTrackType resultType, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, void(*interpolator)(), Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, type, resultType, keys, values, interpolator, extrapolation, extrapolation} {} + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, void(*)(), Extrapolation, Extrapolation) + * with both @p type and @p resultType set to @p type, and both + * @p before and @p after set to @p extrapolation. + */ + explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, AnimationTrackType type, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, void(*interpolator)(), Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, type, keys, values, interpolator, extrapolation, extrapolation} {} + + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Type-erased constructor * @param type Value type @@ -359,30 +503,112 @@ class MAGNUM_TRADE_EXPORT AnimationTrackData { * * Expects that @p view key and value strides both fit into signed * 16-bit values and that keyframe count fits into 32 bits. + * + * @m_deprecated_since_latest Use either the typed + * @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, const Animation::TrackView&) + * constructor or the type-erased + * @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, Animation::Extrapolation, Animation::Extrapolation) + * etc. constructors instead. */ - /** @todo stop taking TrackViewStorage and instead directly take the - key/value views, interpolator/interpolation and extrapolation -- - it's just 6 overloads and makes usage much better */ - explicit AnimationTrackData(AnimationTrackType type, AnimationTrackType resultType, AnimationTrackTarget targetName, UnsignedLong target, const Animation::TrackViewStorage& view) noexcept; + explicit CORRADE_DEPRECATED("use either the typed TrackView constructor or the type-erased constructors taking key/value views directly") AnimationTrackData(AnimationTrackType type, AnimationTrackType resultType, AnimationTrackTarget targetName, UnsignedLong target, const Animation::TrackViewStorage& view) noexcept: AnimationTrackData{targetName, target, type, resultType, view.keys(), view.values(), view.interpolation(), view.interpolator(), view.before(), view.after()} {} /** @overload * * Equivalent to the above with @p type used as both value type and * result type. + * + * @m_deprecated_since_latest Use either the typed + * @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, const Animation::TrackView&) + * constructor or the type-erased + * @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, Animation::Extrapolation, Animation::Extrapolation) + * etc. constructors instead. */ - explicit AnimationTrackData(AnimationTrackType type, AnimationTrackTarget targetName, UnsignedLong target, const Animation::TrackViewStorage& view) noexcept: AnimationTrackData{type, type, targetName, target, view} {} + explicit CORRADE_DEPRECATED("use either the typed TrackView constructor or the type-erased constructors taking key/value views directly") AnimationTrackData(AnimationTrackType type, AnimationTrackTarget targetName, UnsignedLong target, const Animation::TrackViewStorage& view) noexcept: AnimationTrackData{targetName, target, type, view.keys(), view.values(), view.interpolation(), view.interpolator(), view.before(), view.after()} {} + #endif /** - * @brief Constructor + * @brief Construct with generic interpolation behavior * @param targetName Track target name * @param target Track target ID - * @param view @ref Animation::TrackView instance + * @param keys Frame keys + * @param values Frame values + * @param interpolation Interpolation behavior + * @param before Extrapolation behavior before + * @param after Extrapolation behavior after + * @m_since_latest + * + * Detects @ref AnimationTrackType from @p values and delegates to + * @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, Animation::Extrapolation, Animation::Extrapolation). + */ + template> AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, Animation::Extrapolation before, Animation::Extrapolation after) noexcept; + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, Animation::Extrapolation, Animation::Extrapolation) + * with both @p before and @p after set to @p extrapolation. + */ + template> AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, keys, values, interpolation, extrapolation, extrapolation} {} + + /** + * @brief Construct with both generic and custom interpolator + * @param targetName Track target name + * @param target Track target ID + * @param keys Frame keys + * @param values Frame values + * @param interpolation Interpolation behavior + * @param interpolator Interpolator function + * @param before Extrapolation behavior before + * @param after Extrapolation behavior after + * @m_since_latest + * + * Detects @ref AnimationTrackType from @p values and delegates to + * @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, void(*)(), Animation::Extrapolation, Animation::Extrapolation). + */ + template> AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, R(*interpolator)(const typename std::remove_const::type&, const typename std::remove_const::type&, Float), Animation::Extrapolation before, Animation::Extrapolation after) noexcept; + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, R(*)(const V&, const V&, Float), Animation::Extrapolation, Animation::Extrapolation) + * with both @p before and @p after set to @p extrapolation. + */ + template> AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Animation::Interpolation interpolation, R(*interpolator)(const typename std::remove_const::type&, const typename std::remove_const::type&, Float), Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, keys, values, interpolation, interpolator, extrapolation, extrapolation} {} + + /** + * @brief Construct with custom interpolator + * @param targetName Track target name + * @param target Track target ID + * @param keys Frame keys + * @param values Frame values + * @param interpolator Interpolator function + * @param before Extrapolation behavior before + * @param after Extrapolation behavior after + * @m_since_latest + * + * Calls @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolation, R(*)(const V&, const V&, Float), Extrapolation, Extrapolation) + * with @p interpolation set to @ref Animation::Interpolation::Custom. + */ + template> AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, R(*interpolator)(const typename std::remove_const::type&, const typename std::remove_const::type&, Float), Animation::Extrapolation before, Animation::Extrapolation after) noexcept: AnimationTrackData{targetName, target, keys, values, Animation::Interpolation::Custom, interpolator, before, after} {} + + /** @overload + * @m_since_latest + * + * Equivalent to calling @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, R(*)(const V&, const V&, Float), Extrapolation, Extrapolation) + * with both @p before and @p after set to @p extrapolation. + */ + template> AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, R(*interpolator)(const typename std::remove_const::type&, const typename std::remove_const::type&, Float), Animation::Extrapolation extrapolation = Animation::Extrapolation::Constant) noexcept: AnimationTrackData{targetName, target, keys, values, interpolator, extrapolation, extrapolation} {} + + /** + * @brief Construct from a track view + * @param targetName Track target name + * @param target Track target ID + * @param view Track view * @m_since{2020,06} * - * Detects @ref AnimationTrackType from @p view type and delegates to - * @ref AnimationTrackData(AnimationTrackType, AnimationTrackType, AnimationTrackTarget, UnsignedLong, Animation::TrackViewStorage). + * Delegates to @ref AnimationTrackData(AnimationTrackTarget, UnsignedLong, AnimationTrackType, AnimationTrackType, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Animation::Interpolation, R(*)(const V&, const V&, Float), Animation::Extrapolation, Animation::Extrapolation). */ - template explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Animation::TrackView& view) noexcept; + template> explicit AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Animation::TrackView& view) noexcept: AnimationTrackData{targetName, target, view.keys(), view.values(), view.interpolation(), view.interpolator(), view.before(), view.after()} {} /** * @brief Value type @@ -820,7 +1046,9 @@ namespace Implementation { /* LCOV_EXCL_STOP */ } -template inline AnimationTrackData::AnimationTrackData(AnimationTrackTarget targetName, UnsignedLong target, const Animation::TrackView& view) noexcept: AnimationTrackData{Implementation::animationTypeFor(), Implementation::animationTypeFor(), targetName, target, view} {} +template inline AnimationTrackData::AnimationTrackData(const AnimationTrackTarget targetName, const UnsignedLong target, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, const Animation::Interpolation interpolation, const Animation::Extrapolation before, const Animation::Extrapolation after) noexcept: AnimationTrackData{targetName, target, Implementation::animationTypeFor::type>(), Implementation::animationTypeFor(), keys, values, interpolation, before, after} {} + +template inline AnimationTrackData::AnimationTrackData(const AnimationTrackTarget targetName, const UnsignedLong target, const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, const Animation::Interpolation interpolation, R(*interpolator)(const typename std::remove_const::type&, const typename std::remove_const::type&, Float), const Animation::Extrapolation before, const Animation::Extrapolation after) noexcept: AnimationTrackData{targetName, target, Implementation::animationTypeFor::type>(), Implementation::animationTypeFor(), keys, values, interpolation, reinterpret_cast(interpolator), before, after} {} template Animation::TrackView AnimationData::track(UnsignedInt id) const { const Animation::TrackViewStorage storage = track(id); diff --git a/src/Magnum/Trade/Test/AbstractImporterTest.cpp b/src/Magnum/Trade/Test/AbstractImporterTest.cpp index 9d13dfe4f..ba28793c8 100644 --- a/src/Magnum/Trade/Test/AbstractImporterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImporterTest.cpp @@ -3852,9 +3852,8 @@ void AbstractImporterTest::animation() { /* Verify that initializer list is converted to an array with the default deleter and not something disallowed */ if(id == 7) return AnimationData{nullptr, { - AnimationTrackData{AnimationTrackType::Vector3, - AnimationTrackTarget::Scaling3D, 0, {}} - }, &state}; + AnimationTrackData{AnimationTrackTarget::Scaling3D, 0, AnimationTrackType::Vector3, nullptr, nullptr, Animation::Interpolation::Constant} + }, &state}; return AnimationData{{}, {}}; } } importer; diff --git a/src/Magnum/Trade/Test/AnimationDataTest.cpp b/src/Magnum/Trade/Test/AnimationDataTest.cpp index ecbb5638d..b876050e5 100644 --- a/src/Magnum/Trade/Test/AnimationDataTest.cpp +++ b/src/Magnum/Trade/Test/AnimationDataTest.cpp @@ -45,10 +45,23 @@ struct AnimationDataTest: TestSuite::Tester { void debugTrackTarget(); void debugTrackTargetPacked(); - void constructTrack(); - void constructTrackResultType(); - void constructTrackTemplate(); void constructTrackDefault(); + void constructTrack(); + void constructTrackTypeErased(); + void constructTrackTypeErasedImplicitResultType(); + void constructTrackExplicitInterpolator(); + void constructTrackExplicitInterpolatorTypeErased(); + void constructTrackExplicitInterpolatorTypeErasedImplicitResultType(); + void constructTrackCustomInterpolator(); + void constructTrackCustomInterpolatorTypeErased(); + void constructTrackCustomInterpolatorTypeErasedImplicitResultType(); + void constructTrackFromView(); + #ifdef MAGNUM_BUILD_DEPRECATED + void constructTrackDeprecated(); + void constructTrackDeprecatedImplicitResultType(); + #endif + void constructTrackInconsitentViewSize(); + void constructTrackUnknownInterpolator(); #ifndef CORRADE_TARGET_32BIT void constructTrackWrongSize(); #endif @@ -93,10 +106,23 @@ AnimationDataTest::AnimationDataTest() { &AnimationDataTest::debugTrackTarget, &AnimationDataTest::debugTrackTargetPacked, - &AnimationDataTest::constructTrack, - &AnimationDataTest::constructTrackResultType, - &AnimationDataTest::constructTrackTemplate, &AnimationDataTest::constructTrackDefault, + &AnimationDataTest::constructTrack, + &AnimationDataTest::constructTrackTypeErased, + &AnimationDataTest::constructTrackTypeErasedImplicitResultType, + &AnimationDataTest::constructTrackExplicitInterpolator, + &AnimationDataTest::constructTrackExplicitInterpolatorTypeErased, + &AnimationDataTest::constructTrackExplicitInterpolatorTypeErasedImplicitResultType, + &AnimationDataTest::constructTrackCustomInterpolator, + &AnimationDataTest::constructTrackCustomInterpolatorTypeErased, + &AnimationDataTest::constructTrackCustomInterpolatorTypeErasedImplicitResultType, + &AnimationDataTest::constructTrackFromView, + #ifdef MAGNUM_BUILD_DEPRECATED + &AnimationDataTest::constructTrackDeprecated, + &AnimationDataTest::constructTrackDeprecatedImplicitResultType, + #endif + &AnimationDataTest::constructTrackInconsitentViewSize, + &AnimationDataTest::constructTrackUnknownInterpolator, #ifndef CORRADE_TARGET_32BIT &AnimationDataTest::constructTrackWrongSize, #endif @@ -196,22 +222,275 @@ void AnimationDataTest::debugTrackTargetPacked() { CORRADE_COMPARE(out.str(), "Rotation3D Custom(120) 0x4242 Trade::AnimationTrackType::Float\n"); } +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); +} + void AnimationDataTest::constructTrack() { + struct Keyframe { + Float time; + CubicHermite2D value; + } keyframes[3]{}; + + AnimationTrackData data{ + AnimationTrackTarget::Scaling2D, 42, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + Animation::Interpolation::Linear, + Animation::Extrapolation::Constant}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Scaling2D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite2D); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector2); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Linear); + CORRADE_COMPARE(data.track().interpolator(), reinterpret_cast(animationInterpolatorFor(Animation::Interpolation::Linear))); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::Constant); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::Constant); +} + +void AnimationDataTest::constructTrackTypeErased() { + struct Keyframe { + Float time; + CubicHermite3D value; + } keyframes[3]{}; + AnimationTrackData data{ + AnimationTrackTarget::Translation3D, 42, + AnimationTrackType::CubicHermite3D, AnimationTrackType::Vector3, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + Animation::Interpolation::Spline, + Animation::Extrapolation::DefaultConstructed}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Translation3D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite3D); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector3); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Spline); + CORRADE_COMPARE(data.track().interpolator(), reinterpret_cast(animationInterpolatorFor(Animation::Interpolation::Spline))); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::DefaultConstructed); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::DefaultConstructed); +} + +void AnimationDataTest::constructTrackTypeErasedImplicitResultType() { + struct Keyframe { + Float time; + Quaternion value; + } keyframes[3]{}; + + AnimationTrackData data{ + AnimationTrackTarget::Rotation3D, 42, + AnimationTrackType::Quaternion, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + Animation::Interpolation::Linear, + Animation::Extrapolation::DefaultConstructed}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Rotation3D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::Quaternion); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Quaternion); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Linear); + CORRADE_COMPARE(data.track().interpolator(), reinterpret_cast(animationInterpolatorFor(Animation::Interpolation::Linear))); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::DefaultConstructed); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::DefaultConstructed); +} + +void AnimationDataTest::constructTrackExplicitInterpolator() { + struct Keyframe { + Float time; + CubicHermite2D value; + } keyframes[3]{}; + + AnimationTrackData data{ + AnimationTrackTarget::Scaling2D, 42, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + Animation::Interpolation::Spline, + Math::splerp, + Animation::Extrapolation::Constant}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Scaling2D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite2D); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector2); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Spline); + CORRADE_COMPARE(data.track().interpolator(), reinterpret_cast(static_cast(Math::splerp))); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::Constant); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::Constant); +} + +void AnimationDataTest::constructTrackExplicitInterpolatorTypeErased() { + struct Keyframe { + Float time; + CubicHermite2D value; + } keyframes[3]{}; + + auto interpolator = reinterpret_cast(static_cast(Math::splerp)); + + AnimationTrackData data{ + AnimationTrackTarget::Scaling2D, 42, + AnimationTrackType::CubicHermite2D, + AnimationTrackType::Vector2, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + Animation::Interpolation::Spline, + interpolator, + Animation::Extrapolation::Constant}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Scaling2D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite2D); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector2); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Spline); + CORRADE_COMPARE(data.track().interpolator(), interpolator); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::Constant); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::Constant); +} + +void AnimationDataTest::constructTrackExplicitInterpolatorTypeErasedImplicitResultType() { + struct Keyframe { + Float time; + Vector3 value; + } keyframes[3]{}; + + auto interpolator = reinterpret_cast(static_cast(Math::lerp)); + + AnimationTrackData data{ AnimationTrackTarget::Translation3D, 42, - Animation::TrackView{ + AnimationTrackType::Vector3, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + Animation::Interpolation::Linear, + interpolator, + Animation::Extrapolation::DefaultConstructed}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Translation3D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::Vector3); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector3); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Linear); + CORRADE_COMPARE(data.track().interpolator(), interpolator); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::DefaultConstructed); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::DefaultConstructed); +} + +void AnimationDataTest::constructTrackCustomInterpolator() { + struct Keyframe { + Float time; + CubicHermite2D value; + } keyframes[3]{}; + + AnimationTrackData data{ + AnimationTrackTarget::Scaling2D, 42, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + Math::splerp, + Animation::Extrapolation::Constant}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Scaling2D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite2D); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector2); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Custom); + CORRADE_COMPARE(data.track().interpolator(), reinterpret_cast(static_cast(Math::splerp))); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::Constant); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::Constant); +} + +void AnimationDataTest::constructTrackCustomInterpolatorTypeErased() { + struct Keyframe { + Float time; + CubicHermite2D value; + } keyframes[3]{}; + + auto interpolator = reinterpret_cast(static_cast(Math::splerp)); + + AnimationTrackData data{ + AnimationTrackTarget::Scaling2D, 42, + AnimationTrackType::CubicHermite2D, + AnimationTrackType::Vector2, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + interpolator, + Animation::Extrapolation::Constant}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Scaling2D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite2D); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector2); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Custom); + CORRADE_COMPARE(data.track().interpolator(), interpolator); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::Constant); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::Constant); +} + +void AnimationDataTest::constructTrackCustomInterpolatorTypeErasedImplicitResultType() { + struct Keyframe { + Float time; + Vector3 value; + } keyframes[3]{}; + + auto interpolator = reinterpret_cast(static_cast(Math::lerp)); + + AnimationTrackData data{ + AnimationTrackTarget::Translation3D, 42, + AnimationTrackType::Vector3, + Containers::stridedArrayView(keyframes).slice(&Keyframe::time), + Containers::stridedArrayView(keyframes).slice(&Keyframe::value), + interpolator, + Animation::Extrapolation::DefaultConstructed}; + CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Translation3D); + CORRADE_COMPARE(data.target(), 42); + CORRADE_COMPARE(data.type(), AnimationTrackType::Vector3); + CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector3); + CORRADE_COMPARE(data.track().keys().data(), &keyframes[0].time); + CORRADE_COMPARE(data.track().values().data(), &keyframes[0].value); + CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Custom); + CORRADE_COMPARE(data.track().interpolator(), interpolator); + CORRADE_COMPARE(data.track().before(), Animation::Extrapolation::DefaultConstructed); + CORRADE_COMPARE(data.track().after(), Animation::Extrapolation::DefaultConstructed); +} + +void AnimationDataTest::constructTrackFromView() { + AnimationTrackData data{ + AnimationTrackTarget::Translation3D, 42, + Animation::TrackView{ nullptr, Animation::Interpolation::Linear, - animationInterpolatorFor(Animation::Interpolation::Linear)}}; - CORRADE_COMPARE(data.type(), AnimationTrackType::Vector3); + animationInterpolatorFor(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::constructTrackResultType() { +#ifdef MAGNUM_BUILD_DEPRECATED +void AnimationDataTest::constructTrackDeprecated() { + CORRADE_IGNORE_DEPRECATED_PUSH AnimationTrackData data{ AnimationTrackType::CubicHermite3D, AnimationTrackType::Vector3, @@ -220,6 +499,7 @@ void AnimationDataTest::constructTrackResultType() { nullptr, Animation::Interpolation::Linear, animationInterpolatorFor(Animation::Interpolation::Linear)}}; + CORRADE_IGNORE_DEPRECATED_POP CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite3D); CORRADE_COMPARE(data.resultType(), AnimationTrackType::Vector3); CORRADE_COMPARE(data.targetName(), AnimationTrackTarget::Translation3D); @@ -227,34 +507,62 @@ void AnimationDataTest::constructTrackResultType() { CORRADE_COMPARE(data.track().interpolation(), Animation::Interpolation::Linear); } -void AnimationDataTest::constructTrackTemplate() { +void AnimationDataTest::constructTrackDeprecatedImplicitResultType() { + CORRADE_IGNORE_DEPRECATED_PUSH AnimationTrackData data{ + AnimationTrackType::Vector3, AnimationTrackTarget::Translation3D, 42, - Animation::TrackView{ + Animation::TrackView{ nullptr, Animation::Interpolation::Linear, - animationInterpolatorFor(Animation::Interpolation::Linear)}}; - CORRADE_COMPARE(data.type(), AnimationTrackType::CubicHermite3D); + animationInterpolatorFor(Animation::Interpolation::Linear)}}; + CORRADE_IGNORE_DEPRECATED_POP + 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); } +#endif -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); +void AnimationDataTest::constructTrackInconsitentViewSize() { + CORRADE_SKIP_IF_NO_ASSERT(); - 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); + Float time[2]; + Vector2 value[3]; + std::ostringstream out; + Error redirectError{&out}; + AnimationTrackData{ + AnimationTrackTarget::Rotation3D, 42, + Containers::stridedArrayView(time), + Containers::stridedArrayView(value), + Animation::Interpolation::Linear}; + CORRADE_COMPARE(out.str(), "Trade::AnimationTrackData: expected key and value view to have the same size but got 2 and 3\n"); +} + +void AnimationDataTest::constructTrackUnknownInterpolator() { + CORRADE_SKIP_IF_NO_ASSERT(); + + std::ostringstream out; + Error redirectError{&out}; + AnimationTrackData{ + AnimationTrackTarget::Rotation3D, 42, + AnimationTrackType::CubicHermite1D, + AnimationTrackType::Vector2, + nullptr, + nullptr, + Animation::Interpolation::Linear}; + AnimationTrackData{ + AnimationTrackTarget::Rotation3D, 42, + AnimationTrackType::Vector3, + nullptr, + nullptr, + Animation::Interpolation::Spline}; + CORRADE_COMPARE(out.str(), + "Trade::AnimationTrackData: can't deduce interpolator function for Trade::AnimationTrackType::CubicHermite1D, Trade::AnimationTrackType::Vector2 and Animation::Interpolation::Linear\n" + /* This assertion is from the delegated-to interpolationFor(), which + unfortunately doesn't print the types */ + "Animation::interpolatorFor(): can't deduce interpolator function for Animation::Interpolation::Spline\n"); } #ifndef CORRADE_TARGET_32BIT @@ -739,9 +1047,8 @@ void AnimationDataTest::trackWrongIndex() { Error redirectError{&out}; AnimationData data{nullptr, { - AnimationTrackData{AnimationTrackType::Vector3, - AnimationTrackTarget::Scaling3D, 0, {}} - }}; + AnimationTrackData{AnimationTrackTarget::Scaling3D, 0, AnimationTrackType::Vector3, nullptr, nullptr, Animation::Interpolation::Constant} + }}; data.trackType(1); data.trackResultType(1); data.trackTargetName(1); @@ -765,10 +1072,8 @@ void AnimationDataTest::trackWrongType() { Error redirectError{&out}; AnimationData data{nullptr, { - AnimationTrackData{AnimationTrackType::Vector3i, - AnimationTrackType::Vector3, - AnimationTrackTarget::Scaling3D, 0, {}} - }}; + AnimationTrackData{AnimationTrackTarget::Scaling3D, 0, AnimationTrackType::Vector3i, AnimationTrackType::Vector3, nullptr, nullptr, Animation::Interpolation::Constant, nullptr} + }}; data.track(0); @@ -782,10 +1087,8 @@ void AnimationDataTest::trackWrongResultType() { Error redirectError{&out}; AnimationData data{nullptr, { - AnimationTrackData{AnimationTrackType::Vector3i, - AnimationTrackType::Vector3, - AnimationTrackTarget::Scaling3D, 0, {}} - }}; + AnimationTrackData{AnimationTrackTarget::Scaling3D, 0, AnimationTrackType::Vector3i, AnimationTrackType::Vector3, nullptr, nullptr, Animation::Interpolation::Constant, nullptr} + }}; data.track(0);