Browse Source

Trade: animation import interface in AbstractImporter.

pull/191/head
Vladimír Vondruš 8 years ago
parent
commit
0b3e1e3068
  1. 2
      doc/changelog.dox
  2. 33
      src/Magnum/Trade/AbstractImporter.cpp
  3. 68
      src/Magnum/Trade/AbstractImporter.h
  4. 201
      src/Magnum/Trade/Test/AbstractImporterTest.cpp

2
doc/changelog.dox

@ -93,6 +93,8 @@ See also:
@subsubsection changelog-latest-new-trade Trade library
- @ref Trade::AnimationData class and animation import interface in
@ref Trade::AbstractImporter::animation() and related functions
- @ref Trade::ObjectData2D and @ref Trade::ObjectData3D now support also
separate translation / rotation / scaling specification instead of a
combined transformation matrix. See @ref Trade::ObjectData2D::transformation()

33
src/Magnum/Trade/AbstractImporter.cpp

@ -32,6 +32,7 @@
#include <Corrade/Utility/Directory.h>
#include "Magnum/Trade/AbstractMaterialData.h"
#include "Magnum/Trade/AnimationData.h"
#include "Magnum/Trade/CameraData.h"
#include "Magnum/Trade/ImageData.h"
#include "Magnum/Trade/LightData.h"
@ -186,6 +187,38 @@ Containers::Optional<SceneData> AbstractImporter::doScene(UnsignedInt) {
CORRADE_ASSERT(false, "Trade::AbstractImporter::scene(): not implemented", {});
}
UnsignedInt AbstractImporter::animationCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::animationCount(): no file opened", {});
return doAnimationCount();
}
UnsignedInt AbstractImporter::doAnimationCount() const { return 0; }
Int AbstractImporter::animationForName(const std::string& name) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::animationForName(): no file opened", {});
return doAnimationForName(name);
}
Int AbstractImporter::doAnimationForName(const std::string&) { return -1; }
std::string AbstractImporter::animationName(const UnsignedInt id) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::animationName(): no file opened", {});
CORRADE_ASSERT(id < doAnimationCount(), "Trade::AbstractImporter::animationName(): index out of range", {});
return doAnimationName(id);
}
std::string AbstractImporter::doAnimationName(UnsignedInt) { return {}; }
Containers::Optional<AnimationData> AbstractImporter::animation(const UnsignedInt id) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::animation(): no file opened", {});
CORRADE_ASSERT(id < doAnimationCount(), "Trade::AbstractImporter::animation(): index out of range", {});
return doAnimation(id);
}
Containers::Optional<AnimationData> AbstractImporter::doAnimation(UnsignedInt) {
CORRADE_ASSERT(false, "Trade::AbstractImporter::animation(): not implemented", {});
}
UnsignedInt AbstractImporter::lightCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::lightCount(): no file opened", {});
return doLightCount();

68
src/Magnum/Trade/AbstractImporter.h

