Browse Source

Trade: make it possible to construct AnimationData from track init list.

Easier to write. Need to take extra care with default deleters.
pull/371/head
Vladimír Vondruš 7 years ago
parent
commit
6ddcc0b1ae
  1. 2
      doc/changelog.dox
  2. 9
      src/Magnum/Trade/AnimationData.cpp
  3. 28
      src/Magnum/Trade/AnimationData.h
  4. 7
      src/Magnum/Trade/Test/AbstractImporterTest.cpp
  5. 44
      src/Magnum/Trade/Test/AnimationDataTest.cpp

2
doc/changelog.dox

@ -283,6 +283,8 @@ See also:
- New convenience @ref Trade::AnimationTrackData constructor taking a - New convenience @ref Trade::AnimationTrackData constructor taking a
templated @ref Animation::TrackView type, autodetecting value and result templated @ref Animation::TrackView type, autodetecting value and result
@ref Trade::AnimationTrackType out of it @ref Trade::AnimationTrackType out of it
- New convenience @ref Trade::AnimationData constructors taking an
@ref std::initializer_list of @ref Trade::AnimationTrackData
@subsection changelog-latest-buildsystem Build system @subsection changelog-latest-buildsystem Build system

9
src/Magnum/Trade/AnimationData.cpp

@ -29,17 +29,22 @@
#include "Magnum/Math/Vector4.h" #include "Magnum/Math/Vector4.h"
#include "Magnum/Math/Quaternion.h" #include "Magnum/Math/Quaternion.h"
#include "Magnum/Trade/Implementation/arrayUtilities.h"
namespace Magnum { namespace Trade { namespace Magnum { namespace Trade {
AnimationData::AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const Range1D& duration, const void* importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _duration{duration}, _data{std::move(data)}, _tracks{std::move(tracks)}, _importerState{importerState} {} AnimationData::AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const Range1D& duration, const void* importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _duration{duration}, _data{std::move(data)}, _tracks{std::move(tracks)}, _importerState{importerState} {}
AnimationData::AnimationData(Containers::Array<char>&& data, std::initializer_list<AnimationTrackData> tracks, const Range1D& duration, const void* importerState): AnimationData{std::move(data), Implementation::initializerListToArrayWithDefaultDeleter(tracks), duration, importerState} {}
AnimationData::AnimationData(const DataFlags dataFlags, const Containers::ArrayView<const void> data, Containers::Array<AnimationTrackData>&& tracks, const Range1D& duration, const void* importerState) noexcept: AnimationData{Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, std::move(tracks), duration, importerState} { AnimationData::AnimationData(const DataFlags dataFlags, const Containers::ArrayView<const void> data, Containers::Array<AnimationTrackData>&& tracks, const Range1D& duration, const void* importerState) noexcept: AnimationData{Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, std::move(tracks), duration, importerState} {
CORRADE_ASSERT(!(dataFlags & DataFlag::Owned), CORRADE_ASSERT(!(dataFlags & DataFlag::Owned),
"Trade::AnimationData: can't construct a non-owned instance with" << dataFlags, ); "Trade::AnimationData: can't construct a non-owned instance with" << dataFlags, );
_dataFlags = dataFlags; _dataFlags = dataFlags;
} }
AnimationData::AnimationData(const DataFlags dataFlags, const Containers::ArrayView<const void> data, std::initializer_list<AnimationTrackData> tracks, const Range1D& duration, const void* importerState): AnimationData{dataFlags, data, Implementation::initializerListToArrayWithDefaultDeleter(tracks), duration, importerState} {}
AnimationData::AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _data{std::move(data)}, _tracks{std::move(tracks)}, _importerState{importerState} { AnimationData::AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _data{std::move(data)}, _tracks{std::move(tracks)}, _importerState{importerState} {
if(!_tracks.empty()) { if(!_tracks.empty()) {
/* Reset duration to duration of the first track so it properly support /* Reset duration to duration of the first track so it properly support
@ -50,12 +55,16 @@ AnimationData::AnimationData(Containers::Array<char>&& data, Containers::Array<A
} }
} }
AnimationData::AnimationData(Containers::Array<char>&& data, std::initializer_list<AnimationTrackData> tracks, const void* importerState): AnimationData{std::move(data), Implementation::initializerListToArrayWithDefaultDeleter(tracks), importerState} {}
AnimationData::AnimationData(const DataFlags dataFlags, const Containers::ArrayView<const void> data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState) noexcept: AnimationData{Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, std::move(tracks), importerState} { AnimationData::AnimationData(const DataFlags dataFlags, const Containers::ArrayView<const void> data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState) noexcept: AnimationData{Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), Implementation::nonOwnedArrayDeleter}, std::move(tracks), importerState} {
CORRADE_ASSERT(!(dataFlags & DataFlag::Owned), CORRADE_ASSERT(!(dataFlags & DataFlag::Owned),
"Trade::AnimationData: can't construct a non-owned instance with" << dataFlags, ); "Trade::AnimationData: can't construct a non-owned instance with" << dataFlags, );
_dataFlags = dataFlags; _dataFlags = dataFlags;
} }
AnimationData::AnimationData(const DataFlags dataFlags, const Containers::ArrayView<const void> data, std::initializer_list<AnimationTrackData> tracks, const void* importerState): AnimationData{dataFlags, data, Implementation::initializerListToArrayWithDefaultDeleter(tracks), importerState} {}
AnimationData::~AnimationData() = default; AnimationData::~AnimationData() = default;
AnimationData::AnimationData(AnimationData&&) noexcept = default; AnimationData::AnimationData(AnimationData&&) noexcept = default;

28
src/Magnum/Trade/AnimationData.h

@ -327,6 +327,13 @@ class MAGNUM_TRADE_EXPORT AnimationData {
*/ */
explicit AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState = nullptr) noexcept; explicit AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState = nullptr) noexcept;
/**
* @overload
* @m_since_latest
*/
/* Not noexcept because allocation happens inside */
explicit AnimationData(Containers::Array<char>&& data, std::initializer_list<AnimationTrackData> tracks, const void* importerState = nullptr);
/** /**
* @brief Construct a non-owned animation data * @brief Construct a non-owned animation data
* @param dataFlags Data flags * @param dataFlags Data flags
@ -344,6 +351,13 @@ class MAGNUM_TRADE_EXPORT AnimationData {
*/ */
explicit AnimationData(DataFlags dataFlags, Containers::ArrayView<const void> data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState = nullptr) noexcept; explicit AnimationData(DataFlags dataFlags, Containers::ArrayView<const void> data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState = nullptr) noexcept;
/**
* @overload
* @m_since_latest
*/
/* Not noexcept because allocation happens inside */
explicit AnimationData(DataFlags dataFlags, Containers::ArrayView<const void> data, std::initializer_list<AnimationTrackData> tracks, const void* importerState = nullptr);
/** /**
* @brief Construct an animation data with explicit duration * @brief Construct an animation data with explicit duration
* @param data Buffer containing all keyframe data for this * @param data Buffer containing all keyframe data for this
@ -362,6 +376,13 @@ class MAGNUM_TRADE_EXPORT AnimationData {
*/ */
explicit AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const Range1D& duration, const void* importerState = nullptr) noexcept; explicit AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const Range1D& duration, const void* importerState = nullptr) noexcept;
/**
* @overload
* @m_since_latest
*/
/* Not noexcept because allocation happens inside */
explicit AnimationData(Containers::Array<char>&& data, std::initializer_list<AnimationTrackData> tracks, const Range1D& duration, const void* importerState = nullptr);
/** /**
* @brief Construct a non-owned animation data with explicit duration * @brief Construct a non-owned animation data with explicit duration
* @param dataFlags Data flags * @param dataFlags Data flags
@ -380,6 +401,13 @@ class MAGNUM_TRADE_EXPORT AnimationData {
*/ */
explicit AnimationData(DataFlags dataFlags, Containers::ArrayView<const void> data, Containers::Array<AnimationTrackData>&& tracks, const Range1D& duration, const void* importerState = nullptr) noexcept; explicit AnimationData(DataFlags dataFlags, Containers::ArrayView<const void> data, Containers::Array<AnimationTrackData>&& tracks, const Range1D& duration, const void* importerState = nullptr) noexcept;
/**
* @overload
* @m_since_latest
*/
/* Not noexcept because allocation happens inside */
explicit AnimationData(DataFlags dataFlags, Containers::ArrayView<const void> data, std::initializer_list<AnimationTrackData> tracks, const Range1D& duration, const void* importerState = nullptr);
~AnimationData(); ~AnimationData();
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */

7
src/Magnum/Trade/Test/AbstractImporterTest.cpp

@ -1228,7 +1228,12 @@ void AbstractImporterTest::animation() {
else return {}; else return {};
} }
Containers::Optional<AnimationData> doAnimation(UnsignedInt id) override { Containers::Optional<AnimationData> doAnimation(UnsignedInt id) override {
if(id == 7) return AnimationData{{}, {}, &state}; /* Verify that initializer list is converted to an array with
the default deleter and not something disallowed */
if(id == 7) return AnimationData{nullptr, {
{AnimationTrackType::Vector3,
AnimationTrackTargetType::Scaling3D, 0, {}}
}, &state};
else return AnimationData{{}, {}}; else return AnimationData{{}, {}};
} }
} importer; } importer;

44
src/Magnum/Trade/Test/AnimationDataTest.cpp

@ -164,8 +164,6 @@ void AnimationDataTest::constructTrackDataDefault() {
} }
void AnimationDataTest::construct() { void AnimationDataTest::construct() {
/* Ain't the prettiest, but trust me: you won't do it like this in the
plugins anyway */
struct Data { struct Data {
Float time; Float time;
Vector3 position; Vector3 position;
@ -178,7 +176,7 @@ void AnimationDataTest::construct() {
view[2] = {7.5f, {1.0f, 0.3f, 2.1f}, Quaternion{}}; view[2] = {7.5f, {1.0f, 0.3f, 2.1f}, Quaternion{}};
const int state = 5; const int state = 5;
AnimationData data{std::move(buffer), Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{std::move(buffer), {
{AnimationTrackTargetType::Translation3D, 42, {AnimationTrackTargetType::Translation3D, 42,
Animation::TrackView<const Float, const Vector3>{ Animation::TrackView<const Float, const Vector3>{
{view, &view[0].time, view.size(), sizeof(Data)}, {view, &view[0].time, view.size(), sizeof(Data)},
@ -191,7 +189,7 @@ void AnimationDataTest::construct() {
{view, &view[0].rotation, view.size(), sizeof(Data)}, {view, &view[0].rotation, view.size(), sizeof(Data)},
Animation::Interpolation::Linear, Animation::Interpolation::Linear,
animationInterpolatorFor<Quaternion>(Animation::Interpolation::Linear)}} animationInterpolatorFor<Quaternion>(Animation::Interpolation::Linear)}}
}}, {-1.0f, 7.0f}, &state}; }, {-1.0f, 7.0f}, &state};
CORRADE_COMPARE(data.dataFlags(), DataFlag::Owned|DataFlag::Mutable); CORRADE_COMPARE(data.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(data.duration(), (Range1D{-1.0f, 7.0f})); CORRADE_COMPARE(data.duration(), (Range1D{-1.0f, 7.0f}));
@ -234,8 +232,6 @@ void AnimationDataTest::construct() {
} }
void AnimationDataTest::constructImplicitDuration() { void AnimationDataTest::constructImplicitDuration() {
/* Ain't the prettiest, but trust me: you won't do it like this in the
plugins anyway */
struct Data { struct Data {
Float time; Float time;
bool value; bool value;
@ -248,7 +244,7 @@ void AnimationDataTest::constructImplicitDuration() {
view[3] = {7.0f, false}; view[3] = {7.0f, false};
const int state = 5; const int state = 5;
AnimationData data{std::move(buffer), Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{std::move(buffer), {
{AnimationTrackTargetType(129), 0, {AnimationTrackTargetType(129), 0,
Animation::TrackView<const Float, const bool>{ Animation::TrackView<const Float, const bool>{
{view, &view[0].time, 2, sizeof(Data)}, {view, &view[0].time, 2, sizeof(Data)},
@ -259,7 +255,7 @@ void AnimationDataTest::constructImplicitDuration() {
{view, &view[2].time, 2, sizeof(Data)}, {view, &view[2].time, 2, sizeof(Data)},
{view, &view[2].value, 2, sizeof(Data)}, {view, &view[2].value, 2, sizeof(Data)},
Animation::Interpolation::Linear}} Animation::Interpolation::Linear}}
}}, &state}; }, &state};
CORRADE_COMPARE(data.dataFlags(), DataFlag::Owned|DataFlag::Mutable); CORRADE_COMPARE(data.dataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(data.duration(), (Range1D{1.0f, 7.0f})); CORRADE_COMPARE(data.duration(), (Range1D{1.0f, 7.0f}));
@ -316,13 +312,13 @@ void AnimationDataTest::constructNotOwned() {
}; };
const int state = 5; const int state = 5;
AnimationData data{instanceData.dataFlags, keyframes, Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{instanceData.dataFlags, keyframes, {
{AnimationTrackTargetType::Translation3D, 42, {AnimationTrackTargetType::Translation3D, 42,
Animation::TrackView<const Float, const Vector3>{ Animation::TrackView<const Float, const Vector3>{
keyframes, keyframes,
Animation::Interpolation::Constant, Animation::Interpolation::Constant,
animationInterpolatorFor<Vector3>(Animation::Interpolation::Constant)}} animationInterpolatorFor<Vector3>(Animation::Interpolation::Constant)}}
}}, {-1.0f, 7.0f}, &state}; }, {-1.0f, 7.0f}, &state};
CORRADE_COMPARE(data.dataFlags(), instanceData.dataFlags); CORRADE_COMPARE(data.dataFlags(), instanceData.dataFlags);
CORRADE_COMPARE(data.duration(), (Range1D{-1.0f, 7.0f})); CORRADE_COMPARE(data.duration(), (Range1D{-1.0f, 7.0f}));
@ -364,10 +360,10 @@ void AnimationDataTest::constructImplicitDurationNotOwned() {
}; };
const int state = 5; const int state = 5;
AnimationData data{instanceData.dataFlags, keyframes, Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{instanceData.dataFlags, keyframes, {
{AnimationTrackTargetType(129), 0, {AnimationTrackTargetType(129), 0,
Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}}, Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}},
}}, &state}; }, &state};
CORRADE_COMPARE(data.dataFlags(), instanceData.dataFlags); CORRADE_COMPARE(data.dataFlags(), instanceData.dataFlags);
CORRADE_COMPARE(data.duration(), (Range1D{1.0f, 5.0f})); CORRADE_COMPARE(data.duration(), (Range1D{1.0f, 5.0f}));
@ -436,7 +432,7 @@ void AnimationDataTest::constructMove() {
view[2] = {7.5f, {1.0f, 0.3f, 2.1f}, Quaternion{}}; view[2] = {7.5f, {1.0f, 0.3f, 2.1f}, Quaternion{}};
const int state = 5; const int state = 5;
AnimationData a{std::move(buffer), Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData a{std::move(buffer), {
{AnimationTrackTargetType::Translation3D, 42, {AnimationTrackTargetType::Translation3D, 42,
Animation::TrackView<const Float, const Vector3>{ Animation::TrackView<const Float, const Vector3>{
{view, &view[0].time, view.size(), sizeof(Data)}, {view, &view[0].time, view.size(), sizeof(Data)},
@ -449,7 +445,7 @@ void AnimationDataTest::constructMove() {
{view, &view[0].rotation, view.size(), sizeof(Data)}, {view, &view[0].rotation, view.size(), sizeof(Data)},
Animation::Interpolation::Linear, Animation::Interpolation::Linear,
animationInterpolatorFor<Quaternion>(Animation::Interpolation::Linear)}} animationInterpolatorFor<Quaternion>(Animation::Interpolation::Linear)}}
}}, {-1.0f, 7.0f}, &state}; }, {-1.0f, 7.0f}, &state};
AnimationData b{std::move(a)}; AnimationData b{std::move(a)};
@ -525,10 +521,10 @@ void AnimationDataTest::mutableAccessNotAllowed() {
{5.0f, false} {5.0f, false}
}; };
AnimationData data{{}, keyframes, Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{{}, keyframes, {
{AnimationTrackTargetType(129), 0, {AnimationTrackTargetType(129), 0,
Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}}, Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}},
}}}; }};
CORRADE_COMPARE(data.dataFlags(), DataFlags{}); CORRADE_COMPARE(data.dataFlags(), DataFlags{});
std::ostringstream out; std::ostringstream out;
@ -554,14 +550,14 @@ void AnimationDataTest::trackCustomResultType() {
view[0] = {0.0f, {300, 100, 10}}; view[0] = {0.0f, {300, 100, 10}};
view[1] = {5.0f, {30, 60, 100}}; view[1] = {5.0f, {30, 60, 100}};
AnimationData data{std::move(buffer), Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{std::move(buffer), {
{AnimationTrackTargetType::Scaling3D, 0, {AnimationTrackTargetType::Scaling3D, 0,
Animation::TrackView<const Float, const Vector3i, Vector3>{ Animation::TrackView<const Float, const Vector3i, Vector3>{
{view, &view[0].time, view.size(), sizeof(Data)}, {view, &view[0].time, view.size(), sizeof(Data)},
{view, &view[0].position, view.size(), sizeof(Data)}, {view, &view[0].position, view.size(), sizeof(Data)},
[](const Vector3i& a, const Vector3i& b, Float t) -> Vector3 { [](const Vector3i& a, const Vector3i& b, Float t) -> Vector3 {
return Math::lerp(Vector3{a}*0.01f, Vector3{b}*0.01f, t); return Math::lerp(Vector3{a}*0.01f, Vector3{b}*0.01f, t);
}}}} }}}
}}; }};
CORRADE_COMPARE((data.track<Vector3i, Vector3>(0).at(2.5f)), (Vector3{1.65f, 0.8f, 0.55f})); CORRADE_COMPARE((data.track<Vector3i, Vector3>(0).at(2.5f)), (Vector3{1.65f, 0.8f, 0.55f}));
@ -590,11 +586,11 @@ void AnimationDataTest::trackWrongType() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
AnimationData data{nullptr, Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{nullptr, {
{AnimationTrackType::Vector3i, {AnimationTrackType::Vector3i,
AnimationTrackType::Vector3, AnimationTrackType::Vector3,
AnimationTrackTargetType::Scaling3D, 0, {}} AnimationTrackTargetType::Scaling3D, 0, {}}
}}}; }};
data.track<Vector3>(0); data.track<Vector3>(0);
@ -605,11 +601,11 @@ void AnimationDataTest::trackWrongResultType() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
AnimationData data{nullptr, Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{nullptr, {
{AnimationTrackType::Vector3i, {AnimationTrackType::Vector3i,
AnimationTrackType::Vector3, AnimationTrackType::Vector3,
AnimationTrackTargetType::Scaling3D, 0, {}} AnimationTrackTargetType::Scaling3D, 0, {}}
}}}; }};
data.track<Vector3i, Vector2>(0); data.track<Vector3i, Vector2>(0);
@ -622,10 +618,10 @@ void AnimationDataTest::release() {
{5.0f, false} {5.0f, false}
}; };
AnimationData data{{}, keyframes, Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { AnimationData data{{}, keyframes, {
{AnimationTrackTargetType(129), 0, {AnimationTrackTargetType(129), 0,
Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}}, Animation::TrackView<const Float, const bool>{keyframes, Animation::Interpolation::Constant}},
}}}; }};
CORRADE_COMPARE(data.trackCount(), 1); CORRADE_COMPARE(data.trackCount(), 1);
Containers::Array<char> released = data.release(); Containers::Array<char> released = data.release();

Loading…
Cancel
Save