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);