Browse Source

Trade: reintroduce original deprecated SceneData APIs.

Those now operate on top of the new data layout.
pull/525/head
Vladimír Vondruš 5 years ago
parent
commit
4da64d61e2
  1. 13
      doc/changelog.dox
  2. 62
      src/Magnum/Trade/SceneData.cpp
  3. 33
      src/Magnum/Trade/SceneData.h
  4. 129
      src/Magnum/Trade/Test/SceneDataTest.cpp

13
doc/changelog.dox

@ -632,6 +632,15 @@ See also:
directly but rather generated on-the-fly from attribute data, which makes
them less efficient than calling @ref Trade::MaterialData::hasAttribute()
etc.
- @ref Trade::SceneData constructor taking a @ref std::vector of 2D and 3D
children is deprecated in favor of the new scene representation. Use
@ref Trade::SceneData::SceneData(SceneObjectType, UnsignedLong, Containers::Array<char>&&, Containers::Array<SceneFieldData>&&, const void*)
instead.
- @cpp Trade::SceneData::children2D() @ce and
@cpp Trade::SceneData::children3D() @ce are deprecated in favor of the
new scene representation. Use @ref Trade::SceneData::childrenFor() with
@cpp -1 @ce passed as the @p object argument to get a list of top-level
objects.
- @ref Trade::AbstractImporter::material() now returns
@ref Corrade::Containers::Optional instead of a @ref Corrade::Containers::Pointer,
as the new @ref Trade::MaterialData class isn't polymorphic anymore. If
@ -805,6 +814,10 @@ See also:
@cpp Trade::AbstractMaterialData @ce aliases to, doesn't have a
@cpp virtual @ce destructor as subclasses with extra data members aren't a
desired use case anymore.
- @ref Trade::SceneData constructor taking a @ref std::vector of 2D and 3D
children that got deprecated in favor of
@ref Trade::SceneData::SceneData(SceneObjectType, UnsignedLong, Containers::Array<char>&&, Containers::Array<SceneFieldData>&&, const void*)
no longer accepts a scene that has both 2D and 3D children.
- @ref Trade::AbstractImporter::doDefaultScene() is now @cpp const @ce ---
since the function is not expected to fail, no kind of complex lazy
population can be done anyway. This is now consistent with `do*Count()`

62
src/Magnum/Trade/SceneData.cpp

