mirror of https://github.com/mosra/magnum.git
6 changed files with 863 additions and 0 deletions
@ -0,0 +1,141 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
||||
Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include "AnimationData.h" |
||||
|
||||
#include <Corrade/Utility/Debug.h> |
||||
|
||||
#include "Magnum/Math/Vector4.h" |
||||
#include "Magnum/Math/Quaternion.h" |
||||
|
||||
namespace Magnum { namespace Trade { |
||||
|
||||
AnimationData::AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState) noexcept: _data{std::move(data)}, _tracks{std::move(tracks)}, _importerState{importerState} {} |
||||
|
||||
AnimationData::~AnimationData() = default; |
||||
|
||||
AnimationData::AnimationData(AnimationData&&) noexcept = default; |
||||
|
||||
AnimationData& AnimationData::operator=(AnimationData&&) noexcept = default; |
||||
|
||||
AnimationTrackType AnimationData::trackType(UnsignedInt id) const { |
||||
CORRADE_ASSERT(id < _tracks.size(), "Trade::AnimationData::trackType(): index out of range", {}); |
||||
return _tracks[id]._type; |
||||
} |
||||
|
||||
AnimationTrackType AnimationData::trackResultType(UnsignedInt id) const { |
||||
CORRADE_ASSERT(id < _tracks.size(), "Trade::AnimationData::trackResultType(): index out of range", {}); |
||||
return _tracks[id]._resultType; |
||||
} |
||||
|
||||
AnimationTrackTarget AnimationData::trackTarget(UnsignedInt id) const { |
||||
CORRADE_ASSERT(id < _tracks.size(), "Trade::AnimationData::trackTarget(): index out of range", {}); |
||||
return _tracks[id]._target; |
||||
} |
||||
|
||||
UnsignedInt AnimationData::trackTargetId(UnsignedInt id) const { |
||||
CORRADE_ASSERT(id < _tracks.size(), "Trade::AnimationData::trackTargetId(): index out of range", {}); |
||||
return _tracks[id]._targetId; |
||||
} |
||||
|
||||
template<class V, class R> auto animationInterpolatorFor(Animation::Interpolation interpolation) -> R(*)(const V&, const V&, Float) { |
||||
return Animation::interpolatorFor<V, R>(interpolation); |
||||
} |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<bool, bool>(Animation::Interpolation) -> bool(*)(const bool&, const bool&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Float, Float>(Animation::Interpolation) -> Float(*)(const Float&, const Float&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<UnsignedInt, UnsignedInt>(Animation::Interpolation) -> UnsignedInt(*)(const UnsignedInt&, const UnsignedInt&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Int, Int>(Animation::Interpolation) -> Int(*)(const Int&, const Int&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BoolVector<2>, Math::BoolVector<2>>(Animation::Interpolation) -> Math::BoolVector<2>(*)(const Math::BoolVector<2>&, const Math::BoolVector<2>&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BoolVector<3>, Math::BoolVector<3>>(Animation::Interpolation) -> Math::BoolVector<3>(*)(const Math::BoolVector<3>&, const Math::BoolVector<3>&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Math::BoolVector<4>, Math::BoolVector<4>>(Animation::Interpolation) -> Math::BoolVector<4>(*)(const Math::BoolVector<4>&, const Math::BoolVector<4>&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2, Vector2>(Animation::Interpolation) -> Vector2(*)(const Vector2&, const Vector2&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2i, Vector2i>(Animation::Interpolation) -> Vector2i(*)(const Vector2i&, const Vector2i&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector2ui, Vector2ui>(Animation::Interpolation) -> Vector2ui(*)(const Vector2ui&, const Vector2ui&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector3, Vector3>(Animation::Interpolation) -> Vector3(*)(const Vector3&, const Vector3&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector3i, Vector3i>(Animation::Interpolation) -> Vector3i(*)(const Vector3i&, const Vector3i&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector3ui, Vector3ui>(Animation::Interpolation) -> Vector3ui(*)(const Vector3ui&, const Vector3ui&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector4, Vector4>(Animation::Interpolation) -> Vector4(*)(const Vector4&, const Vector4&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector4d, Vector4d>(Animation::Interpolation) -> Vector4d(*)(const Vector4d&, const Vector4d&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector4i, Vector4i>(Animation::Interpolation) -> Vector4i(*)(const Vector4i&, const Vector4i&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Vector4ui, Vector4ui>(Animation::Interpolation) -> Vector4ui(*)(const Vector4ui&, const Vector4ui&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<Quaternion, Quaternion>(Animation::Interpolation) -> Quaternion(*)(const Quaternion&, const Quaternion&, Float); |
||||
template MAGNUM_TRADE_EXPORT auto animationInterpolatorFor<DualQuaternion, DualQuaternion>(Animation::Interpolation) -> DualQuaternion(*)(const DualQuaternion&, const DualQuaternion&, Float); |
||||
|
||||
Debug& operator<<(Debug& debug, const AnimationTrackType value) { |
||||
switch(value) { |
||||
/* LCOV_EXCL_START */ |
||||
#define _c(value) case AnimationTrackType::value: return debug << "Trade::AnimationTrackType::" #value; |
||||
_c(Bool) |
||||
_c(Float) |
||||
_c(UnsignedInt) |
||||
_c(Int) |
||||
_c(BoolVector2) |
||||
_c(BoolVector3) |
||||
_c(BoolVector4) |
||||
_c(Vector2) |
||||
_c(Vector2ui) |
||||
_c(Vector2i) |
||||
_c(Vector3) |
||||
_c(Vector3ui) |
||||
_c(Vector3i) |
||||
_c(Vector4) |
||||
_c(Vector4ui) |
||||
_c(Vector4i) |
||||
_c(Quaternion) |
||||
_c(DualQuaternion) |
||||
#undef _c |
||||
/* LCOV_EXCL_STOP */ |
||||
} |
||||
|
||||
return debug << "Trade::AnimationTrackType(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")"; |
||||
} |
||||
|
||||
Debug& operator<<(Debug& debug, const AnimationTrackTarget value) { |
||||
if(UnsignedByte(value) >= UnsignedByte(AnimationTrackTarget::Custom)) |
||||
return debug << "Trade::AnimationTrackTarget::Custom(" << Debug::nospace << UnsignedByte(value) << Debug::nospace << ")"; |
||||
|
||||
switch(value) { |
||||
/* LCOV_EXCL_START */ |
||||
#define _c(value) case AnimationTrackTarget::value: return debug << "Trade::AnimationTrackTarget::" #value; |
||||
_c(Translation2D) |
||||
_c(Translation3D) |
||||
_c(Rotation2D) |
||||
_c(Rotation3D) |
||||
_c(Scaling2D) |
||||
_c(Scaling3D) |
||||
#undef _c |
||||
/* LCOV_EXCL_STOP */ |
||||
|
||||
/* To silence compiler warning about unhandled values */ |
||||
case AnimationTrackTarget::Custom: CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ |
||||
} |
||||
|
||||
return debug << "Trade::AnimationTrackTarget(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")"; |
||||
} |
||||
#endif |
||||
|
||||
}} |
||||
@ -0,0 +1,386 @@
|
||||
#ifndef Magnum_Trade_AnimationData_h |
||||
#define Magnum_Trade_AnimationData_h |
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
||||
Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class @ref Magnum::Trade::AnimationTrackData, @ref Magnum::Trade::AnimationData, enum @ref Magnum::Trade::AnimationTrackType, @ref Magnum::Trade::AnimationTrackTarget, function @ref Magnum::Trade::animationInterpolatorFor() |
||||
*/ |
||||
|
||||
#include "Magnum/Magnum.h" |
||||
#include "Magnum/Math/Math.h" |
||||
#include "Magnum/Animation/Track.h" |
||||
#include "Magnum/Trade/Trade.h" |
||||
#include "Magnum/Trade/visibility.h" |
||||
|
||||
namespace Magnum { namespace Trade { |
||||
|
||||
/**
|
||||
@brief Type of animation track data |
||||
|
||||
@see @ref AnimationData |
||||
@experimental |
||||
*/ |
||||
enum class AnimationTrackType: UnsignedByte { |
||||
Bool, /**< @cpp bool @ce <b></b> */ |
||||
Float, /**< @ref Magnum::Float "Float" */ |
||||
UnsignedInt, /**< @ref Magnum::UnsignedInt "UnsignedInt" */ |
||||
Int, /**< @ref Magnum::Int "Int" */ |
||||
BoolVector2, /**< @ref Math::BoolVector "Math::BoolVector<2>" */ |
||||
BoolVector3, /**< @ref Math::BoolVector "Math::BoolVector<3>" */ |
||||
BoolVector4, /**< @ref Math::BoolVector "Math::BoolVector<4>" */ |
||||
|
||||
/**
|
||||
* @ref Magnum::Vector2 "Vector2". Usually used for |
||||
* @ref AnimationTrackTarget::Translation2D and |
||||
* @ref AnimationTrackTarget::Scaling2D. |
||||
*/ |
||||
Vector2, |
||||
|
||||
Vector2ui, /**< @ref Magnum::Vector2ui "Vector2ui" */ |
||||
Vector2i, /**< @ref Magnum::Vector2i "Vector2i" */ |
||||
|
||||
/**
|
||||
* @ref Magnum::Vector3 "Vector3". Usually used for |
||||
* @ref AnimationTrackTarget::Translation3D and |
||||
* @ref AnimationTrackTarget::Scaling3D. |
||||
*/ |
||||
Vector3, |
||||
|
||||
Vector3ui, /**< @ref Magnum::Vector3ui "Vector3ui" */ |
||||
Vector3i, /**< @ref Magnum::Vector3i "Vector3i" */ |
||||
Vector4, /**< @ref Magnum::Vector4 "Vector4" */ |
||||
Vector4ui, /**< @ref Magnum::Vector4ui "Vector4ui" */ |
||||
Vector4i, /**< @ref Magnum::Vector4i "Vector4i" */ |
||||
|
||||
/**
|
||||
* @ref Magnum::Quaternion "Quaternion". Usually used for |
||||
* @ref AnimationTrackTarget::Rotation3D. |
||||
*/ |
||||
Quaternion, |
||||
|
||||
DualQuaternion /**< @ref Magnum::DualQuaternion "DualQuaternion" */ |
||||
}; |
||||
|
||||
/** @debugoperatorenum{AnimationTrackType} */ |
||||
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, AnimationTrackType value); |
||||
|
||||
/**
|
||||
@brief Target of an animation track |
||||
|
||||
@see @ref AnimationData |
||||
@experimental |
||||
*/ |
||||
enum class AnimationTrackTarget: UnsignedByte { |
||||
/**
|
||||
* Modifies 2D object translation. Type is usually |
||||
* @ref Magnum::Vector2 "Vector2". |
||||
* |
||||
* @see @ref AnimationTrackType::Vector2, @ref ObjectData2D::translation() |
||||
*/ |
||||
Translation2D, |
||||
|
||||
/**
|
||||
* Modifies 3D object translation. Type is usually |
||||
* @ref Magnum::Vector3 "Vector3". |
||||
* |
||||
* @see @ref AnimationTrackType::Vector3, @ref ObjectData3D::translation() |
||||
*/ |
||||
Translation3D, |
||||
|
||||
/**
|
||||
* Modifies 2D object rotation. Type is usually |
||||
* @ref Magnum::Complex "Complex". |
||||
* |
||||
* @see @ref ObjectData2D::rotation() |
||||
*/ |
||||
Rotation2D, |
||||
|
||||
/**
|
||||
* Modifies 3D object rotation. Type is usually |
||||
* @ref Magnum::Quaternion "Quaternion". |
||||
* |
||||
* @see @ref AnimationTrackType::Quaternion, @ref ObjectData3D::rotation() |
||||
*/ |
||||
Rotation3D, |
||||
|
||||
/**
|
||||
* Modifies 2D object scaling. Type is usually |
||||
* @ref Magnum::Vector2 "Vector2". |
||||
* |
||||
* @see @ref AnimationTrackType::Vector2, @ref ObjectData2D::scaling() |
||||
*/ |
||||
Scaling2D, |
||||
|
||||
/**
|
||||
* Modifies 3D object scaling. Type is usually |
||||
* @ref Magnum::Vector3 "Vector3". |
||||
* |
||||
* @see @ref AnimationTrackType::Vector3, @ref ObjectData3D::scaling() |
||||
*/ |
||||
Scaling3D, |
||||
|
||||
/**
|
||||
* This and all higher values are for importer-specific targets. Can be of |
||||
* any type, @ref AnimationData::trackTargetId() might or might not point |
||||
* to an existing object. See documentation of particular importer for |
||||
* details. |
||||
*/ |
||||
Custom = 128 |
||||
}; |
||||
|
||||
/** @debugoperatorenum{AnimationTrackTarget} */ |
||||
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, AnimationTrackTarget value); |
||||
|
||||
/**
|
||||
@brief Animation track data |
||||
|
||||
Used when constructing @ref AnimationData. Fields can be accessed through its |
||||
API. |
||||
@experimental |
||||
*/ |
||||
class AnimationTrackData { |
||||
public: |
||||
/**
|
||||
* @brief Constructor |
||||
* @param type Value type |
||||
* @param resultType Result type |
||||
* @param target Track target |
||||
* @param targetId Track target ID |
||||
* @param view Type-erased @ref Animation::TrackView instance |
||||
*/ |
||||
/*implicit*/ AnimationTrackData(AnimationTrackType type, AnimationTrackType resultType, AnimationTrackTarget target, UnsignedInt targetId, Animation::TrackViewStorage view) noexcept: _type{type}, _resultType{resultType}, _target{target}, _targetId{targetId}, _view{view} {} |
||||
|
||||
/** @overload
|
||||
* |
||||
* Equivalent to the above with @p type used as both value type and |
||||
* result type. |
||||
*/ |
||||
/*implicit*/ AnimationTrackData(AnimationTrackType type, AnimationTrackTarget target, UnsignedInt targetId, Animation::TrackViewStorage view) noexcept: _type{type}, _resultType{type}, _target{target}, _targetId{targetId}, _view{view} {} |
||||
|
||||
private: |
||||
friend AnimationData; |
||||
|
||||
AnimationTrackType _type, _resultType; |
||||
AnimationTrackTarget _target; |
||||
UnsignedInt _targetId; |
||||
Animation::TrackViewStorage _view; |
||||
}; |
||||
|
||||
/**
|
||||
@brief Animation clip data |
||||
|
||||
@see @ref AbstractImporter::animation() |
||||
@experimental |
||||
*/ |
||||
class MAGNUM_TRADE_EXPORT AnimationData { |
||||
public: |
||||
/**
|
||||
* @brief Constructor |
||||
* @param data Buffer containing all keyframe data for this |
||||
* animation clip |
||||
* @param tracks Track data |
||||
* @param importerState Importer-specific state |
||||
* |
||||
* Each item of @p track should have an @ref Animation::TrackView |
||||
* instance pointing its key/value views to @p data. |
||||
*/ |
||||
explicit AnimationData(Containers::Array<char>&& data, Containers::Array<AnimationTrackData>&& tracks, const void* importerState = nullptr) noexcept; |
||||
|
||||
~AnimationData(); |
||||
|
||||
/** @brief Copying is not allowed */ |
||||
AnimationData(const AnimationData&) = delete; |
||||
|
||||
/** @brief Move constructor */ |
||||
AnimationData(AnimationData&&) noexcept; |
||||
|
||||
/** @brief Copying is not allowed */ |
||||
AnimationData& operator=(const AnimationData&) = delete; |
||||
|
||||
/** @brief Move assignment */ |
||||
AnimationData& operator=(AnimationData&&) noexcept; |
||||
|
||||
/**
|
||||
* @brief Raw data |
||||
* |
||||
* Contains data for all tracks contained in this clip. |
||||
* @see @ref release() |
||||
*/ |
||||
Containers::ArrayView<char> data() |
||||
#ifndef CORRADE_GCC47_COMPATIBILITY |
||||
& |
||||
#endif |
||||
{ return _data; } |
||||
#ifndef CORRADE_GCC47_COMPATIBILITY |
||||
Containers::ArrayView<char> data() && = delete; /**< @overload */ |
||||
#endif |
||||
|
||||
/** @overload */ |
||||
Containers::ArrayView<const char> data() const |
||||
#ifndef CORRADE_GCC47_COMPATIBILITY |
||||
& |
||||
#endif |
||||
{ return _data; } |
||||
#ifndef CORRADE_GCC47_COMPATIBILITY |
||||
Containers::ArrayView<const char> data() const && = delete; /**< @overload */ |
||||
#endif |
||||
|
||||
/** @brief Track count */ |
||||
UnsignedInt trackCount() const { return _tracks.size(); } |
||||
|
||||
/**
|
||||
* @brief Track value type |
||||
* @param id Track index |
||||
* |
||||
* Data types are usually closely related to @ref trackTarget(), see |
||||
* @ref AnimationTrackTarget documentation for more information. |
||||
* @see @ref trackCount() |
||||
*/ |
||||
AnimationTrackType trackType(UnsignedInt id) const; |
||||
|
||||
/**
|
||||
* @brief Track result type |
||||
* @param id Track index |
||||
* |
||||
* In case track values are packed, track result type is different from |
||||
* @ref trackType(). Data types are usually closely related to |
||||
* @ref trackTarget(), see @ref AnimationTrackTarget documentation for |
||||
* more information. |
||||
* @see @ref trackCount() |
||||
*/ |
||||
AnimationTrackType trackResultType(UnsignedInt id) const; |
||||
|
||||
/**
|
||||
* @brief Track target |
||||
* @param id Track index |
||||
* |
||||
* Particular animation targets usually correspond to a common |
||||
* @ref trackType(), see @ref AnimationTrackTarget documentation for |
||||
* more information. |
||||
* @see @ref trackCount() |
||||
*/ |
||||
AnimationTrackTarget trackTarget(UnsignedInt id) const; |
||||
|
||||
/**
|
||||
* @brief Track target index |
||||
* @param id Track index |
||||
* |
||||
* For @ref trackTarget() with @ref AnimationTrackTarget::Translation2D, |
||||
* @ref AnimationTrackTarget::Translation3D, |
||||
* @ref AnimationTrackTarget::Rotation2D, |
||||
* @ref AnimationTrackTarget::Rotation3D, |
||||
* @ref AnimationTrackTarget::Scaling2D, |
||||
* @ref AnimationTrackTarget::Scaling3D specifies object which property |
||||
* is modified. |
||||
* @see @ref trackCount(), @ref AbstractImporter::object2D(), |
||||
* @ref AbstractImporter::object3D() |
||||
*/ |
||||
UnsignedInt trackTargetId(UnsignedInt id) const; |
||||
|
||||
/**
|
||||
* @brief Track data |
||||
* @tparam V Track value type |
||||
* @tparam R Track result type |
||||
* |
||||
* Expects that requested types are correct for given @ref trackType() |
||||
* and @ref trackResultType(). Note that the returned view is onto |
||||
* @ref data(), meaning you either need to ensure that the |
||||
* @cpp AnimationData @ce instance stays in scope for as long as you |
||||
* use the view or you need to release the data array using |
||||
* @ref release() and manage its lifetime yourself. |
||||
*/ |
||||
template<class V, class R = Animation::ResultOf<V>> Animation::TrackView<Float, V, R> track(UnsignedInt id) const; |
||||
|
||||
/**
|
||||
* @brief Release data storage |
||||
* |
||||
* Releases the ownership of the data array and resets internal state |
||||
* to default. |
||||
* @see @ref data() |
||||
*/ |
||||
Containers::Array<char> release() { return std::move(_data); } |
||||
|
||||
/**
|
||||
* @brief Importer-specific state |
||||
* |
||||
* See @ref AbstractImporter::importerState() for more information. |
||||
*/ |
||||
const void* importerState() const { return _importerState; } |
||||
|
||||
private: |
||||
Containers::Array<char> _data; |
||||
Containers::Array<AnimationTrackData> _tracks; |
||||
const void* _importerState; |
||||
}; |
||||
|
||||
/** @relatesalso AnimationData
|
||||
@brief Animation interpolator function for given interpolation behavior |
||||
|
||||
To be used from importer plugins --- unlike @ref Animation::interpolatorFor() |
||||
guarantees that the returned function pointer is not instantiated inside plugin |
||||
binary to avoid dangling function pointers on plugin unload. See |
||||
@ref Animation::interpolatorFor() for more information. |
||||
@see @ref AnimationData |
||||
@experimental |
||||
*/ |
||||
template<class V, class R = Animation::ResultOf<V>> MAGNUM_TRADE_EXPORT auto animationInterpolatorFor(Animation::Interpolation interpolation) -> R(*)(const V&, const V&, Float); |
||||
|
||||
#if !defined(CORRADE_NO_ASSERT) || defined(CORRADE_GRACEFUL_ASSERT) |
||||
namespace Implementation { |
||||
/* LCOV_EXCL_START */ |
||||
template<class T> AnimationTrackType animationTypeFor(); |
||||
template<> constexpr AnimationTrackType animationTypeFor<bool>() { return AnimationTrackType::Bool; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Float>() { return AnimationTrackType::Float; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<UnsignedInt>() { return AnimationTrackType::UnsignedInt; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Int>() { return AnimationTrackType::Int; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Math::BoolVector<2>>() { return AnimationTrackType::BoolVector2; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Math::BoolVector<3>>() { return AnimationTrackType::BoolVector3; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Math::BoolVector<4>>() { return AnimationTrackType::BoolVector4; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector2>() { return AnimationTrackType::Vector2; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector2ui>() { return AnimationTrackType::Vector2ui; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector2i>() { return AnimationTrackType::Vector2i; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector3>() { return AnimationTrackType::Vector3; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector3ui>() { return AnimationTrackType::Vector3ui; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector3i>() { return AnimationTrackType::Vector3i; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector4>() { return AnimationTrackType::Vector4; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector4ui>() { return AnimationTrackType::Vector4ui; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Vector4i>() { return AnimationTrackType::Vector4i; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<Quaternion>() { return AnimationTrackType::Quaternion; } |
||||
template<> constexpr AnimationTrackType animationTypeFor<DualQuaternion>() { return AnimationTrackType::DualQuaternion; } |
||||
/* LCOV_EXCL_STOP */ |
||||
} |
||||
#endif |
||||
|
||||
template<class V, class R> Animation::TrackView<Float, V, R> AnimationData::track(UnsignedInt id) const { |
||||
CORRADE_ASSERT(id < _tracks.size(), "Trade::AnimationData::track(): index out of range", (Animation::TrackView<Float, V, R>{})); |
||||
CORRADE_ASSERT(Implementation::animationTypeFor<V>() == _tracks[id]._type, "Trade::AnimationData::track(): improper type requested for" << _tracks[id]._type, (Animation::TrackView<Float, V, R>{})); |
||||
CORRADE_ASSERT(Implementation::animationTypeFor<R>() == _tracks[id]._resultType, "Trade::AnimationData::track(): improper result type requested for" << _tracks[id]._resultType, (Animation::TrackView<Float, V, R>{})); |
||||
return static_cast<const Animation::TrackView<Float, V, R>&>(_tracks[id]._view); |
||||
} |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,320 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
||||
Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include <sstream> |
||||
#include <Corrade/TestSuite/Tester.h> |
||||
|
||||
#include "Magnum/Math/Quaternion.h" |
||||
#include "Magnum/Trade/AnimationData.h" |
||||
|
||||
namespace Magnum { namespace Trade { namespace Test { |
||||
|
||||
struct AnimationDataTest: TestSuite::Tester { |
||||
explicit AnimationDataTest(); |
||||
|
||||
void construct(); |
||||
void constructCopy(); |
||||
void constructMove(); |
||||
|
||||
void trackCustomResultType(); |
||||
|
||||
void trackWrongIndex(); |
||||
void trackWrongType(); |
||||
void trackWrongResultType(); |
||||
|
||||
void debugAnimationTrackType(); |
||||
void debugAnimationTrackTarget(); |
||||
}; |
||||
|
||||
AnimationDataTest::AnimationDataTest() { |
||||
addTests({&AnimationDataTest::construct, |
||||
&AnimationDataTest::constructCopy, |
||||
&AnimationDataTest::constructMove, |
||||
|
||||
&AnimationDataTest::trackCustomResultType, |
||||
|
||||
&AnimationDataTest::trackWrongIndex, |
||||
&AnimationDataTest::trackWrongType, |
||||
&AnimationDataTest::trackWrongResultType, |
||||
|
||||
&AnimationDataTest::debugAnimationTrackType, |
||||
&AnimationDataTest::debugAnimationTrackTarget}); |
||||
} |
||||
|
||||
using namespace Math::Literals; |
||||
|
||||
void AnimationDataTest::construct() { |
||||
/* Ain't the prettiest, but trust me: you won't do it like this in the
|
||||
plugins anyway */ |
||||
struct Data { |
||||
Float time; |
||||
Vector3 position; |
||||
Quaternion rotation; |
||||
}; |
||||
Containers::Array<char> buffer{sizeof(Data)*3}; |
||||
auto view = Containers::arrayCast<Data>(buffer); |
||||
view[0] = {0.0f, {3.0f, 1.0f, 0.1f}, Quaternion::rotation(45.0_degf, Vector3::yAxis())}; |
||||
view[1] = {5.0f, {0.3f, 0.6f, 1.0f}, Quaternion::rotation(20.0_degf, Vector3::yAxis())}; |
||||
view[2] = {7.5f, {1.0f, 0.3f, 2.1f}, Quaternion{}}; |
||||
|
||||
const int state = 5; |
||||
AnimationData data{std::move(buffer), Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { |
||||
{AnimationTrackType::Vector3, |
||||
AnimationTrackTarget::Translation3D, 42, |
||||
Animation::TrackView<Float, Vector3>{ |
||||
{&view[0].time, view.size(), sizeof(Data)}, |
||||
{&view[0].position, view.size(), sizeof(Data)}, |
||||
Animation::Interpolation::Constant, |
||||
animationInterpolatorFor<Vector3>(Animation::Interpolation::Constant)}}, |
||||
{AnimationTrackType::Quaternion, |
||||
AnimationTrackTarget::Rotation3D, 1337, |
||||
Animation::TrackView<Float, Quaternion>{ |
||||
{&view[0].time, view.size(), sizeof(Data)}, |
||||
{&view[0].rotation, view.size(), sizeof(Data)}, |
||||
Animation::Interpolation::Linear, |
||||
animationInterpolatorFor<Quaternion>(Animation::Interpolation::Linear)}} |
||||
}}, &state}; |
||||
|
||||
CORRADE_COMPARE(data.data().size(), sizeof(Data)*3); |
||||
CORRADE_COMPARE(data.trackCount(), 2); |
||||
CORRADE_COMPARE(data.importerState(), &state); |
||||
|
||||
{ |
||||
CORRADE_COMPARE(data.trackType(0), AnimationTrackType::Vector3); |
||||
CORRADE_COMPARE(data.trackResultType(0), AnimationTrackType::Vector3); |
||||
CORRADE_COMPARE(data.trackTarget(0), AnimationTrackTarget::Translation3D); |
||||
CORRADE_COMPARE(data.trackTargetId(0), 42); |
||||
|
||||
Animation::TrackView<Float, Vector3> track = data.track<Vector3>(0); |
||||
CORRADE_COMPARE(track.keys().size(), 3); |
||||
CORRADE_COMPARE(track.values().size(), 3); |
||||
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant); |
||||
CORRADE_COMPARE(track.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f})); |
||||
} { |
||||
CORRADE_COMPARE(data.trackType(1), AnimationTrackType::Quaternion); |
||||
CORRADE_COMPARE(data.trackResultType(1), AnimationTrackType::Quaternion); |
||||
CORRADE_COMPARE(data.trackTarget(1), AnimationTrackTarget::Rotation3D); |
||||
CORRADE_COMPARE(data.trackTargetId(1), 1337); |
||||
|
||||
Animation::TrackView<Float, Quaternion> track = data.track<Quaternion>(1); |
||||
CORRADE_COMPARE(track.keys().size(), 3); |
||||
CORRADE_COMPARE(track.values().size(), 3); |
||||
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Linear); |
||||
CORRADE_COMPARE(track.at(2.5f), Quaternion::rotation(32.5_degf, Vector3::yAxis())); |
||||
} |
||||
} |
||||
|
||||
void AnimationDataTest::constructCopy() { |
||||
CORRADE_VERIFY(!(std::is_constructible<AnimationData, const AnimationData&>{})); |
||||
CORRADE_VERIFY(!(std::is_assignable<AnimationData, const AnimationData&>{})); |
||||
} |
||||
|
||||
void AnimationDataTest::constructMove() { |
||||
/* Ugh and here we go again! */ |
||||
struct Data { |
||||
Float time; |
||||
Vector3 position; |
||||
Quaternion rotation; |
||||
}; |
||||
Containers::Array<char> buffer{sizeof(Data)*3}; |
||||
auto view = Containers::arrayCast<Data>(buffer); |
||||
view[0] = {0.0f, {3.0f, 1.0f, 0.1f}, Quaternion::rotation(45.0_degf, Vector3::yAxis())}; |
||||
view[1] = {5.0f, {0.3f, 0.6f, 1.0f}, Quaternion::rotation(20.0_degf, Vector3::yAxis())}; |
||||
view[2] = {7.5f, {1.0f, 0.3f, 2.1f}, Quaternion{}}; |
||||
|
||||
const int state = 5; |
||||
AnimationData a{std::move(buffer), Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { |
||||
{AnimationTrackType::Vector3, |
||||
AnimationTrackTarget::Translation3D, 42, |
||||
Animation::TrackView<Float, Vector3>{ |
||||
{&view[0].time, view.size(), sizeof(Data)}, |
||||
{&view[0].position, view.size(), sizeof(Data)}, |
||||
Animation::Interpolation::Constant, |
||||
animationInterpolatorFor<Vector3>(Animation::Interpolation::Constant)}}, |
||||
{AnimationTrackType::Quaternion, |
||||
AnimationTrackTarget::Rotation3D, 1337, |
||||
Animation::TrackView<Float, Quaternion>{ |
||||
{&view[0].time, view.size(), sizeof(Data)}, |
||||
{&view[0].rotation, view.size(), sizeof(Data)}, |
||||
Animation::Interpolation::Linear, |
||||
animationInterpolatorFor<Quaternion>(Animation::Interpolation::Linear)}} |
||||
}}, &state}; |
||||
|
||||
AnimationData b{std::move(a)}; |
||||
|
||||
CORRADE_COMPARE(b.data().size(), sizeof(Data)*3); |
||||
CORRADE_COMPARE(b.trackCount(), 2); |
||||
CORRADE_COMPARE(b.importerState(), &state); |
||||
|
||||
{ |
||||
CORRADE_COMPARE(b.trackType(0), AnimationTrackType::Vector3); |
||||
CORRADE_COMPARE(b.trackResultType(0), AnimationTrackType::Vector3); |
||||
CORRADE_COMPARE(b.trackTarget(0), AnimationTrackTarget::Translation3D); |
||||
CORRADE_COMPARE(b.trackTargetId(0), 42); |
||||
|
||||
Animation::TrackView<Float, Vector3> track = b.track<Vector3>(0); |
||||
CORRADE_COMPARE(track.keys().size(), 3); |
||||
CORRADE_COMPARE(track.values().size(), 3); |
||||
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant); |
||||
CORRADE_COMPARE(track.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f})); |
||||
} { |
||||
CORRADE_COMPARE(b.trackType(1), AnimationTrackType::Quaternion); |
||||
CORRADE_COMPARE(b.trackResultType(1), AnimationTrackType::Quaternion); |
||||
CORRADE_COMPARE(b.trackTarget(1), AnimationTrackTarget::Rotation3D); |
||||
CORRADE_COMPARE(b.trackTargetId(1), 1337); |
||||
|
||||
Animation::TrackView<Float, Quaternion> track = b.track<Quaternion>(1); |
||||
CORRADE_COMPARE(track.keys().size(), 3); |
||||
CORRADE_COMPARE(track.values().size(), 3); |
||||
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Linear); |
||||
CORRADE_COMPARE(track.at(2.5f), Quaternion::rotation(32.5_degf, Vector3::yAxis())); |
||||
} |
||||
|
||||
int other; |
||||
AnimationData c{nullptr, nullptr, &other}; |
||||
c = std::move(b); |
||||
|
||||
CORRADE_COMPARE(c.data().size(), sizeof(Data)*3); |
||||
CORRADE_COMPARE(c.trackCount(), 2); |
||||
CORRADE_COMPARE(c.importerState(), &state); |
||||
|
||||
{ |
||||
CORRADE_COMPARE(c.trackType(0), AnimationTrackType::Vector3); |
||||
CORRADE_COMPARE(c.trackResultType(0), AnimationTrackType::Vector3); |
||||
CORRADE_COMPARE(c.trackTarget(0), AnimationTrackTarget::Translation3D); |
||||
CORRADE_COMPARE(c.trackTargetId(0), 42); |
||||
|
||||
Animation::TrackView<Float, Vector3> track = c.track<Vector3>(0); |
||||
CORRADE_COMPARE(track.keys().size(), 3); |
||||
CORRADE_COMPARE(track.values().size(), 3); |
||||
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Constant); |
||||
CORRADE_COMPARE(track.at(2.5f), (Vector3{3.0f, 1.0f, 0.1f})); |
||||
} { |
||||
CORRADE_COMPARE(c.trackType(1), AnimationTrackType::Quaternion); |
||||
CORRADE_COMPARE(c.trackResultType(1), AnimationTrackType::Quaternion); |
||||
CORRADE_COMPARE(c.trackTarget(1), AnimationTrackTarget::Rotation3D); |
||||
CORRADE_COMPARE(c.trackTargetId(1), 1337); |
||||
|
||||
Animation::TrackView<Float, Quaternion> track = c.track<Quaternion>(1); |
||||
CORRADE_COMPARE(track.keys().size(), 3); |
||||
CORRADE_COMPARE(track.values().size(), 3); |
||||
CORRADE_COMPARE(track.interpolation(), Animation::Interpolation::Linear); |
||||
CORRADE_COMPARE(track.at(2.5f), Quaternion::rotation(32.5_degf, Vector3::yAxis())); |
||||
} |
||||
} |
||||
|
||||
void AnimationDataTest::trackCustomResultType() { |
||||
using namespace Math::Literals; |
||||
|
||||
struct Data { |
||||
Float time; |
||||
Vector3i position; |
||||
}; |
||||
Containers::Array<char> buffer{sizeof(Data)*3}; |
||||
auto view = Containers::arrayCast<Data>(buffer); |
||||
view[0] = {0.0f, {300, 100, 10}}; |
||||
view[1] = {5.0f, {30, 60, 100}}; |
||||
|
||||
AnimationData data{std::move(buffer), Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { |
||||
{AnimationTrackType::Vector3i, |
||||
AnimationTrackType::Vector3, |
||||
AnimationTrackTarget::Scaling3D, 0, |
||||
Animation::TrackView<Float, Vector3i, Vector3>{ |
||||
{&view[0].time, view.size(), sizeof(Data)}, |
||||
{&view[0].position, view.size(), sizeof(Data)}, |
||||
[](const Vector3i& a, const Vector3i& b, Float t) -> Vector3 { |
||||
return Math::lerp(Vector3{a}*0.01f, Vector3{b}*0.01f, t); |
||||
}}}} |
||||
}}; |
||||
|
||||
CORRADE_COMPARE((data.track<Vector3i, Vector3>(0).at(2.5f)), (Vector3{1.65f, 0.8f, 0.55f})); |
||||
} |
||||
|
||||
void AnimationDataTest::trackWrongIndex() { |
||||
std::ostringstream out; |
||||
Error redirectError{&out}; |
||||
|
||||
AnimationData data{nullptr, nullptr}; |
||||
data.trackType(0); |
||||
data.trackResultType(0); |
||||
data.trackTarget(0); |
||||
data.trackTargetId(0); |
||||
data.track<Float>(0); |
||||
|
||||
CORRADE_COMPARE(out.str(), |
||||
"Trade::AnimationData::trackType(): index out of range\n" |
||||
"Trade::AnimationData::trackResultType(): index out of range\n" |
||||
"Trade::AnimationData::trackTarget(): index out of range\n" |
||||
"Trade::AnimationData::trackTargetId(): index out of range\n" |
||||
"Trade::AnimationData::track(): index out of range\n"); |
||||
} |
||||
|
||||
void AnimationDataTest::trackWrongType() { |
||||
std::ostringstream out; |
||||
Error redirectError{&out}; |
||||
|
||||
AnimationData data{nullptr, Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { |
||||
{AnimationTrackType::Vector3i, |
||||
AnimationTrackType::Vector3, |
||||
AnimationTrackTarget::Scaling3D, 0, {}} |
||||
}}}; |
||||
|
||||
data.track<Vector3>(0); |
||||
|
||||
CORRADE_COMPARE(out.str(), "Trade::AnimationData::track(): improper type requested for Trade::AnimationTrackType::Vector3i\n"); |
||||
} |
||||
|
||||
void AnimationDataTest::trackWrongResultType() { |
||||
std::ostringstream out; |
||||
Error redirectError{&out}; |
||||
|
||||
AnimationData data{nullptr, Containers::Array<AnimationTrackData>{Containers::InPlaceInit, { |
||||
{AnimationTrackType::Vector3i, |
||||
AnimationTrackType::Vector3, |
||||
AnimationTrackTarget::Scaling3D, 0, {}} |
||||
}}}; |
||||
|
||||
data.track<Vector3i, Vector2>(0); |
||||
|
||||
CORRADE_COMPARE(out.str(), "Trade::AnimationData::track(): improper result type requested for Trade::AnimationTrackType::Vector3\n"); |
||||
} |
||||
|
||||
void AnimationDataTest::debugAnimationTrackType() { |
||||
std::ostringstream out; |
||||
|
||||
Debug{&out} << AnimationTrackType::DualQuaternion << AnimationTrackType(0xde); |
||||
CORRADE_COMPARE(out.str(), "Trade::AnimationTrackType::DualQuaternion Trade::AnimationTrackType(0xde)\n"); |
||||
} |
||||
|
||||
void AnimationDataTest::debugAnimationTrackTarget() { |
||||
std::ostringstream out; |
||||
|
||||
Debug{&out} << AnimationTrackTarget::Rotation3D << AnimationTrackTarget(135) << AnimationTrackTarget(0x42); |
||||
CORRADE_COMPARE(out.str(), "Trade::AnimationTrackTarget::Rotation3D Trade::AnimationTrackTarget::Custom(135) Trade::AnimationTrackTarget(0x42)\n"); |
||||
} |
||||
|
||||
}}} |
||||
|
||||
CORRADE_TEST_MAIN(Magnum::Trade::Test::AnimationDataTest) |
||||
Loading…
Reference in new issue