Browse Source

SceneGraph: add Object::addFeature().

Compared to AbstractObject::addFeature() it passes a concrete Object
type to the feature constructor, which makes it work in more cases.
pull/651/head
Vladimír Vondruš 2 years ago
parent
commit
4928538231
  1. 4
      doc/changelog.dox
  2. 12
      src/Magnum/SceneGraph/Object.h
  3. 25
      src/Magnum/SceneGraph/Test/ObjectTest.cpp

4
doc/changelog.dox

@ -843,6 +843,10 @@ See also:
- @ref SceneGraph trees are now destructed in a way that preserves
@ref SceneGraph::Object::parent() links up to the root as well as
@ref SceneGraph::AbstractFeature::object() references
- Added @ref SceneGraph::Object::addFeature() as a counterpart to
@ref SceneGraph::AbstractObject::addFeature() that passes a concrete object
type to the feature constructor, in order to make it work with for example
the @ref BulletIntegration::MotionState
@subsubsection changelog-latest-changes-scenetools SceneTools library

12
src/Magnum/SceneGraph/Object.h

@ -139,6 +139,18 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
/** @brief Moving is not allowed */
Object<Transformation>& operator=(Object<Transformation>&&) = delete;
/**
* @brief Add a feature
* @m_since_latest
*
* Like @ref AbstractObject::addFeature(), but passing a concrete
* object type to the feature constructor, instead of just the base
* @ref AbstractObject.
*/
template<class U, class ...Args> U& addFeature(Args&&... args) {
return *(new U{*this, std::forward<Args>(args)...});
}
/**
* @{ @name Scene hierarchy
*

25
src/Magnum/SceneGraph/Test/ObjectTest.cpp

@ -41,6 +41,7 @@ struct ObjectTest: TestSuite::Tester {
explicit ObjectTest();
template<class T> void addFeature();
template<class T> void addFeatureAbstractObject();
template<class T> void parenting();
template<class T> void addChild();
@ -67,6 +68,8 @@ ObjectTest::ObjectTest() {
addTests<ObjectTest>({
&ObjectTest::addFeature<Float>,
&ObjectTest::addFeature<Double>,
&ObjectTest::addFeatureAbstractObject<Float>,
&ObjectTest::addFeatureAbstractObject<Double>,
&ObjectTest::parenting<Float>,
&ObjectTest::parenting<Double>,
@ -127,18 +130,38 @@ template<class T> void ObjectTest::addFeature() {
class MyFeature: public AbstractBasicFeature3D<T> {
public:
explicit MyFeature(AbstractBasicObject3D<T>& object, Int&, Containers::Pointer<int>&&): AbstractBasicFeature3D<T>{object} {}
explicit MyFeature(Object3D<T>& object, Int&, Containers::Pointer<int>&&): AbstractBasicFeature3D<T>{object} {}
};
Object3D<T> o;
CORRADE_VERIFY(o.features().isEmpty());
/* Test perfect forwarding as well */
int a = 0;
/* When called on Object3D, the feature constructor should get the concrete
Object type. AbstractObject::addFeature() is tested below. */
MyFeature& f = o.template addFeature<MyFeature>(a, Containers::Pointer<int>{});
CORRADE_VERIFY(!o.features().isEmpty());
CORRADE_COMPARE(&f.object(), &o);
}
template<class T> void ObjectTest::addFeatureAbstractObject() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());
/* Like addFeature(), but calling the base variant on AbstractObject */
class MyFeature: public AbstractBasicFeature3D<T> {
public:
explicit MyFeature(AbstractBasicObject3D<T>& object, Int&, Containers::Pointer<int>&&): AbstractBasicFeature3D<T>{object} {}
};
Object3D<T> o;
CORRADE_VERIFY(o.features().isEmpty());
int a = 0;
MyFeature& f = static_cast<AbstractBasicObject3D<T>&>(o).template addFeature<MyFeature>(a, Containers::Pointer<int>{});
CORRADE_VERIFY(!o.features().isEmpty());
CORRADE_COMPARE(&f.object(), &o);
}
template<class T> void ObjectTest::parenting() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());

Loading…
Cancel
Save