From 954798a9ba32ae1110b50835a219c5887d6fd897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 6 Nov 2019 19:34:46 +0100 Subject: [PATCH] Animation: allow mutable access to data referenced by TrackView. This is a breaking change, sorry. --- doc/changelog.dox | 7 + doc/snippets/MagnumAnimation.cpp | 8 +- src/Magnum/Animation/Interpolation.h | 7 +- src/Magnum/Animation/Player.h | 113 +++++--- src/Magnum/Animation/Player.hpp | 10 +- src/Magnum/Animation/Test/Benchmark.cpp | 14 +- src/Magnum/Animation/Test/PlayerTest.cpp | 94 +++++-- src/Magnum/Animation/Test/TrackTest.cpp | 55 ++-- src/Magnum/Animation/Test/TrackViewTest.cpp | 280 ++++++++++++++++++-- src/Magnum/Animation/Track.h | 112 +++++--- 10 files changed, 542 insertions(+), 158 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index ebf061501..9d8fd656c 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -105,6 +105,13 @@ See also: deprecated in favor of the new @ref Platform::Sdl2Application::setCursor() together with @ref Platform::Sdl2Application::Cursor::HiddenLocked +@subsection changelog-latest-compatibility Potential compatibility breakages, removed APIs + +- @ref Animation::TrackView "TrackView" in the still-experimental + @ref Animation library was changed to allow mutable access to the keys & + values it references. Existing code needs to be changed to say + @cpp TrackView @ce instead of @cpp TrackView @ce. + @section changelog-2019-10 2019.10 Released 2019-10-24, tagged as diff --git a/doc/snippets/MagnumAnimation.cpp b/doc/snippets/MagnumAnimation.cpp index f4204660c..332ad3014 100644 --- a/doc/snippets/MagnumAnimation.cpp +++ b/doc/snippets/MagnumAnimation.cpp @@ -276,9 +276,9 @@ auto callback = [](std::vector& data, Int value) { Animation::Player player; player.addRawCallback(track, - [](const Animation::TrackViewStorage& track, Float key, + [](const Animation::TrackViewStorage& track, Float key, std::size_t& hint, void* destination, void(*callback)(), void* userData) { - Int value = static_cast&>(track) + Int value = static_cast&>(track) .atStrict(key, hint); if(value == *static_cast(destination)) return; *static_cast(destination) = value; @@ -341,11 +341,11 @@ const Keyframe data[]{ {6.0f, Vector2::yAxis(0.0f), 180.0_degf} }; -Animation::TrackView positions{ +Animation::TrackView positions{ {data, &data[0].time, Containers::arraySize(data), sizeof(Keyframe)}, {data, &data[0].position, Containers::arraySize(data), sizeof(Keyframe)}, Math::lerp}; -Animation::TrackView rotations{ +Animation::TrackView rotations{ {data, &data[0].time, Containers::arraySize(data), sizeof(Keyframe)}, {data, &data[0].rotation, Containers::arraySize(data), sizeof(Keyframe)}, Math::lerp}; diff --git a/src/Magnum/Animation/Interpolation.h b/src/Magnum/Animation/Interpolation.h index ecc4025d2..e73b19b94 100644 --- a/src/Magnum/Animation/Interpolation.h +++ b/src/Magnum/Animation/Interpolation.h @@ -293,11 +293,14 @@ namespace Implementation { /* Generic types where result type is the same as value type */ template struct ResultTraits { - typedef V Type; + typedef typename std::remove_const::type Type; }; template struct ResultTraits> { typedef T Type; }; +template struct ResultTraits> { + typedef T Type; +}; template struct TypeTraits { typedef V(*Interpolator)(const V&, const V&, Float); @@ -365,7 +368,7 @@ template struct MAGNUM_EXPORT TypeTraits, T> { /* Needs to be defined later so it can pick up the TypeTraits definitions */ template auto interpolatorFor(Interpolation interpolation) -> R(*)(const V&, const V&, Float) { - return Implementation::TypeTraits::interpolator(interpolation); + return Implementation::TypeTraits::type, R>::interpolator(interpolation); } template R interpolate(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, const Extrapolation before, const Extrapolation after, R(*const interpolator)(const V&, const V&, Float), K frame, std::size_t& hint) { diff --git a/src/Magnum/Animation/Player.h b/src/Magnum/Animation/Player.h index 0835e7204..4135c6819 100644 --- a/src/Magnum/Animation/Player.h +++ b/src/Magnum/Animation/Player.h @@ -370,7 +370,7 @@ template& track(std::size_t i) const; + const TrackViewStorage& track(std::size_t i) const; /** * @brief Add a track with a result destination @@ -378,7 +378,12 @@ template Player& add(const TrackView& track, R& destination); + template Player& add(const TrackView& track, R& destination); + + /** @overload */ + template Player& add(const TrackView& track, R& destination) { + return add(reinterpret_cast&>(track), destination); + } /** @overload * @@ -388,7 +393,7 @@ template Player& add(const Track& track, R& destination) { - return add(TrackView{track}, destination); + return add(TrackView{track}, destination); } #else /* MSVC 2015 and 2017 is clueless when it comes to trying to deduce the @@ -405,7 +410,7 @@ template Player& add(const Track& track, R& destination) { - return add(static_cast&>(track), destination); + return add(static_cast&>(track), destination); } #endif @@ -423,6 +428,9 @@ template Player& addWithCallback(const TrackView& track, void(*callback)(K, const R&, void*), void* userData = nullptr); + + /** @overload */ template Player& addWithCallback(const TrackView& track, void(*callback)(K, const R&, void*), void* userData = nullptr); #else /* Otherwise the user would be forced to use the + operator to convert @@ -430,7 +438,10 @@ template Player& addWithCallback(const TrackView& track, Callback callback, void* userData = nullptr); + template Player& addWithCallback(const TrackView& track, Callback callback, void* userData = nullptr); + template Player& addWithCallback(const TrackView& track, Callback callback, void* userData = nullptr) { + return addWithCallback(reinterpret_cast&>(track), callback, userData); + } #endif /** @overload @@ -443,11 +454,11 @@ template Player& addWithCallback(const Track& track, void(*callback)(K, const R&, void*), void* userData = nullptr); #elif !defined(CORRADE_MSVC2019_COMPATIBILITY) /* See above why */ template Player& addWithCallback(const Track& track, Callback callback, void* userData = nullptr) { - return addWithCallback(TrackView{track}, callback, userData); + return addWithCallback(TrackView{track}, callback, userData); } #else /* see the add() function for explanation */ template Player& addWithCallback(const Track& track, Callback callback, void* userData = nullptr) { - return addWithCallback(static_cast&>(track), callback, userData); + return addWithCallback(static_cast&>(track), callback, userData); } #endif @@ -461,9 +472,15 @@ template Player& addWithCallback(const TrackView& track, void(*callback)(K, const R&, U&), U& userData); + + /** @overload */ template Player& addWithCallback(const TrackView& track, void(*callback)(K, const R&, U&), U& userData); #else /* See above why */ - template Player& addWithCallback(const TrackView& track, Callback callback, U& userData); + template Player& addWithCallback(const TrackView& track, Callback callback, U& userData); + template Player& addWithCallback(const TrackView& track, Callback callback, U& userData) { + return addWithCallback(reinterpret_cast&>(track), callback, userData); + } #endif /** @overload @@ -476,11 +493,11 @@ template Player& addWithCallback(const Track& track, void(*callback)(K, const R&, U&), U& userData); #elif !defined(CORRADE_MSVC2019_COMPATIBILITY) /* See above why */ template Player& addWithCallback(const Track& track, Callback callback, U& userData) { - return addWithCallback(TrackView{track}, callback, userData); + return addWithCallback(TrackView{track}, callback, userData); } #else /* see the add() function for explanation */ template Player& addWithCallback(const Track& track, Callback callback, U& userData) { - return addWithCallback(static_cast&>(track), callback, userData); + return addWithCallback(static_cast&>(track), callback, userData); } #endif @@ -500,9 +517,15 @@ template Player& addWithCallbackOnChange(const TrackView& track, void(*callback)(K, const R&, void*), R& destination, void* userData = nullptr); + + /** @overload */ template Player& addWithCallbackOnChange(const TrackView& track, void(*callback)(K, const R&, void*), R& destination, void* userData = nullptr); #else /* See above why */ - template Player& addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, void* userData = nullptr); + template Player& addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, void* userData = nullptr); + template Player& addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, void* userData = nullptr) { + return addWithCallbackOnChange(reinterpret_cast&>(track), callback, destination, userData); + } #endif /** @overload @@ -515,11 +538,11 @@ template Player& addWithCallbackOnChange(const Track& track, void(*callback)(K, const R&, void*), R& destination, void* userData = nullptr); #elif !defined(CORRADE_MSVC2019_COMPATIBILITY) /* See above why */ template Player& addWithCallbackOnChange(const Track& track, Callback callback, R& destination, void* userData = nullptr) { - return addWithCallbackOnChange(TrackView{track}, callback, destination, userData); + return addWithCallbackOnChange(TrackView{track}, callback, destination, userData); } #else /* see the add() function for explanation */ template Player& addWithCallbackOnChange(const Track& track, Callback callback, R& destination, void* userData = nullptr) { - return addWithCallbackOnChange(static_cast&>(track), callback, destination, userData); + return addWithCallbackOnChange(static_cast&>(track), callback, destination, userData); } #endif @@ -533,9 +556,15 @@ template Player& addWithCallbackOnChange(const TrackView& track, void(*callback)(K, const R&, void*), R& destination, U& userData); + + /** @overload */ template Player& addWithCallbackOnChange(const TrackView& track, void(*callback)(K, const R&, void*), R& destination, U& userData); #else /* See above why */ - template Player& addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, U& userData); + template Player& addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, U& userData); + template Player& addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, U& userData) { + return addWithCallbackOnChange(reinterpret_cast&>(track), callback, destination, userData); + } #endif /** @overload @@ -548,11 +577,11 @@ template Player& addWithCallbackOnChange(const Track& track, void(*callback)(K, const R&, void*), R& destination, U& userData); #elif !defined(CORRADE_MSVC2019_COMPATIBILITY) /* See above why */ template Player& addWithCallbackOnChange(const Track& track, Callback callback, R& destination, U& userData) { - return addWithCallbackOnChange(TrackView{track}, callback, destination, userData); + return addWithCallbackOnChange(TrackView{track}, callback, destination, userData); } #else /* see the add() function for explanation */ template Player& addWithCallbackOnChange(const Track& track, Callback callback, R& destination, U& userData) { - return addWithCallbackOnChange(static_cast&>(track), callback, destination, userData); + return addWithCallbackOnChange(static_cast&>(track), callback, destination, userData); } #endif @@ -579,9 +608,15 @@ template Player& addRawCallback(const TrackView& track, void(*callback)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userData); + template Player& addRawCallback(const TrackView& track, void(*callback)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userData); + + /** @overload */ + template Player& addRawCallback(const TrackView& track, void(*callback)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userData); #else - template Player& addRawCallback(const TrackView& track, Callback callback, void* destination, void(*userCallback)(), void* userData); + template Player& addRawCallback(const TrackView& track, Callback callback, void* destination, void(*userCallback)(), void* userData); + template Player& addRawCallback(const TrackView& track, Callback callback, void* destination, void(*userCallback)(), void* userData) { + return addRawCallback(reinterpret_cast&>(track), callback, destination, userCallback, userData); + } #endif /** @overload @@ -591,14 +626,14 @@ template Player& addRawCallback(const Track& track, void(*callback)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userData); + template Player& addRawCallback(const Track& track, void(*callback)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userData); #elif !defined(CORRADE_MSVC2019_COMPATIBILITY) /* See above why */ template Player& addRawCallback(const Track& track, Callback callback, void* destination, void(*userCallback)(), void* userData) { - return addRawCallback(TrackView{track}, callback, destination, userCallback, userData); + return addRawCallback(TrackView{track}, callback, destination, userCallback, userData); } #else /* see the add() function for explanation */ template Player& addRawCallback(const Track& track, Callback callback, void* destination, void(*userCallback)(), void* userData) { - return addRawCallback(static_cast&>(track), callback, destination, userCallback, userData); + return addRawCallback(static_cast&>(track), callback, destination, userCallback, userData); } #endif @@ -773,7 +808,7 @@ template& addInternal(const TrackViewStorage& track, void (*advancer)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userCallbackData); + Player& addInternal(const TrackViewStorage& track, void (*advancer)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userCallbackData); Containers::Optional> elapsedInternal(T time, T& updatedStartTime, T& updatedPauseTime, State& updatedState) const; @@ -785,58 +820,58 @@ template template Player& Player::add(const TrackView& track, R& destination) { +template template Player& Player::add(const TrackView& track, R& destination) { return addInternal(track, - [](const TrackViewStorage& track, K key, std::size_t& hint, void* destination, void(*)(), void*) { - *static_cast(destination) = static_cast&>(track).at(key, hint); + [](const TrackViewStorage& track, K key, std::size_t& hint, void* destination, void(*)(), void*) { + *static_cast(destination) = static_cast&>(track).at(key, hint); }, &destination, nullptr, nullptr); } #ifndef DOXYGEN_GENERATING_OUTPUT -template template Player& Player::addWithCallback(const TrackView& track, Callback callback, void* userData) { +template template Player& Player::addWithCallback(const TrackView& track, Callback callback, void* userData) { auto callbackPtr = static_cast(callback); return addInternal(track, - [](const TrackViewStorage& track, K key, std::size_t& hint, void*, void(*callback)(), void* userData) { + [](const TrackViewStorage& track, K key, std::size_t& hint, void*, void(*callback)(), void* userData) { /** @todo try to use atStrict() if possible */ - reinterpret_cast(callback)(key, static_cast&>(track).at(key, hint), userData); + reinterpret_cast(callback)(key, static_cast&>(track).at(key, hint), userData); }, nullptr, reinterpret_cast(callbackPtr), userData); } -template template Player& Player::addWithCallback(const TrackView& track, Callback callback, U& userData) { +template template Player& Player::addWithCallback(const TrackView& track, Callback callback, U& userData) { auto callbackPtr = static_cast(callback); return addInternal(track, - [](const TrackViewStorage& track, K key, std::size_t& hint, void*, void(*callback)(), void* userData) { + [](const TrackViewStorage& track, K key, std::size_t& hint, void*, void(*callback)(), void* userData) { /** @todo try to use atStrict() if possible */ - reinterpret_cast(callback)(key, static_cast&>(track).at(key, hint), *static_cast(userData)); + reinterpret_cast(callback)(key, static_cast&>(track).at(key, hint), *static_cast(userData)); }, nullptr, reinterpret_cast(callbackPtr), &userData); } -template template Player& Player::addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, void* userData) { +template template Player& Player::addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, void* userData) { auto callbackPtr = static_cast(callback); return addInternal(track, - [](const TrackViewStorage& track, K key, std::size_t& hint, void* destination, void(*callback)(), void* userData) { + [](const TrackViewStorage& track, K key, std::size_t& hint, void* destination, void(*callback)(), void* userData) { /** @todo try to use atStrict() if possible */ - R result = static_cast&>(track).at(key, hint); + R result = static_cast&>(track).at(key, hint); if(result == *static_cast(destination)) return; reinterpret_cast(callback)(key, result, userData); *static_cast(destination) = result; }, &destination, reinterpret_cast(callbackPtr), userData); } -template template Player& Player::addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, U& userData) { +template template Player& Player::addWithCallbackOnChange(const TrackView& track, Callback callback, R& destination, U& userData) { auto callbackPtr = static_cast(callback); return addInternal(track, - [](const TrackViewStorage& track, K key, std::size_t& hint, void* destination, void(*callback)(), void* userData) { + [](const TrackViewStorage& track, K key, std::size_t& hint, void* destination, void(*callback)(), void* userData) { /** @todo try to use atStrict() if possible */ - R result = static_cast&>(track).at(key, hint); + R result = static_cast&>(track).at(key, hint); if(result == *static_cast(destination)) return; reinterpret_cast(callback)(key, result, *static_cast(userData)); *static_cast(destination) = result; }, &destination, reinterpret_cast(callbackPtr), &userData); } -template template Player& Player::addRawCallback(const TrackView& track, Callback callback, void* destination, void(*userCallback)(), void* userData) { - auto callbackPtr = static_cast&, K, std::size_t&, void*, void(*)(), void*)>(callback); +template template Player& Player::addRawCallback(const TrackView& track, Callback callback, void* destination, void(*userCallback)(), void* userData) { + auto callbackPtr = static_cast&, K, std::size_t&, void*, void(*)(), void*)>(callback); return addInternal(track, callbackPtr, destination, userCallback, userData); } #endif diff --git a/src/Magnum/Animation/Player.hpp b/src/Magnum/Animation/Player.hpp index 1773b8b4c..ff114cce5 100644 --- a/src/Magnum/Animation/Player.hpp +++ b/src/Magnum/Animation/Player.hpp @@ -60,10 +60,10 @@ namespace Implementation { template struct Player::Track { /* Not sure why is this still needed for emplace_back(). It's 2018, COME ON ¯\_(ツ)_/¯ */ - /*implicit*/ Track(const TrackViewStorage& track, void (*advancer)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userCallbackData, std::size_t hint) noexcept: track{track}, advancer{advancer}, destination{destination}, userCallback{userCallback}, userCallbackData{userCallbackData}, hint{hint} {} + /*implicit*/ Track(const TrackViewStorage& track, void (*advancer)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* destination, void(*userCallback)(), void* userCallbackData, std::size_t hint) noexcept: track{track}, advancer{advancer}, destination{destination}, userCallback{userCallback}, userCallbackData{userCallbackData}, hint{hint} {} - TrackViewStorage track; - void (*advancer)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*); + TrackViewStorage track; + void (*advancer)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*); void* destination; void(*userCallback)(); void* userCallbackData; @@ -93,14 +93,14 @@ template std::size_t Player::size() const { return _tracks.size(); } -template const TrackViewStorage& Player::track(std::size_t i) const { +template const TrackViewStorage& Player::track(std::size_t i) const { CORRADE_ASSERT(i < _tracks.size(), /* Returning track 0 so we can test this w/ MSVC debug iterators */ "Animation::Player::track(): index out of range", _tracks[0].track); return _tracks[i].track; } -template Player& Player::addInternal(const TrackViewStorage& track, void(*const advancer)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* const destination, void(*const userCallback)(), void* const userCallbackData) { +template Player& Player::addInternal(const TrackViewStorage& track, void(*const advancer)(const TrackViewStorage&, K, std::size_t&, void*, void(*)(), void*), void* const destination, void(*const userCallback)(), void* const userCallbackData) { if(_tracks.empty() && _duration == Math::Range1D{}) _duration = track.duration(); else diff --git a/src/Magnum/Animation/Test/Benchmark.cpp b/src/Magnum/Animation/Test/Benchmark.cpp index 0983e0240..89db04b65 100644 --- a/src/Magnum/Animation/Test/Benchmark.cpp +++ b/src/Magnum/Animation/Test/Benchmark.cpp @@ -55,8 +55,8 @@ struct Benchmark: TestSuite::Tester { Containers::Array> _interleaved; Containers::StridedArrayView1D _keysInterleaved; Containers::StridedArrayView1D _valuesInterleaved; - TrackView _track; - TrackView _trackInterleaved; + TrackView _track; + TrackView _trackInterleaved; }; namespace { @@ -91,7 +91,7 @@ Benchmark::Benchmark() { _keysInterleaved = {_interleaved, &_interleaved[0].first, _interleaved.size(), sizeof(std::pair)}; _valuesInterleaved = {_interleaved, &_interleaved[0].second, _interleaved.size(), sizeof(std::pair)}; - _track = TrackView{ + _track = TrackView{ Containers::arrayView(_keys), Containers::arrayView(_values), Math::select}; _trackInterleaved = {_keysInterleaved, _valuesInterleaved, Math::select}; } @@ -235,8 +235,8 @@ void Benchmark::playerAdvanceCallback() { void Benchmark::playerAdvanceRawCallback() { Int result{}; Player player; - player.addRawCallback(_track, [](const TrackViewStorage& track, Float key, std::size_t& hint, void* destination, void(*)(), void*) { - *static_cast(destination) += static_cast&>(track).atStrict(key, hint); + player.addRawCallback(_track, [](const TrackViewStorage& track, Float key, std::size_t& hint, void* destination, void(*)(), void*) { + *static_cast(destination) += static_cast&>(track).atStrict(key, hint); }, &result, nullptr, nullptr) .play({}); CORRADE_BENCHMARK(250) { @@ -249,8 +249,8 @@ void Benchmark::playerAdvanceRawCallback() { void Benchmark::playerAdvanceRawCallbackDirectInterpolator() { Int result{}; Player player; - player.addRawCallback(_track, [](const TrackViewStorage& track, Float key, std::size_t& hint, void* destination, void(*)(), void*) { - *static_cast(destination) += static_cast&>(track).atStrict(Math::select, key, hint); + player.addRawCallback(_track, [](const TrackViewStorage& track, Float key, std::size_t& hint, void* destination, void(*)(), void*) { + *static_cast(destination) += static_cast&>(track).atStrict(Math::select, key, hint); }, &result, nullptr, nullptr) .play({}); CORRADE_BENCHMARK(250) { diff --git a/src/Magnum/Animation/Test/PlayerTest.cpp b/src/Magnum/Animation/Test/PlayerTest.cpp index 922884480..e358bf24d 100644 --- a/src/Magnum/Animation/Test/PlayerTest.cpp +++ b/src/Magnum/Animation/Test/PlayerTest.cpp @@ -77,17 +77,26 @@ struct PlayerTest: TestSuite::Tester { void setState(); - void add(); - void addWithCallback(); - void addWithCallbackTemplate(); - void addWithCallbackOnChange(); - void addWithCallbackOnChangeTemplate(); - void addRawCallback(); + template const T& addTemplateTrack(); + template void add(); + template void addWithCallback(); + template void addWithCallbackTemplate(); + template void addWithCallbackOnChange(); + template void addWithCallbackOnChangeTemplate(); + template void addRawCallback(); void runFor100YearsFloat(); void runFor100YearsChrono(); void debugState(); + + Animation::Track mutableTrack{{ + {1.0f, 1.5f}, + {2.5f, 3.0f}, + {3.0f, 5.0f}, + {4.0f, 2.0f} + }, Math::lerp}; + Animation::TrackView mutableView = mutableTrack; }; const struct { @@ -159,12 +168,18 @@ PlayerTest::PlayerTest() { &PlayerTest::setState, - &PlayerTest::add, - &PlayerTest::addWithCallback, - &PlayerTest::addWithCallbackTemplate, - &PlayerTest::addWithCallbackOnChange, - &PlayerTest::addWithCallbackOnChangeTemplate, - &PlayerTest::addRawCallback}); + &PlayerTest::add>, + &PlayerTest::add>, + &PlayerTest::addWithCallback>, + &PlayerTest::addWithCallback>, + &PlayerTest::addWithCallbackTemplate>, + &PlayerTest::addWithCallbackTemplate>, + &PlayerTest::addWithCallbackOnChange>, + &PlayerTest::addWithCallbackOnChange>, + &PlayerTest::addWithCallbackOnChangeTemplate>, + &PlayerTest::addWithCallbackOnChangeTemplate>, + &PlayerTest::addRawCallback>, + &PlayerTest::addRawCallback>}); addInstancedTests({ &PlayerTest::runFor100YearsFloat, @@ -1114,10 +1129,27 @@ void PlayerTest::setState() { CORRADE_COMPARE(player.state(), State::Stopped); } -void PlayerTest::add() { +/* So we don't need to duplicate the add*() tests by hand */ +template struct AddTemplate; +template<> struct AddTemplate> { + static const char* name() { return "Track"; }; +}; +template<> struct AddTemplate> { + static const char* name() { return "TrackView"; }; +}; +template<> const Animation::Track& PlayerTest::addTemplateTrack() { + return Track; +} +template<> const Animation::TrackView& PlayerTest::addTemplateTrack() { + return mutableView; +} + +template void PlayerTest::add() { + setTestCaseTemplateName(AddTemplate::name()); + Float value = -1.0f; Player player; - player.add(Track, value) + player.add(addTemplateTrack(), value) .play(2.0f); CORRADE_COMPARE(player.duration().size(), 3.0f); @@ -1130,13 +1162,15 @@ void PlayerTest::add() { CORRADE_COMPARE(value, 4.0f); } -void PlayerTest::addWithCallback() { +template void PlayerTest::addWithCallback() { + setTestCaseTemplateName(AddTemplate::name()); + struct Data { Float value = -1.0f; Int called = 0; } data; Player player; - player.addWithCallback(Track, [](Float, const Float& value, void* userData) { + player.addWithCallback(addTemplateTrack(), [](Float, const Float& value, void* userData) { static_cast(userData)->value = value; ++static_cast(userData)->called; }, &data) @@ -1154,13 +1188,15 @@ void PlayerTest::addWithCallback() { CORRADE_COMPARE(data.called, 1); } -void PlayerTest::addWithCallbackTemplate() { +template void PlayerTest::addWithCallbackTemplate() { + setTestCaseTemplateName(AddTemplate::name()); + struct Data { Float value = -1.0f; Int called = 0; } data; Player player; - player.addWithCallback(Track, [](Float, const Float& value, Data& userData) { + player.addWithCallback(addTemplateTrack(), [](Float, const Float& value, Data& userData) { userData.value = value; ++userData.called; }, data) @@ -1178,13 +1214,15 @@ void PlayerTest::addWithCallbackTemplate() { CORRADE_COMPARE(data.called, 1); } -void PlayerTest::addWithCallbackOnChange() { +template void PlayerTest::addWithCallbackOnChange() { + setTestCaseTemplateName(AddTemplate::name()); + struct Data { Float value = -1.0f; Int called = 0; } data; Player player; - player.addWithCallbackOnChange(Track, [](Float, const Float& value, void* userData) { + player.addWithCallbackOnChange(addTemplateTrack(), [](Float, const Float& value, void* userData) { static_cast(userData)->value = value; ++static_cast(userData)->called; }, data.value, &data) @@ -1212,13 +1250,15 @@ void PlayerTest::addWithCallbackOnChange() { CORRADE_COMPARE(data.called, 2); } -void PlayerTest::addWithCallbackOnChangeTemplate() { +template void PlayerTest::addWithCallbackOnChangeTemplate() { + setTestCaseTemplateName(AddTemplate::name()); + struct Data { Float value = -1.0f; Int called = 0; } data; Player player; - player.addWithCallbackOnChange(Track, [](Float, const Float& value, Data& userData) { + player.addWithCallbackOnChange(addTemplateTrack(), [](Float, const Float& value, Data& userData) { userData.value = value; ++userData.called; }, data.value, data) @@ -1251,17 +1291,19 @@ void callback(std::vector& data, Int value) { data.push_back(value); } -void PlayerTest::addRawCallback() { - Animation::Track track; +template void PlayerTest::addRawCallback() { + setTestCaseTemplateName(AddTemplate::name()); + + T track; Int result = -1; std::vector data; Animation::Player player; player.addRawCallback(track, - [](const Animation::TrackViewStorage& track, Float key, + [](const Animation::TrackViewStorage& track, Float key, std::size_t& hint, void* destination, void(*callback)(), void* userData) { - Int value = static_cast&>(track).at(key, hint); + Int value = static_cast&>(track).at(key, hint); if(value == *static_cast(destination)) return; *static_cast(destination) = value; reinterpret_cast&, Int)>(callback)(*static_cast*>(userData), value); diff --git a/src/Magnum/Animation/Test/TrackTest.cpp b/src/Magnum/Animation/Test/TrackTest.cpp index f399bf983..9e3cf54a1 100644 --- a/src/Magnum/Animation/Test/TrackTest.cpp +++ b/src/Magnum/Animation/Test/TrackTest.cpp @@ -118,34 +118,45 @@ TrackTest::TrackTest() { using namespace Math::Literals; void TrackTest::constructEmpty() { - const Track a; + Track a; + const Track& ca = a; - CORRADE_VERIFY(!a.interpolator()); - CORRADE_VERIFY(!a.size()); - CORRADE_VERIFY(a.keys().empty()); + CORRADE_VERIFY(!ca.interpolator()); + CORRADE_VERIFY(!ca.size()); + CORRADE_VERIFY(ca.keys().empty()); + CORRADE_VERIFY(ca.keys().empty()); CORRADE_VERIFY(a.values().empty()); - CORRADE_COMPARE(a.at(42.0f), Vector3{}); + CORRADE_VERIFY(ca.values().empty()); + CORRADE_COMPARE(ca.at(42.0f), Vector3{}); } void TrackTest::constructArrayInterpolator() { - const Track a{ + Track a{ Containers::Array>{Containers::InPlaceInit, {{1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}}, Math::select, Extrapolation::Extrapolated, Extrapolation::Constant}; - - CORRADE_COMPARE(a.interpolation(), Interpolation::Custom); - CORRADE_COMPARE(a.interpolator(), Math::select); - CORRADE_COMPARE(a.before(), Extrapolation::Extrapolated); - CORRADE_COMPARE(a.after(), Extrapolation::Constant); - CORRADE_COMPARE(a.duration(), (Range1D{1.0f, 5.0f})); - CORRADE_COMPARE(a.size(), 2); + const Track& ca = a; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Custom); + CORRADE_COMPARE(ca.interpolator(), Math::select); + CORRADE_COMPARE(ca.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(ca.after(), Extrapolation::Constant); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); CORRADE_COMPARE(a.data().size(), 2); + CORRADE_COMPARE(ca.data().size(), 2); CORRADE_COMPARE(a.keys().size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + CORRADE_COMPARE(ca.data()[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); CORRADE_COMPARE(a.data()[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + CORRADE_COMPARE(ca.keys()[1], 5.0f); CORRADE_COMPARE(a.keys()[1], 5.0f); + CORRADE_COMPARE(ca.values()[0], (Vector3{3.0f, 1.0f, 0.1f})); CORRADE_COMPARE(a.values()[0], (Vector3{3.0f, 1.0f, 0.1f})); } @@ -379,12 +390,13 @@ void TrackTest::constructInitializerListInterpolationInterpolatorDefaults() { } void TrackTest::convertView() { - const Track a{ + Track a{ {{1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}, Interpolation::Linear, customLerp, Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; - const TrackView av = a; + const Track& ca = a; + const TrackView av = a; CORRADE_COMPARE(av.interpolation(), Interpolation::Linear); CORRADE_COMPARE(av.interpolator(), customLerp); CORRADE_COMPARE(av.before(), Extrapolation::Extrapolated); @@ -396,6 +408,19 @@ void TrackTest::convertView() { CORRADE_COMPARE(av[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); CORRADE_COMPARE(av.keys()[1], 5.0f); CORRADE_COMPARE(av.values()[0], (Vector3{3.0f, 1.0f, 0.1f})); + + const TrackView cav = ca; + CORRADE_COMPARE(cav.interpolation(), Interpolation::Linear); + CORRADE_COMPARE(cav.interpolator(), customLerp); + CORRADE_COMPARE(cav.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(cav.after(), Extrapolation::DefaultConstructed); + CORRADE_COMPARE(cav.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(cav.size(), 2); + CORRADE_COMPARE(cav.keys().size(), 2); + CORRADE_COMPARE(cav.values().size(), 2); + CORRADE_COMPARE(cav[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + CORRADE_COMPARE(cav.keys()[1], 5.0f); + CORRADE_COMPARE(cav.values()[0], (Vector3{3.0f, 1.0f, 0.1f})); } void TrackTest::at() { diff --git a/src/Magnum/Animation/Test/TrackViewTest.cpp b/src/Magnum/Animation/Test/TrackViewTest.cpp index 728c3a67f..ba477b1ee 100644 --- a/src/Magnum/Animation/Test/TrackViewTest.cpp +++ b/src/Magnum/Animation/Test/TrackViewTest.cpp @@ -49,6 +49,7 @@ struct TrackViewTest: TestSuite::Tester { void constructSingleArrayInterpolationInterpolatorDefaults(); void constructCopyStorage(); + void convertToConstView(); void at(); void atStrict(); @@ -106,7 +107,8 @@ TrackViewTest::TrackViewTest() { &TrackViewTest::constructSingleArrayInterpolationInterpolator, &TrackViewTest::constructSingleArrayInterpolationInterpolatorDefaults, - &TrackViewTest::constructCopyStorage}); + &TrackViewTest::constructCopyStorage, + &TrackViewTest::convertToConstView}); addInstancedTests({&TrackViewTest::at, &TrackViewTest::atStrict}, Containers::arraySize(AtData)); @@ -119,6 +121,7 @@ using namespace Math::Literals; void TrackViewTest::constructEmpty() { const TrackView a; + const TrackView ca; CORRADE_VERIFY(!a.interpolator()); CORRADE_COMPARE(a.duration(), Range1D{}); @@ -126,11 +129,18 @@ void TrackViewTest::constructEmpty() { CORRADE_VERIFY(a.keys().empty()); CORRADE_VERIFY(a.values().empty()); CORRADE_COMPARE(a.at(42.0f), Vector3{}); + + CORRADE_VERIFY(!ca.interpolator()); + CORRADE_COMPARE(ca.duration(), Range1D{}); + CORRADE_VERIFY(!ca.size()); + CORRADE_VERIFY(ca.keys().empty()); + CORRADE_VERIFY(ca.values().empty()); + CORRADE_COMPARE(ca.at(42.0f), Vector3{}); } void TrackViewTest::constructInterpolator() { - constexpr Float keys[]{1.0f, 5.0f}; - constexpr Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + Float keys[]{1.0f, 5.0f}; + Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; const TrackView a{keys, values, Math::select, Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; @@ -144,11 +154,27 @@ void TrackViewTest::constructInterpolator() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + constexpr Float ckeys[]{1.0f, 5.0f}; + constexpr Vector3 cvalues[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + + const TrackView ca{ckeys, cvalues, Math::select, + Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Custom); + CORRADE_COMPARE(ca.interpolator(), Math::select); + CORRADE_COMPARE(ca.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(ca.after(), Extrapolation::DefaultConstructed); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructInterpolatorDefaults() { - constexpr Float keys[]{1.0f, 5.0f}; - constexpr Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + Float keys[]{1.0f, 5.0f}; + Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; const TrackView a{keys, values, Math::lerp, Extrapolation::Constant}; @@ -162,11 +188,27 @@ void TrackViewTest::constructInterpolatorDefaults() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + constexpr Float ckeys[]{1.0f, 5.0f}; + constexpr Vector3 cvalues[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + + const TrackView ca{ckeys, cvalues, Math::lerp, + Extrapolation::Constant}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Custom); + CORRADE_COMPARE(ca.interpolator(), Math::lerp); + CORRADE_COMPARE(ca.before(), Extrapolation::Constant); + CORRADE_COMPARE(ca.after(), Extrapolation::Constant); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructInterpolation() { - constexpr Float keys[]{1.0f, 5.0f}; - constexpr Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + Float keys[]{1.0f, 5.0f}; + Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; const TrackView a{keys, values, Interpolation::Linear, Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; @@ -180,11 +222,27 @@ void TrackViewTest::constructInterpolation() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + constexpr Float ckeys[]{1.0f, 5.0f}; + constexpr Vector3 cvalues[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + + const TrackView ca{ckeys, cvalues, Interpolation::Linear, + Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Linear); + CORRADE_COMPARE(ca.interpolator(), Math::lerp); + CORRADE_COMPARE(ca.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(ca.after(), Extrapolation::DefaultConstructed); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructInterpolationDefaults() { - constexpr Float keys[]{1.0f, 5.0f}; - constexpr Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + Float keys[]{1.0f, 5.0f}; + Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; const TrackView a{keys, values, Interpolation::Constant, Extrapolation::Constant}; @@ -198,13 +256,29 @@ void TrackViewTest::constructInterpolationDefaults() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + constexpr Float ckeys[]{1.0f, 5.0f}; + constexpr Vector3 cvalues[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + + const TrackView ca{ckeys, cvalues, Interpolation::Constant, + Extrapolation::Constant}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Constant); + CORRADE_COMPARE(ca.interpolator(), Math::select); + CORRADE_COMPARE(ca.before(), Extrapolation::Constant); + CORRADE_COMPARE(ca.after(), Extrapolation::Constant); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } Vector3 customLerp(const Vector3&, const Vector3&, Float) { return {}; } void TrackViewTest::constructInterpolationInterpolator() { - constexpr Float keys[]{1.0f, 5.0f}; - constexpr Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + Float keys[]{1.0f, 5.0f}; + Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; const TrackView a{keys, values, Interpolation::Linear, customLerp, Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; @@ -218,11 +292,27 @@ void TrackViewTest::constructInterpolationInterpolator() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + constexpr Float ckeys[]{1.0f, 5.0f}; + constexpr Vector3 cvalues[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + + const TrackView ca{ckeys, cvalues, + Interpolation::Linear, customLerp, Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Linear); + CORRADE_COMPARE(ca.interpolator(), customLerp); + CORRADE_COMPARE(ca.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(ca.after(), Extrapolation::DefaultConstructed); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructInterpolationInterpolatorDefaults() { - constexpr Float keys[]{1.0f, 5.0f}; - constexpr Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + Float keys[]{1.0f, 5.0f}; + Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; const TrackView a{keys, values, Interpolation::Constant, customLerp, Extrapolation::Constant}; @@ -236,10 +326,26 @@ void TrackViewTest::constructInterpolationInterpolatorDefaults() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + constexpr Float ckeys[]{1.0f, 5.0f}; + constexpr Vector3 cvalues[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + + const TrackView ca{ckeys, cvalues, + Interpolation::Constant, customLerp, Extrapolation::Constant}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Constant); + CORRADE_COMPARE(ca.interpolator(), customLerp); + CORRADE_COMPARE(ca.before(), Extrapolation::Constant); + CORRADE_COMPARE(ca.after(), Extrapolation::Constant); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructSingleArrayInterpolator() { - const std::pair data[]{ + std::pair data[]{ {1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}; @@ -255,10 +361,27 @@ void TrackViewTest::constructSingleArrayInterpolator() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + const std::pair cdata[]{ + {1.0f, {3.0f, 1.0f, 0.1f}}, + {5.0f, {0.3f, 0.6f, 1.0f}}}; + + const TrackView ca{cdata, Math::select, + Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Custom); + CORRADE_COMPARE(ca.interpolator(), Math::select); + CORRADE_COMPARE(ca.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(ca.after(), Extrapolation::DefaultConstructed); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructSingleArrayInterpolatorDefaults() { - const std::pair data[]{ + std::pair data[]{ {1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}; @@ -274,10 +397,27 @@ void TrackViewTest::constructSingleArrayInterpolatorDefaults() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + const std::pair cdata[]{ + {1.0f, {3.0f, 1.0f, 0.1f}}, + {5.0f, {0.3f, 0.6f, 1.0f}}}; + + const TrackView ca{cdata, Math::lerp, + Extrapolation::Constant}; + + CORRADE_COMPARE(a.interpolation(), Interpolation::Custom); + CORRADE_COMPARE(a.interpolator(), Math::lerp); + CORRADE_COMPARE(a.before(), Extrapolation::Constant); + CORRADE_COMPARE(a.after(), Extrapolation::Constant); + CORRADE_COMPARE(a.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(a.size(), 2); + CORRADE_COMPARE(a.keys().size(), 2); + CORRADE_COMPARE(a.values().size(), 2); + CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructSingleArrayInterpolation() { - const std::pair data[]{ + std::pair data[]{ {1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}; @@ -293,10 +433,27 @@ void TrackViewTest::constructSingleArrayInterpolation() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + const std::pair cdata[]{ + {1.0f, {3.0f, 1.0f, 0.1f}}, + {5.0f, {0.3f, 0.6f, 1.0f}}}; + + const TrackView ca{cdata, Interpolation::Linear, + Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Linear); + CORRADE_COMPARE(ca.interpolator(), Math::lerp); + CORRADE_COMPARE(ca.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(ca.after(), Extrapolation::DefaultConstructed); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructSingleArrayInterpolationDefaults() { - const std::pair data[]{ + std::pair data[]{ {1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}; @@ -312,10 +469,27 @@ void TrackViewTest::constructSingleArrayInterpolationDefaults() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + const std::pair cdata[]{ + {1.0f, {3.0f, 1.0f, 0.1f}}, + {5.0f, {0.3f, 0.6f, 1.0f}}}; + + const TrackView ca{cdata, Interpolation::Constant, + Extrapolation::Constant}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Constant); + CORRADE_COMPARE(ca.interpolator(), Math::select); + CORRADE_COMPARE(ca.before(), Extrapolation::Constant); + CORRADE_COMPARE(ca.after(), Extrapolation::Constant); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructSingleArrayInterpolationInterpolator() { - const std::pair data[]{ + std::pair data[]{ {1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}; @@ -331,10 +505,27 @@ void TrackViewTest::constructSingleArrayInterpolationInterpolator() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + const std::pair cdata[]{ + {1.0f, {3.0f, 1.0f, 0.1f}}, + {5.0f, {0.3f, 0.6f, 1.0f}}}; + + const TrackView ca{cdata, Interpolation::Linear, customLerp, + Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Linear); + CORRADE_COMPARE(ca.interpolator(), customLerp); + CORRADE_COMPARE(ca.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(ca.after(), Extrapolation::DefaultConstructed); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructSingleArrayInterpolationInterpolatorDefaults() { - const std::pair data[]{ + std::pair data[]{ {1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}; @@ -350,10 +541,27 @@ void TrackViewTest::constructSingleArrayInterpolationInterpolatorDefaults() { CORRADE_COMPARE(a.keys().size(), 2); CORRADE_COMPARE(a.values().size(), 2); CORRADE_COMPARE(a[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + const std::pair cdata[]{ + {1.0f, {3.0f, 1.0f, 0.1f}}, + {5.0f, {0.3f, 0.6f, 1.0f}}}; + + const TrackView ca{cdata, Interpolation::Constant, + customLerp, Extrapolation::Constant}; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Constant); + CORRADE_COMPARE(ca.interpolator(), customLerp); + CORRADE_COMPARE(ca.before(), Extrapolation::Constant); + CORRADE_COMPARE(ca.after(), Extrapolation::Constant); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } void TrackViewTest::constructCopyStorage() { - const std::pair data[]{ + std::pair data[]{ {1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}; @@ -375,6 +583,30 @@ void TrackViewTest::constructCopyStorage() { CORRADE_COMPARE(bv[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); } +void TrackViewTest::convertToConstView() { + Float keys[]{1.0f, 5.0f}; + Vector3 values[]{{3.0f, 1.0f, 0.1f}, {0.3f, 0.6f, 1.0f}}; + + const TrackView a{keys, values, Interpolation::Linear, + customLerp, Extrapolation::Extrapolated, Extrapolation::DefaultConstructed}; + + const TrackView ca = a; + + CORRADE_COMPARE(ca.interpolation(), Interpolation::Linear); + CORRADE_COMPARE(ca.interpolator(), customLerp); + CORRADE_COMPARE(ca.before(), Extrapolation::Extrapolated); + CORRADE_COMPARE(ca.after(), Extrapolation::DefaultConstructed); + CORRADE_COMPARE(ca.duration(), (Range1D{1.0f, 5.0f})); + CORRADE_COMPARE(ca.size(), 2); + CORRADE_COMPARE(ca.keys().size(), 2); + CORRADE_COMPARE(ca.values().size(), 2); + CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); + + /* Conversion back is not possible */ + CORRADE_VERIFY((std::is_convertible, TrackView>::value)); + CORRADE_VERIFY(!(std::is_convertible, TrackView>::value)); +} + const std::pair Keyframes[]{ {0.0f, 3.0f}, {2.0f, 1.0f}, @@ -386,7 +618,7 @@ void TrackViewTest::at() { const auto& data = AtData[testCaseInstanceId()]; setTestCaseDescription(data.name); - const TrackView a{Keyframes, Math::lerp, + const TrackView a{Keyframes, Math::lerp, data.extrapolationBefore, data.extrapolationAfter}; std::size_t hint{}; @@ -399,7 +631,7 @@ void TrackViewTest::atStrict() { const auto& data = AtData[testCaseInstanceId()]; setTestCaseDescription(data.name); - const TrackView a{Keyframes, Math::lerp, + const TrackView a{Keyframes, Math::lerp, data.extrapolationBefore, data.extrapolationAfter}; std::size_t hint{}; @@ -416,7 +648,7 @@ Float lerpHalf(const Half& a, const Half& b, Float t) { } void TrackViewTest::atDifferentResultType() { - const TrackView a{ + const TrackView a{ {Keyframes, &Keyframes[0].first, Containers::arraySize(Keyframes), sizeof(Keyframes[0])}, HalfValues, lerpHalf}; @@ -427,7 +659,7 @@ void TrackViewTest::atDifferentResultType() { } void TrackViewTest::atDifferentResultTypeStrict() { - const TrackView a{ + const TrackView a{ {Keyframes, &Keyframes[0].first, Containers::arraySize(Keyframes), sizeof(Keyframes[0])}, HalfValues, lerpHalf}; diff --git a/src/Magnum/Animation/Track.h b/src/Magnum/Animation/Track.h index 89dcc95f6..f389b71d6 100644 --- a/src/Magnum/Animation/Track.h +++ b/src/Magnum/Animation/Track.h @@ -243,7 +243,12 @@ template& operator=(Track&&) = default; /** @brief Conversion to a view */ - operator TrackView() const noexcept { + operator TrackView() const noexcept { + return TrackView{_data, _interpolation, _interpolator, _before, _after}; + } + + /** @overload */ + operator TrackView() noexcept { return TrackView{_data, _interpolation, _interpolator, _before, _after}; } @@ -298,6 +303,9 @@ template> data() const { return _data; } + /** @overload */ + Containers::ArrayView> data() { return _data; } + /** * @brief Key data * @@ -307,6 +315,11 @@ template{_data, &_data[0].first, _data.size(), sizeof(std::pair)} : nullptr; } + /** @overload */ + Containers::StridedArrayView1D keys() { + return _data ? Containers::StridedArrayView1D{_data, &_data[0].first, _data.size(), sizeof(std::pair)} : nullptr; + } + /** * @brief Value data * @@ -316,6 +329,11 @@ template{_data, &_data[0].second, _data.size(), sizeof(std::pair)} : nullptr; } + /** @overload */ + Containers::StridedArrayView1D values() { + return _data ? Containers::StridedArrayView1D{_data, &_data[0].second, _data.size(), sizeof(std::pair)} : nullptr; + } + /** * @brief Keyframe access * @@ -323,6 +341,9 @@ template& operator[](std::size_t i) const { return _data[i]; } + /** @overload */ + std::pair& operator[](std::size_t i) { return _data[i]; } + /** * @brief Animated value at a given time * @@ -452,8 +473,8 @@ template class TrackViewStorage { * a default-constructed value is returned. Use @ref Math::join() to * calculate combined duration for a set of tracks. */ - Math::Range1D duration() const { - return _keys.empty() ? Math::Range1D{} : Math::Range1D{_keys.front(), _keys.back()}; + Math::Range1D::type> duration() const { + return _keys.empty() ? Math::Range1D::type>{} : Math::Range1D::type>{_keys.front(), _keys.back()}; } /** @brief Keyframe count */ @@ -466,17 +487,19 @@ template class TrackViewStorage { * * @see @ref TrackView::values(), @ref TrackView::operator[]() */ - Containers::StridedArrayView1D keys() const { + Containers::StridedArrayView1D keys() const { return _keys; } private: template friend class TrackView; + template explicit TrackViewStorage(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, R(*interpolator)(const V&, const V&, Float), Extrapolation before, Extrapolation after) noexcept: _keys{keys}, _values{reinterpret_cast&>(values)}, _interpolator{reinterpret_cast(interpolator)}, _interpolation{interpolation}, _before{before}, _after{after} {} + template explicit TrackViewStorage(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, R(*interpolator)(const V&, const V&, Float), Extrapolation before, Extrapolation after) noexcept: _keys{keys}, _values{reinterpret_cast&>(values)}, _interpolator{reinterpret_cast(interpolator)}, _interpolation{interpolation}, _before{before}, _after{after} {} - Containers::StridedArrayView1D _keys; - Containers::StridedArrayView1D _values; + Containers::StridedArrayView1D _keys; + Containers::StridedArrayView1D::value, const char, char>::type> _values; void(*_interpolator)(void); Interpolation _interpolation; Extrapolation _before, _after; @@ -488,8 +511,9 @@ template class TrackViewStorage { @tparam V Value type @tparam R Result type -Unlike @ref Track this is a non-owning view onto keyframe + value pairs. See -its documentation for more information. +Unlike @ref Track this is a non-owning view onto keyframe + value pairs. The +@p K and @p V can be either both mutable or both @cpp const @ce. See the +@ref Track documentation for more information. @experimental */ template #endif > class TrackView: public TrackViewStorage { + static_assert(std::is_const::value == std::is_const::value && !std::is_const::value, + "K and V should be either both mutable or both const; R shouldn't be const"); + public: /** @brief Value type */ typedef V ValueType; + /** + * @brief Key-value type + * + * Used mainly when converting from @ref Track. Equal to + * @cpp std::pair @ce if @p K and @p V are not @cpp const @ce, + * and to @cpp const std::pair @ce (where @p K_ / @p V_ are + * with @cpp const @ce removed) when they are @cpp const @ce. + */ + typedef typename std::conditional::value, const std::pair::type, typename std::remove_const::type>, std::pair>::type KeyValueType; + /** @brief Animation result type */ typedef R ResultType; @@ -527,17 +564,17 @@ template&, const Containers::StridedArrayView1D&, Interpolation, Interpolator, Extrapolation, Extrapolation) or - * @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolation, Extrapolation, Extrapolation) + * See @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolation, Interpolator, Extrapolation, Extrapolation) or + * @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolation, Extrapolation, Extrapolation) * for an alternative. */ - /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage{keys, values, Interpolation::Custom, interpolator, before, after} {} + /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage{keys, values, Interpolation::Custom, interpolator, before, after} {} /** @overload - * Equivalent to calling @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolator, Extrapolation, Extrapolation) + * Equivalent to calling @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolator, Extrapolation, Extrapolation) * with both @p before and @p after set to @p extrapolation. */ - /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{keys, values, interpolator, extrapolation, extrapolation} {} + /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{keys, values, interpolator, extrapolation, extrapolation} {} /** * @brief Construct with custom interpolator from an interleaved array @@ -547,15 +584,15 @@ template&, const Containers::StridedArrayView1D&, Interpolator, Extrapolation, Extrapolation). + * @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolator, Extrapolation, Extrapolation). */ - /*implicit*/ TrackView(Containers::ArrayView> data, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackView{Containers::StridedArrayView1D{data, data ? &data[0].first : nullptr, data.size(), sizeof(std::pair)}, Containers::StridedArrayView1D{data, data ? &data[0].second : nullptr, data.size(), sizeof(std::pair)}, interpolator, before, after} {} + /*implicit*/ TrackView(Containers::ArrayView data, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackView{Containers::StridedArrayView1D{data, data ? &data[0].first : nullptr, data.size(), sizeof(std::pair)}, Containers::StridedArrayView1D{data, data ? &data[0].second : nullptr, data.size(), sizeof(std::pair)}, interpolator, before, after} {} /** @overload - * Equivalent to calling @ref TrackView(Containers::ArrayView>, Interpolator, Extrapolation, Extrapolation) + * Equivalent to calling @ref TrackView(Containers::ArrayView, Interpolator, Extrapolation, Extrapolation) * with both @p before and @p after set to @p extrapolation. */ - explicit TrackView(Containers::ArrayView> data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{data, interpolator, extrapolation, extrapolation} {} + explicit TrackView(Containers::ArrayView data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{data, interpolator, extrapolation, extrapolation} {} /** * @brief Construct with both generic and custom interpolator @@ -572,13 +609,13 @@ template& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage{keys, values, interpolation, interpolator, before, after} {} + /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage{keys, values, interpolation, interpolator, before, after} {} /** @overload - * Equivalent to calling @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolation, Interpolator, Extrapolation, Extrapolation) + * Equivalent to calling @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolation, Interpolator, Extrapolation, Extrapolation) * with both @p before and @p after set to @p extrapolation. */ - /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{keys, values, interpolation, interpolator, extrapolation, extrapolation} {} + /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{keys, values, interpolation, interpolator, extrapolation, extrapolation} {} /** * @brief Construct with both generic and custom interpolator from an interleaved array @@ -589,15 +626,15 @@ template&, const Containers::StridedArrayView1D&, Interpolator, Extrapolation, Extrapolation). + * @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolator, Extrapolation, Extrapolation). */ - /*implicit*/ TrackView(Containers::ArrayView> data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage{Containers::StridedArrayView1D{data, data ? &data[0].first : nullptr, data.size(), sizeof(std::pair)}, Containers::StridedArrayView1D{data, data ? &data[0].second : nullptr, data.size(), sizeof(std::pair)}, interpolation, interpolator, before, after} {} + /*implicit*/ TrackView(Containers::ArrayView data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage{Containers::StridedArrayView1D{data, data ? &data[0].first : nullptr, data.size(), sizeof(std::pair)}, Containers::StridedArrayView1D{data, data ? &data[0].second : nullptr, data.size(), sizeof(std::pair)}, interpolation, interpolator, before, after} {} /** @overload - * Equivalent to calling @ref TrackView(Containers::ArrayView>, Interpolation, Interpolator, Extrapolation, Extrapolation) + * Equivalent to calling @ref TrackView(Containers::ArrayView, Interpolation, Interpolator, Extrapolation, Extrapolation) * with both @p before and @p after set to @p extrapolation. */ - /*implicit*/ TrackView(Containers::ArrayView> data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{data, interpolation, interpolator, extrapolation, extrapolation} {} + /*implicit*/ TrackView(Containers::ArrayView data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{data, interpolation, interpolator, extrapolation, extrapolation} {} /** * @brief Construct with generic interpolation behavior @@ -613,13 +650,13 @@ template& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage{keys, values, interpolation, interpolatorFor(interpolation), before, after} {} + /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage{keys, values, interpolation, interpolatorFor(interpolation), before, after} {} /** @overload - * Equivalent to calling @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolation, Extrapolation, Extrapolation) + * Equivalent to calling @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolation, Extrapolation, Extrapolation) * with both @p before and @p after set to @p extrapolation. */ - /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{keys, values, interpolation, extrapolation, extrapolation} {} + /*implicit*/ TrackView(const Containers::StridedArrayView1D& keys, const Containers::StridedArrayView1D& values, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{keys, values, interpolation, extrapolation, extrapolation} {} /** * @brief Construct with generic interpolation behavior from an interleaved array @@ -629,15 +666,18 @@ template&, const Containers::StridedArrayView1D&, Interpolator, Extrapolation, Extrapolation). + * @ref TrackView(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, Interpolator, Extrapolation, Extrapolation). */ - /*implicit*/ TrackView(Containers::ArrayView> data, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: TrackView{Containers::StridedArrayView1D{data, data ? &data[0].first : nullptr, data.size(), sizeof(std::pair)}, Containers::StridedArrayView1D{data, data ? &data[0].second : nullptr, data.size(), sizeof(std::pair)}, interpolation, before, after} {} + /*implicit*/ TrackView(Containers::ArrayView data, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: TrackView{Containers::StridedArrayView1D{data, data ? &data[0].first : nullptr, data.size(), sizeof(std::pair)}, Containers::StridedArrayView1D{data, data ? &data[0].second : nullptr, data.size(), sizeof(std::pair)}, interpolation, before, after} {} /** @overload - * Equivalent to calling @ref TrackView(Containers::ArrayView>, Interpolation, Extrapolation, Extrapolation) + * Equivalent to calling @ref TrackView(Containers::ArrayView, Interpolation, Extrapolation, Extrapolation) * with both @p before and @p after set to @p extrapolation. */ - /*implicit*/ TrackView(Containers::ArrayView> data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{data, interpolation, extrapolation, extrapolation} {} + /*implicit*/ TrackView(Containers::ArrayView data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant) noexcept: TrackView{data, interpolation, extrapolation, extrapolation} {} + + /** @brief Convert a mutable view to a const one */ + template::value>::type> /*implicit*/ TrackView(const TrackView::type, typename std::remove_const::type, R>& other) noexcept: TrackViewStorage{other._keys, reinterpret_cast&>(other._values), other._interpolation, reinterpret_cast(other._interpolator), other._before, other._after} {} /** * @brief Interpolation function @@ -653,8 +693,8 @@ template values() const { - return reinterpret_cast&>(TrackViewStorage::_values); + Containers::StridedArrayView1D values() const { + return reinterpret_cast&>(TrackViewStorage::_values); } /** @@ -662,7 +702,7 @@ template operator[](std::size_t i) const { + std::pair::type, typename std::remove_const::type> operator[](std::size_t i) const { return {TrackViewStorage::_keys[i], values()[i]}; } @@ -715,7 +755,7 @@ template::_keys, values(), TrackViewStorage::_before, TrackViewStorage::_after, interpolator, frame, hint); + return interpolate::type, typename std::remove_const::type, R>(TrackViewStorage::_keys, values(), TrackViewStorage::_before, TrackViewStorage::_after, interpolator, frame, hint); } /** @@ -739,7 +779,7 @@ template::_keys, values(), interpolator, frame, hint); + return interpolateStrict::type, typename std::remove_const::type, R>(TrackViewStorage::_keys, values(), interpolator, frame, hint); } };