@ -39,6 +39,12 @@
#include "Magnum/Math/PackingBatch.h"
#include "Magnum/Trade/Implementation/arrayUtilities.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <vector>
#include <Corrade/Containers/ArrayTuple.h>
#include <Corrade/Containers/ArrayViewStl.h>
#endif
namespace Magnum { namespace Trade {
Debug& operator<<(Debug& debug, const SceneObjectType value) {
@ -580,6 +586,48 @@ SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong object
SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong objectCount, const DataFlags dataFlags, const Containers::ArrayView<const void> data, const std::initializer_list<SceneFieldData> fields, const void* const importerState): SceneData{objectType, objectCount, dataFlags, data, Implementation::initializerListToArrayWithDefaultDeleter(fields), importerState} {}
#ifdef MAGNUM_BUILD_DEPRECATED
SceneData::SceneData(std::vector<UnsignedInt> children2D, std::vector<UnsignedInt> children3D, const void* const importerState): _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _objectType{SceneObjectType::UnsignedInt}, _importerState{importerState} {
/* Assume nobody ever created a scene with both 2D and 3D children.
(PrimitiveImporter did, but that's an exception and blame goes on me.)
If this blows up for you, please complain. Or rather upgrade to the new
API which ... forces you to have a separate scene for 2D and 3D. But you
can share the data among the two, at least. */
CORRADE_ASSERT(children2D.empty() || children3D.empty(),
"Trade::SceneData: it's no longer possible to have a scene with both 2D and 3D objects", );
Containers::ArrayView<const UnsignedInt> children;
if(!children2D.empty()) {
_dimensions = 2;
children = children2D;
} else if(!children3D.empty()) {
_dimensions = 3;
children = children3D;
} else _dimensions = 0;
/* Set object count to the max found child index. It's not great as it
doesn't take any nested object into account but SceneData created this
way is expected to be used only through the deprecated APIs anyway,
which don't care about this value. */
_objectCount = children.empty() ? 0 : Math::max(children) + 1;
/* Convert the vector with top-level object IDs to the parent field, where
all have -1 as a parent. This way the (also deprecated) children2D() /
children3D() will return the desired values. */
Containers::ArrayView<UnsignedInt> objects;
Containers::ArrayView<Int> parents;
_data = Containers::ArrayTuple{
{NoInit, children.size(), objects},
{NoInit, children.size(), parents},
};
_fields = {InPlaceInit, {
SceneFieldData{SceneField::Parent, objects, parents}
}};
Utility::copy(children, objects);
constexpr Int parent[]{-1};
Utility::copy(Containers::stridedArrayView(parent).broadcasted<0>(parents.size()), parents);
}
#endif
SceneData::SceneData(SceneData&&) noexcept = default;
SceneData::~SceneData() = default;
@ -1932,6 +1980,20 @@ Containers::Optional<const void*> SceneData::importerStateFor(const UnsignedInt
return *importerState;
}
#ifdef MAGNUM_BUILD_DEPRECATED
std::vector<UnsignedInt> SceneData::children2D() const {
if(_dimensions != 2) return {};
const Containers::Array<UnsignedInt> children = childrenFor(-1);
return {children.begin(), children.end()};
}
std::vector<UnsignedInt> SceneData::children3D() const {
if(_dimensions != 3) return {};
const Containers::Array<UnsignedInt> children = childrenFor(-1);
return {children.begin(), children.end()};
}
#endif
Containers::Array<SceneFieldData> SceneData::releaseFieldData() {
Containers::Array<SceneFieldData> out = std::move(_fields);
_fields = {};

33
src/Magnum/Trade/SceneData.h

@ -36,6 +36,11 @@
#include "Magnum/Trade/Trade.h"
#include "Magnum/Trade/visibility.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Utility/StlForwardVector.h>
#include <Corrade/Utility/Macros.h>
#endif
namespace Magnum { namespace Trade {
/**
@ -821,6 +826,18 @@ class MAGNUM_TRADE_EXPORT SceneData {
/* Not noexcept because allocation happens inside */
explicit SceneData(SceneObjectType objectType, UnsignedLong objectCount, DataFlags dataFlags, Containers::ArrayView<const void> data, std::initializer_list<SceneFieldData> fields, const void* importerState = nullptr);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Constructor
* @param children2D Two-dimensional child objects
* @param children3D Three-dimensional child objects
* @param importerState Importer-specific state
* @m_deprecated_since_latest Use @ref SceneData(SceneObjectType, UnsignedLong, Containers::Array<char>&&, Containers::Array<SceneFieldData>&&, const void*)
* instead.
*/
explicit CORRADE_DEPRECATED("use SceneData(SceneObjectType, UnsignedLong, Containers::Array<char>&&, Containers::Array<SceneFieldData>&&, const void*) instead") SceneData(std::vector<UnsignedInt> children2D, std::vector<UnsignedInt> children3D, const void* importerState = nullptr);
#endif
/** @brief Copying is not allowed */
SceneData(const SceneData&) = delete;
@ -2080,6 +2097,22 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
Containers::Optional<const void*> importerStateFor(UnsignedInt object) const;
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Two-dimensional root scene objects
* @m_deprecated_since_latest Use @ref childrenFor() with `-1` passed
* as the @p object argument.
*/
CORRADE_DEPRECATED("use childrenFor() instead") std::vector<UnsignedInt> children2D() const;
/**
* @brief Three-dimensional root scene objects
* @m_deprecated_since_latest Use @ref childrenFor() with `-1` passed
* as the @p object argument.
*/
CORRADE_DEPRECATED("use childrenFor() instead") std::vector<UnsignedInt> children3D() const;
#endif
/**
* @brief Release field data storage
* @m_since_latest

129
src/Magnum/Trade/Test/SceneDataTest.cpp

@ -40,6 +40,11 @@
#include "Magnum/Math/Range.h"
#include "Magnum/Trade/SceneData.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <vector>
#include <Corrade/Containers/GrowableArray.h>
#endif
namespace Magnum { namespace Trade { namespace Test { namespace {
struct SceneDataTest: TestSuite::Tester {
@ -85,8 +90,11 @@ struct SceneDataTest: TestSuite::Tester {
void construct();
void constructZeroFields();
void constructZeroObjects();
void constructNotOwned();
#ifdef MAGNUM_BUILD_DEPRECATED
void constructDeprecated();
void constructDeprecatedBoth2DAnd3D();
#endif
void constructDuplicateField();
void constructDuplicateCustomField();
@ -171,6 +179,10 @@ struct SceneDataTest: TestSuite::Tester {
void skinsFor();
void importerStateFor();
#ifdef MAGNUM_BUILD_DEPRECATED
void childrenDeprecated();
#endif
void fieldForFieldMissing();
void fieldForInvalidObject();
@ -198,6 +210,18 @@ const struct {
{"offset at the end", 3, 10, 0}
};
#ifdef MAGNUM_BUILD_DEPRECATED
const struct {
const char* name;
bool is2D;
bool is3D;
} ChildrenDeprecatedData[]{
{"2D", true, false},
{"3D", false, true},
{"neither", false, false}
};
#endif
SceneDataTest::SceneDataTest() {
addTests({&SceneDataTest::objectTypeSize,
&SceneDataTest::objectTypeSizeInvalid,
@ -243,6 +267,13 @@ SceneDataTest::SceneDataTest() {
addInstancedTests({&SceneDataTest::constructNotOwned},
Containers::arraySize(NotOwnedData));
#ifdef MAGNUM_BUILD_DEPRECATED
addInstancedTests({&SceneDataTest::constructDeprecated},
Containers::arraySize(ChildrenDeprecatedData));
addTests({&SceneDataTest::constructDeprecatedBoth2DAnd3D});
#endif
addTests({&SceneDataTest::constructDuplicateField,
&SceneDataTest::constructDuplicateCustomField,
&SceneDataTest::constructInconsistentObjectType,
@ -380,9 +411,14 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::lightsFor,
&SceneDataTest::camerasFor,
&SceneDataTest::skinsFor,
&SceneDataTest::importerStateFor,
&SceneDataTest::importerStateFor});
#ifdef MAGNUM_BUILD_DEPRECATED
addInstancedTests({&SceneDataTest::childrenDeprecated},
Containers::arraySize(ChildrenDeprecatedData));
#endif
&SceneDataTest::fieldForFieldMissing,
addTests({&SceneDataTest::fieldForFieldMissing,
&SceneDataTest::fieldForInvalidObject,
&SceneDataTest::releaseFieldData,
@ -1419,6 +1455,56 @@ void SceneDataTest::constructNotOwned() {
CORRADE_COMPARE(scene.mutableField<UnsignedByte>(0)[2], 0);
}
#ifdef MAGNUM_BUILD_DEPRECATED
void SceneDataTest::constructDeprecated() {
auto&& data = ChildrenDeprecatedData[testCaseInstanceId()];
setTestCaseDescription(data.name);
int a;
CORRADE_IGNORE_DEPRECATED_PUSH
SceneData scene{
data.is2D ? std::vector<UnsignedInt>{5, 17, 36, 22} : std::vector<UnsignedInt>{},
data.is3D ? std::vector<UnsignedInt>{5, 17, 36, 22} : std::vector<UnsignedInt>{},
&a};
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedInt);
if(data.is2D || data.is3D)
CORRADE_COMPARE(scene.objectCount(), 37);
else
CORRADE_COMPARE(scene.objectCount(), 0);
CORRADE_COMPARE(scene.dataFlags(), DataFlag::Mutable|DataFlag::Owned);
CORRADE_COMPARE(scene.importerState(), &a);
CORRADE_COMPARE(scene.fieldCount(), 1);
CORRADE_COMPARE(scene.fieldName(0), SceneField::Parent);
CORRADE_COMPARE(scene.fieldType(0), SceneFieldType::Int);
if(data.is2D || data.is3D) {
CORRADE_COMPARE_AS(scene.objects<UnsignedInt>(0),
Containers::arrayView<UnsignedInt>({5, 17, 36, 22}),
TestSuite::Compare::Container);
CORRADE_COMPARE_AS(scene.field<Int>(0),
Containers::arrayView<Int>({-1, -1, -1, -1}),
TestSuite::Compare::Container);
} else CORRADE_COMPARE(scene.fieldSize(SceneField::Parent), 0);
/* There's no transformation field that would disambiguate this, the state
is set directly */
CORRADE_COMPARE(scene.is2D(), data.is2D);
CORRADE_COMPARE(scene.is3D(), data.is3D);
}
void SceneDataTest::constructDeprecatedBoth2DAnd3D() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
std::ostringstream out;
Error redirectError{&out};
CORRADE_IGNORE_DEPRECATED_PUSH
SceneData scene{{5, 17}, {36, 22}};
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(out.str(), "Trade::SceneData: it's no longer possible to have a scene with both 2D and 3D objects\n");
}
#endif
void SceneDataTest::constructDuplicateField() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
@ -4695,6 +4781,43 @@ void SceneDataTest::importerStateFor() {
CORRADE_COMPARE(scene.importerStateFor(1), Containers::NullOpt);
}
#ifdef MAGNUM_BUILD_DEPRECATED
void SceneDataTest::childrenDeprecated() {
auto&& data = ChildrenDeprecatedData[testCaseInstanceId()];
setTestCaseDescription(data.name);
struct Field {
UnsignedByte object;
Short parent;
} fields[]{
{5, -1},
{2, 0},
{3, 0},
{0, -1},
{1, 2},
{4, -1}
};
Containers::StridedArrayView1D<Field> view = fields;
Containers::Array<SceneFieldData> fieldData;
arrayAppend(fieldData, SceneFieldData{SceneField::Parent, view.slice(&Field::object), view.slice(&Field::parent)});
if(data.is2D)
arrayAppend(fieldData, SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Vector2, nullptr});
if(data.is3D)
arrayAppend(fieldData, SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Vector3, nullptr});
SceneData scene{SceneObjectType::UnsignedByte, 25, {}, fields, std::move(fieldData)};
CORRADE_IGNORE_DEPRECATED_PUSH
CORRADE_COMPARE_AS(scene.children2D(),
(data.is2D ? std::vector<UnsignedInt>{5, 0, 4} : std::vector<UnsignedInt>{}),
TestSuite::Compare::Container);
CORRADE_COMPARE_AS(scene.children3D(),
(data.is3D ? std::vector<UnsignedInt>{5, 0, 4} : std::vector<UnsignedInt>{}),
TestSuite::Compare::Container);
CORRADE_IGNORE_DEPRECATED_POP
}
#endif
void SceneDataTest::fieldForFieldMissing() {
SceneData scene{SceneObjectType::UnsignedInt, 7, nullptr, {}};

Loading…
Cancel
Save