@ -139,6 +139,8 @@ expose internal state through various accessors:
state for currently opened file
- @ref AbstractMaterialData::importerState() can expose importer state for
given material imported by @ref material()
- @ref AnimationData::importerState() can expose importer state for given
animation imported by @ref animation()
- @ref CameraData::importerState() can expose importer state for a camera
importer by @ref camera()
- @ref ImageData::importerState() can expose importer state for an image
@ -204,10 +206,19 @@ checked by the implementation:
- All `do*()` implementations taking data ID as parameter are called only if
the ID is from valid range.
@attention @ref Corrade::Containers::Array instances returned from the plugin
@attention
@ref Corrade::Containers::Array instances returned from the plugin
should *not* use anything else than the default deleter, otherwise this can
cause dangling function pointer call on array destruction if the plugin
gets unloaded before the array is destroyed.
@attention
Similarly for interpolator functions passed through
@ref Animation::TrackView instances to @ref AnimationData --- to avoid
dangling pointers, be sure to always include an interpolator returned from
@ref animationInterpolatorFor(), which guarantees the function is *not*
instantiated in the plugin binary. Avoid using
@ref Animation::interpolatorFor() (or indirectly it by specifying
just @ref Animation::Interpolation), as it doesn't have such guarantee.
*/
class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlugin<AbstractImporter> {
public:
@ -446,6 +457,34 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
*/
Containers::Optional<SceneData> scene(UnsignedInt id);
/** @brief Animation count */
UnsignedInt animationCount() const;
/**
* @brief Animation ID for given name
*
* If no animation for given name exists, returns @cpp -1 @ce.
* @see @ref animationName()
*/
Int animationForName(const std::string& name);
/**
* @brief Animation name
* @param id Animation ID, from range [0, @ref animationCount()).
*
* @see @ref animationForName()
*/
std::string animationName(UnsignedInt id);
/**
* @brief Animation
* @param id Animation ID, from range [0, @ref animationCount()).
*
* Returns given animation or @ref Containers::NullOpt if importing
* failed.
*/
Containers::Optional<AnimationData> animation(UnsignedInt id);
/** @brief Light count */
UnsignedInt lightCount() const;
@ -753,7 +792,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* documentation of a particular plugin for more information about
* returned type and contents. Returns `nullptr` by default.
* @see @ref AbstractMaterialData::importerState(),
* @ref CameraData::importerState(), @ref ImageData::importerState(),
* @ref AnimationData::importerState(), @ref CameraData::importerState(),
* @ref ImageData::importerState(), @ref LightData::importerState(),
* @ref MeshData2D::importerState(), @ref MeshData3D::importerState(),
* @ref ObjectData2D::importerState(), @ref ObjectData3D::importerState(),
* @ref SceneData::importerState(), @ref TextureData::importerState()
@ -834,6 +874,30 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
/** @brief Implementation for @ref scene() */
virtual Containers::Optional<SceneData> doScene(UnsignedInt id);
/**
* @brief Implementation for @ref animationCount()
*
* Default implementation returns @cpp 0 @ce.
*/
virtual UnsignedInt doAnimationCount() const;
/**
* @brief Implementation for @ref animationForName()
*
* Default implementation returns @cpp -1 @ce.
*/
virtual Int doAnimationForName(const std::string& name);
/**
* @brief Implementation for @ref animationName()
*
* Default implementation returns empty string.
*/
virtual std::string doAnimationName(UnsignedInt id);
/** @brief Implementation for @ref animation() */
virtual Containers::Optional<AnimationData> doAnimation(UnsignedInt id);
/**
* @brief Implementation for @ref lightCount()
*

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

@ -29,6 +29,7 @@
#include <Corrade/Utility/Directory.h>
#include "Magnum/Trade/AbstractImporter.h"
#include "Magnum/Trade/AnimationData.h"
#include "Magnum/Trade/CameraData.h"
#include "Magnum/Trade/ImageData.h"
#include "Magnum/Trade/LightData.h"
@ -85,6 +86,18 @@ class AbstractImporterTest: public TestSuite::Tester {
void sceneNoFile();
void sceneOutOfRange();
void animation();
void animationCountNotImplemented();
void animationCountNoFile();
void animationForNameNotImplemented();
void animationForNameNoFile();
void animationNameNotImplemented();
void animationNameNoFile();
void animationNameOutOfRange();
void animationNotImplemented();
void animationNoFile();
void animationOutOfRange();
void light();
void lightCountNotImplemented();
void lightCountNoFile();
@ -264,6 +277,18 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::sceneNoFile,
&AbstractImporterTest::sceneOutOfRange,
&AbstractImporterTest::animation,
&AbstractImporterTest::animationCountNotImplemented,
&AbstractImporterTest::animationCountNoFile,
&AbstractImporterTest::animationForNameNotImplemented,
&AbstractImporterTest::animationForNameNoFile,
&AbstractImporterTest::animationNameNotImplemented,
&AbstractImporterTest::animationNameNoFile,
&AbstractImporterTest::animationNameOutOfRange,
&AbstractImporterTest::animationNotImplemented,
&AbstractImporterTest::animationNoFile,
&AbstractImporterTest::animationOutOfRange,
&AbstractImporterTest::light,
&AbstractImporterTest::lightCountNotImplemented,
&AbstractImporterTest::lightCountNoFile,
@ -963,6 +988,182 @@ void AbstractImporterTest::sceneOutOfRange() {
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::scene(): index out of range\n");
}
void AbstractImporterTest::animation() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doAnimationCount() const override { return 8; }
Int doAnimationForName(const std::string& name) override {
if(name == "eighth") return 7;
else return -1;
}
std::string doAnimationName(UnsignedInt id) override {
if(id == 7) return "eighth";
else return {};
}
Containers::Optional<AnimationData> doAnimation(UnsignedInt id) override {
if(id == 7) return AnimationData{{}, {}, &state};
else return AnimationData{{}, {}};
}
};
std::ostringstream out;
Error redirectError{&out};
Importer importer;
CORRADE_COMPARE(importer.animationCount(), 8);
CORRADE_COMPARE(importer.animationForName("eighth"), 7);
CORRADE_COMPARE(importer.animationName(7), "eighth");
auto data = importer.animation(7);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->importerState(), &state);
}
void AbstractImporterTest::animationCountNotImplemented() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
};
Importer importer;
CORRADE_COMPARE(importer.animationCount(), 0);
}
void AbstractImporterTest::animationCountNoFile() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
void doClose() override {}
};
std::ostringstream out;
Error redirectError{&out};
Importer importer;
importer.animationCount();
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::animationCount(): no file opened\n");
}
void AbstractImporterTest::animationForNameNotImplemented() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
};
Importer importer;
CORRADE_COMPARE(importer.animationForName(""), -1);
}
void AbstractImporterTest::animationForNameNoFile() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
void doClose() override {}
};
std::ostringstream out;
Error redirectError{&out};
Importer importer;
importer.animationForName("");
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::animationForName(): no file opened\n");
}
void AbstractImporterTest::animationNameNotImplemented() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doAnimationCount() const override { return 8; }
};
Importer importer;
CORRADE_COMPARE(importer.animationName(7), "");
}
void AbstractImporterTest::animationNameNoFile() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
void doClose() override {}
};
std::ostringstream out;
Error redirectError{&out};
Importer importer;
importer.animationName(42);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::animationName(): no file opened\n");
}
void AbstractImporterTest::animationNameOutOfRange() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
};
std::ostringstream out;
Error redirectError{&out};
Importer importer;
importer.animationName(0);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::animationName(): index out of range\n");
}
void AbstractImporterTest::animationNotImplemented() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doAnimationCount() const override { return 8; }
};
std::ostringstream out;
Error redirectError{&out};
Importer importer;
importer.animation(7);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::animation(): not implemented\n");
}
void AbstractImporterTest::animationNoFile() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
void doClose() override {}
};
std::ostringstream out;
Error redirectError{&out};
Importer importer;
importer.animation(42);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::animation(): no file opened\n");
}
void AbstractImporterTest::animationOutOfRange() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
};
std::ostringstream out;
Error redirectError{&out};
Importer importer;
importer.animation(0);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::animation(): index out of range\n");
}
void AbstractImporterTest::light() {
class Importer: public Trade::AbstractImporter {
Features doFeatures() const override { return {}; }

Loading…
Cancel
Save