Browse Source

Better usage of *Basic* in class names, part 3: SceneGraph features.

Use AbstractFeature<dimensions, T>, AbstractGroupedFeature<...>,
AbstractFeatureGroup<...>, FeatureGroup<...> like before and add two
kinds of aliases instead of only one, one with *Basic* for abstract type
and one for Float type.

Partially reverts commit 572efce3f7.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
43feadfed6
  1. 4
      src/SceneGraph/AbstractCamera.h
  2. 8
      src/SceneGraph/AbstractCamera.hpp
  3. 89
      src/SceneGraph/AbstractFeature.h
  4. 12
      src/SceneGraph/AbstractFeature.hpp
  5. 68
      src/SceneGraph/AbstractGroupedFeature.h
  6. 20
      src/SceneGraph/AbstractObject.h
  7. 4
      src/SceneGraph/Animable.h
  8. 6
      src/SceneGraph/Animable.hpp
  9. 2
      src/SceneGraph/AnimableGroup.h
  10. 8
      src/SceneGraph/Drawable.h
  11. 87
      src/SceneGraph/FeatureGroup.h
  12. 8
      src/SceneGraph/FeatureGroup.hpp
  13. 4
      src/SceneGraph/Object.hpp
  14. 35
      src/SceneGraph/SceneGraph.h
  15. 8
      src/SceneGraph/instantiation.cpp
  16. 6
      src/Shapes/AbstractShape.cpp
  17. 2
      src/Shapes/AbstractShape.h
  18. 2
      src/Shapes/ShapeGroup.h

4
src/SceneGraph/AbstractCamera.h

@ -72,7 +72,7 @@ relevant sections in
@see AbstractCamera2D, AbstractCamera3D, @ref scenegraph, Drawable, DrawableGroup
*/
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicCamera: public AbstractBasicFeature<dimensions, T> {
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicCamera: public AbstractFeature<dimensions, T> {
public:
/**
* @brief Constructor
@ -98,7 +98,7 @@ template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT Abstrac
* applied as first.
*/
typename DimensionTraits<dimensions, T>::MatrixType cameraMatrix() {
AbstractBasicFeature<dimensions, T>::object()->setClean();
AbstractFeature<dimensions, T>::object()->setClean();
return _cameraMatrix;
}

8
src/SceneGraph/AbstractCamera.hpp

@ -70,8 +70,8 @@ template<UnsignedInt dimensions, class T> typename DimensionTraits<dimensions, T
}
template<UnsignedInt dimensions, class T> AbstractBasicCamera<dimensions, T>::AbstractBasicCamera(AbstractObject<dimensions, T>* object): AbstractBasicFeature<dimensions, T>(object), _aspectRatioPolicy(AspectRatioPolicy::NotPreserved) {
AbstractBasicFeature<dimensions, T>::setCachedTransformations(CachedTransformation::InvertedAbsolute);
template<UnsignedInt dimensions, class T> AbstractBasicCamera<dimensions, T>::AbstractBasicCamera(AbstractObject<dimensions, T>* object): AbstractFeature<dimensions, T>(object), _aspectRatioPolicy(AspectRatioPolicy::NotPreserved) {
AbstractFeature<dimensions, T>::setCachedTransformations(CachedTransformation::InvertedAbsolute);
}
template<UnsignedInt dimensions, class T> AbstractBasicCamera<dimensions, T>::~AbstractBasicCamera() {}
@ -88,11 +88,11 @@ template<UnsignedInt dimensions, class T> void AbstractBasicCamera<dimensions, T
}
template<UnsignedInt dimensions, class T> void AbstractBasicCamera<dimensions, T>::draw(BasicDrawableGroup<dimensions, T>& group) {
AbstractObject<dimensions, T>* scene = AbstractBasicFeature<dimensions, T>::object()->scene();
AbstractObject<dimensions, T>* scene = AbstractFeature<dimensions, T>::object()->scene();
CORRADE_ASSERT(scene, "Camera::draw(): cannot draw when camera is not part of any scene", );
/* Compute camera matrix */
AbstractBasicFeature<dimensions, T>::object()->setClean();
AbstractFeature<dimensions, T>::object()->setClean();
/* Compute transformations of all objects in the group relative to the camera */
std::vector<AbstractObject<dimensions, T>*> objects(group.size());

89
src/SceneGraph/AbstractFeature.h

@ -25,7 +25,7 @@
*/
/** @file
* @brief Class Magnum::SceneGraph::AbstractBasicFeature, typedef Magnum::SceneGraph::AbstractFeature2D, Magnum::SceneGraph::AbstractFeature3D, enum Magnum::SceneGraph::CachedTransformation, enum set Magnum::SceneGraph::CachedTransformations
* @brief Class Magnum::SceneGraph::AbstractFeature, alias Magnum::SceneGraph::BasicAbstractFeature2D, Magnum::SceneGraph::BasicAbstractFeature3D, typedef Magnum::SceneGraph::AbstractFeature2D, Magnum::SceneGraph::AbstractFeature3D, enum Magnum::SceneGraph::CachedTransformation, enum set Magnum::SceneGraph::CachedTransformations
*/
#include <Containers/EnumSet.h>
@ -40,8 +40,8 @@ namespace Magnum { namespace SceneGraph {
@brief Which transformation to cache in given feature
@see @ref scenegraph-caching, CachedTransformations,
AbstractBasicFeature::setCachedTransformations(), AbstractBasicFeature::clean(),
AbstractBasicFeature::cleanInverted()
AbstractFeature::setCachedTransformations(), AbstractFeature::clean(),
AbstractFeature::cleanInverted()
@todo Provide also simpler representations from which could benefit
other transformation implementations, as they won't need to
e.g. create transformation matrix from quaternion?
@ -65,8 +65,8 @@ enum class CachedTransformation: UnsignedByte {
/**
@brief Which transformations to cache in this feature
@see @ref scenegraph-caching, AbstractBasicFeature::setCachedTransformations(),
AbstractBasicFeature::clean(), AbstractBasicFeature::cleanInverted()
@see @ref scenegraph-caching, AbstractFeature::setCachedTransformations(),
AbstractFeature::clean(), AbstractFeature::cleanInverted()
*/
typedef Containers::EnumSet<CachedTransformation, UnsignedByte> CachedTransformations;
@ -154,18 +154,19 @@ For other specializations (e.g. using Double type) you have to use
AbstractFeature.hpp implementation file to avoid linker errors. See also
@ref compilation-speedup-hpp for more information.
- @ref AbstractBasicFeature "AbstractBasicFeature<2, Float>"
- @ref AbstractBasicFeature "AbstractBasicFeature<3, Float>"
- @ref AbstractFeature "AbstractFeature<2, Float>"
- @ref AbstractFeature "AbstractFeature<3, Float>"
@see @ref AbstractFeature2D, @ref AbstractFeature3D
@see @ref AbstractBasicFeature2D, @ref AbstractBasicFeature3D,
@ref AbstractFeature2D, @ref AbstractFeature3D
*/
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicFeature
#ifndef DOXYGEN_GENERATING_OUTPUT
: private Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>
#endif
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractFeature
#ifndef DOXYGEN_GENERATING_OUTPUT
: private Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>
#endif
{
friend class Containers::LinkedList<AbstractBasicFeature<dimensions, T>>;
friend class Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>;
friend class Containers::LinkedList<AbstractFeature<dimensions, T>>;
friend class Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>;
template<class Transformation> friend class Object;
public:
@ -173,38 +174,38 @@ template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT Abstrac
* @brief Constructor
* @param object %Object holding this feature
*/
explicit AbstractBasicFeature(AbstractObject<dimensions, T>* object);
explicit AbstractFeature(AbstractObject<dimensions, T>* object);
virtual ~AbstractBasicFeature() = 0;
virtual ~AbstractFeature() = 0;
/** @brief %Object holding this feature */
AbstractObject<dimensions, T>* object() {
return Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>::list();
return Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::list();
}
/** @overload */
const AbstractObject<dimensions, T>* object() const {
return Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>::list();
return Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::list();
}
/** @brief Previous feature or `nullptr`, if this is first feature */
AbstractBasicFeature<dimensions, T>* previousFeature() {
return Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>::previous();
AbstractFeature<dimensions, T>* previousFeature() {
return Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::previous();
}
/** @overload */
const AbstractBasicFeature<dimensions, T>* previousFeature() const {
return Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>::previous();
const AbstractFeature<dimensions, T>* previousFeature() const {
return Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::previous();
}
/** @brief Next feature or `nullptr`, if this is last feature */
AbstractBasicFeature<dimensions, T>* nextFeature() {
return Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>::next();
AbstractFeature<dimensions, T>* nextFeature() {
return Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::next();
}
/** @overload */
const AbstractBasicFeature<dimensions, T>* nextFeature() const {
return Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>::next();
const AbstractFeature<dimensions, T>* nextFeature() const {
return Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::next();
}
/**
@ -282,19 +283,51 @@ template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT Abstrac
CachedTransformations _cachedTransformations;
};
#ifndef CORRADE_GCC46_COMPATIBILITY
/**
@brief Base feature for two-dimensional scenes
Convenience alternative to <tt>%AbstractFeature<2, T></tt>. See AbstractFeature
for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractFeature<2, T></tt> instead.
@see @ref AbstractFeature2D, @ref AbstractBasicFeature3D
*/
template<class T> using AbstractBasicFeature2D = AbstractFeature<2, T>;
#endif
/**
@brief Base feature for two-dimensional float scenes
@see @ref AbstractFeature3D
*/
typedef AbstractBasicFeature<2, Float> AbstractFeature2D;
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef AbstractBasicFeature2D<Float> AbstractFeature2D;
#else
typedef AbstractFeature<2, Float> AbstractFeature2D;
#endif
#ifndef CORRADE_GCC46_COMPATIBILITY
/**
@brief Base feature for three-dimensional scenes
Convenience alternative to <tt>%AbstractFeature<3, T></tt>. See AbstractFeature
for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractFeature<3, T></tt> instead.
@see AbstractFeature2D
*/
template<class T> using AbstractBasicFeature3D = AbstractFeature<3, T>;
#endif
/**
@brief Base feature for three-dimensional float scenes
@see @ref AbstractFeature2D
*/
typedef AbstractBasicFeature<3, Float> AbstractFeature3D;
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef AbstractBasicFeature3D<Float> AbstractFeature3D;
#else
typedef AbstractFeature<3, Float> AbstractFeature3D;
#endif
}}

12
src/SceneGraph/AbstractFeature.hpp

@ -32,17 +32,17 @@
namespace Magnum { namespace SceneGraph {
template<UnsignedInt dimensions, class T> AbstractBasicFeature<dimensions, T>::AbstractBasicFeature(AbstractObject<dimensions, T>* object) {
object->Containers::template LinkedList<AbstractBasicFeature<dimensions, T>>::insert(this);
template<UnsignedInt dimensions, class T> AbstractFeature<dimensions, T>::AbstractFeature(AbstractObject<dimensions, T>* object) {
object->Containers::template LinkedList<AbstractFeature<dimensions, T>>::insert(this);
}
template<UnsignedInt dimensions, class T> AbstractBasicFeature<dimensions, T>::~AbstractBasicFeature() = default;
template<UnsignedInt dimensions, class T> AbstractFeature<dimensions, T>::~AbstractFeature() = default;
template<UnsignedInt dimensions, class T> void AbstractBasicFeature<dimensions, T>::markDirty() {}
template<UnsignedInt dimensions, class T> void AbstractFeature<dimensions, T>::markDirty() {}
template<UnsignedInt dimensions, class T> void AbstractBasicFeature<dimensions, T>::clean(const typename DimensionTraits<dimensions, T>::MatrixType&) {}
template<UnsignedInt dimensions, class T> void AbstractFeature<dimensions, T>::clean(const typename DimensionTraits<dimensions, T>::MatrixType&) {}
template<UnsignedInt dimensions, class T> void AbstractBasicFeature<dimensions, T>::cleanInverted(const typename DimensionTraits<dimensions, T>::MatrixType&) {}
template<UnsignedInt dimensions, class T> void AbstractFeature<dimensions, T>::cleanInverted(const typename DimensionTraits<dimensions, T>::MatrixType&) {}
}}

68
src/SceneGraph/AbstractGroupedFeature.h

@ -25,7 +25,7 @@
*/
/** @file
* @brief Class Magnum::SceneGraph::AbstractBasicGroupedFeature, alias Magnum::SceneGraph::AbstractGroupedFeature2D, Magnum::SceneGraph::AbstractGroupedFeature3D
* @brief Class Magnum::SceneGraph::AbstractGroupedFeature, alias Magnum::SceneGraph::AbstractBasicGroupedFeature2D, Magnum::SceneGraph::AbstractBasicGroupedFeature3D, Magnum::SceneGraph::AbstractGroupedFeature2D, Magnum::SceneGraph::AbstractGroupedFeature3D
*/
#include <vector>
@ -38,12 +38,12 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base for grouped features
Used together with BasicFeatureGroup.
Used together with FeatureGroup.
@section AbstractGroupedFeature-subclassing Subclassing
Usage is via subclassing the feature using [CRTP](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)
and typedef'ing BasicFeatureGroup to accept only given type, e.g.:
and typedef'ing FeatureGroup to accept only given type, e.g.:
@code
class Drawable: public SceneGraph::AbstractGroupedFeature3D<Drawable> {
// ...
@ -59,15 +59,15 @@ For other specializations (e.g. using Double type) you have to use
AbstractGroupedFeature.hpp implementation file to avoid linker errors. See also
@ref compilation-speedup-hpp for more information.
- @ref AbstractBasicFeatureGroup "AbstractBasicFeatureGroup<2, Float>"
- @ref AbstractBasicFeatureGroup "AbstractBasicFeatureGroup<3, Float>"
- @ref AbstractFeatureGroup "AbstractFeatureGroup<2, Float>"
- @ref AbstractFeatureGroup "AbstractFeatureGroup<3, Float>"
@see @ref AbstractGroupedFeature2D, @ref AbstractGroupedFeature3D,
@ref scenegraph, @ref BasicFeatureGroup, @ref FeatureGroup2D,
@ref FeatureGroup3D
@see @ref scenegraph, @ref AbstractBasicGroupedFeature2D,
@ref AbstractBasicGroupedFeature3D, @ref AbstractGroupedFeature2D,
@ref AbstractGroupedFeature3D, @ref FeatureGroup
*/
template<UnsignedInt dimensions, class Derived, class T> class AbstractBasicGroupedFeature: public AbstractBasicFeature<dimensions, T> {
friend class BasicFeatureGroup<dimensions, Derived, T>;
template<UnsignedInt dimensions, class Derived, class T> class AbstractGroupedFeature: public AbstractFeature<dimensions, T> {
friend class FeatureGroup<dimensions, Derived, T>;
public:
/**
@ -78,7 +78,7 @@ template<UnsignedInt dimensions, class Derived, class T> class AbstractBasicGrou
* Adds the feature to the object and to group, if specified.
* @see FeatureGroup::add()
*/
explicit AbstractBasicGroupedFeature(AbstractObject<dimensions, T>* object, BasicFeatureGroup<dimensions, Derived, T>* group = nullptr): AbstractBasicFeature<dimensions, T>(object), _group(nullptr) {
explicit AbstractGroupedFeature(AbstractObject<dimensions, T>* object, FeatureGroup<dimensions, Derived, T>* group = nullptr): AbstractFeature<dimensions, T>(object), _group(nullptr) {
if(group) group->add(static_cast<Derived*>(this));
}
@ -88,44 +88,68 @@ template<UnsignedInt dimensions, class Derived, class T> class AbstractBasicGrou
* Removes the feature from object and from group, if it belongs to
* any.
*/
~AbstractBasicGroupedFeature() {
~AbstractGroupedFeature() {
if(_group) _group->remove(static_cast<Derived*>(this));
}
/** @brief Group this feature belongs to */
BasicFeatureGroup<dimensions, Derived, T>* group() {
FeatureGroup<dimensions, Derived, T>* group() {
return _group;
}
/** @overload */
const BasicFeatureGroup<dimensions, Derived, T>* group() const {
const FeatureGroup<dimensions, Derived, T>* group() const {
return _group;
}
private:
BasicFeatureGroup<dimensions, Derived, T>* _group;
FeatureGroup<dimensions, Derived, T>* _group;
};
#ifndef CORRADE_GCC46_COMPATIBILITY
/**
@brief Base grouped feature for two-dimensional scenes
Convenience alternative to <tt>%AbstractGroupedFeature<2, Derived, T></tt>. See
AbstractGroupedFeature for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractGroupedFeature<2, Derived, T></tt>
instead.
@see @ref AbstractGroupedFeature2D, @ref AbstractBasicGroupedFeature3D
*/
template<class Derived, class T> using AbstractBasicGroupedFeature2D = AbstractGroupedFeature<2, Derived, T>;
/**
@brief Base grouped feature for two-dimensional float scenes
Convenience alternative to <tt>%AbstractBasicGroupedFeature<2, Derived, Float></tt>.
@note Not available on GCC < 4.7. Use <tt>%AbstractBasicGroupedFeature<2, Derived, Float></tt>
Convenience alternative to <tt>%AbstractBasicGroupedFeature2D<Derived, Float></tt>.
See AbstractGroupedFeature for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractGroupedFeature<2, Derived, Float></tt>
instead.
@see @ref AbstractGroupedFeature3D
*/
template<class Derived> using AbstractGroupedFeature2D = AbstractBasicGroupedFeature<2, Derived, Float>;
template<class Derived> using AbstractGroupedFeature2D = AbstractBasicGroupedFeature2D<Derived, Float>;
/**
@brief Base grouped feature for three-dimensional scenes
Convenience alternative to <tt>%AbstractGroupedFeature<3, Derived, T></tt>. See
AbstractGroupedFeature for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractGroupedFeature<3, Derived, T></tt>
instead.
@see @ref AbstractGroupedFeature3D, @ref AbstractBasicGroupedFeature2D
*/
template<class Derived, class T> using AbstractBasicGroupedFeature3D = AbstractGroupedFeature<3, Derived, T>;
/**
@brief Base for three-dimensional grouped features
@brief Base grouped feature for three-dimensional float scenes
Convenience alternative to <tt>%AbstractBasicGroupedFeature<3, Derived, Float></tt>.
@note Not available on GCC < 4.7. Use <tt>%AbstractBasicGroupedFeature<3, Derived, Float></tt>
Convenience alternative to <tt>%AbstractBasicGroupedFeature3D<Derived, Float></tt>.
See AbstractGroupedFeature for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractGroupedFeature<3, Derived, Float></tt>
instead.
@see @ref AbstractGroupedFeature2D
*/
template<class Derived> using AbstractGroupedFeature3D = AbstractBasicGroupedFeature<3, Derived, Float>;
template<class Derived> using AbstractGroupedFeature3D = AbstractBasicGroupedFeature3D<Derived, Float>;
#endif
}}

20
src/SceneGraph/AbstractObject.h

@ -59,46 +59,46 @@ for(AbstractFeature* feature = o->firstFeature(); feature; feature = feature->ne
*/
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractObject
#ifndef DOXYGEN_GENERATING_OUTPUT
: private Containers::LinkedList<AbstractBasicFeature<dimensions, T>>
: private Containers::LinkedList<AbstractFeature<dimensions, T>>
#endif
{
friend class Containers::LinkedList<AbstractBasicFeature<dimensions, T>>;
friend class Containers::LinkedListItem<AbstractBasicFeature<dimensions, T>, AbstractObject<dimensions, T>>;
friend class AbstractBasicFeature<dimensions, T>;
friend class Containers::LinkedList<AbstractFeature<dimensions, T>>;
friend class Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>;
friend class AbstractFeature<dimensions, T>;
public:
/** @brief Matrix type */
typedef typename DimensionTraits<dimensions, T>::MatrixType MatrixType;
/** @brief Feature object type */
typedef AbstractBasicFeature<dimensions, T> FeatureType;
typedef AbstractFeature<dimensions, T> FeatureType;
explicit AbstractObject();
virtual ~AbstractObject();
/** @brief Whether this object has features */
bool hasFeatures() const {
return !Containers::LinkedList<AbstractBasicFeature<dimensions, T>>::isEmpty();
return !Containers::LinkedList<AbstractFeature<dimensions, T>>::isEmpty();
}
/** @brief First object feature or `nullptr`, if this object has no features */
FeatureType* firstFeature() {
return Containers::LinkedList<AbstractBasicFeature<dimensions, T>>::first();
return Containers::LinkedList<AbstractFeature<dimensions, T>>::first();
}
/** @overload */
const FeatureType* firstFeature() const {
return Containers::LinkedList<AbstractBasicFeature<dimensions, T>>::first();
return Containers::LinkedList<AbstractFeature<dimensions, T>>::first();
}
/** @brief Last object feature or `nullptr`, if this object has no features */
FeatureType* lastFeature() {
return Containers::LinkedList<AbstractBasicFeature<dimensions, T>>::last();
return Containers::LinkedList<AbstractFeature<dimensions, T>>::last();
}
/** @overload */
const FeatureType* lastFeature() const {
return Containers::LinkedList<AbstractBasicFeature<dimensions, T>>::last();
return Containers::LinkedList<AbstractFeature<dimensions, T>>::last();
}
/**

4
src/SceneGraph/Animable.h

@ -138,9 +138,9 @@ Animable.hpp implementation file to avoid linker errors. See also
- @ref Animable "Animable<3, Float>", @ref AnimableGroup "AnimableGroup<3, Float>"
@see @ref scenegraph, @ref BasicAnimable2D, @ref BasicAnimable3D,
@ref Animable2D, @ref Animable3D
@ref Animable2D, @ref Animable3D, @ref AnimableGroup
*/
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT Animable: public AbstractBasicGroupedFeature<dimensions, Animable<dimensions, T>, T> {
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT Animable: public AbstractGroupedFeature<dimensions, Animable<dimensions, T>, T> {
friend class AnimableGroup<dimensions, T>;
public:

6
src/SceneGraph/Animable.hpp

@ -35,7 +35,7 @@
namespace Magnum { namespace SceneGraph {
template<UnsignedInt dimensions, class T> Animable<dimensions, T>::Animable(AbstractObject<dimensions, T>* object, AnimableGroup<dimensions, T>* group): AbstractBasicGroupedFeature<dimensions, Animable<dimensions, T>, T>(object, group), _duration(0.0f), startTime(std::numeric_limits<Float>::infinity()), pauseTime(-std::numeric_limits<Float>::infinity()), previousState(AnimationState::Stopped), currentState(AnimationState::Stopped), _repeated(false), _repeatCount(0), repeats(0) {}
template<UnsignedInt dimensions, class T> Animable<dimensions, T>::Animable(AbstractObject<dimensions, T>* object, AnimableGroup<dimensions, T>* group): AbstractGroupedFeature<dimensions, Animable<dimensions, T>, T>(object, group), _duration(0.0f), startTime(std::numeric_limits<Float>::infinity()), pauseTime(-std::numeric_limits<Float>::infinity()), previousState(AnimationState::Stopped), currentState(AnimationState::Stopped), _repeated(false), _repeatCount(0), repeats(0) {}
template<UnsignedInt dimensions, class T> Animable<dimensions, T>::~Animable() {}
@ -53,11 +53,11 @@ template<UnsignedInt dimensions, class T> Animable<dimensions, T>* Animable<dime
}
template<UnsignedInt dimensions, class T> AnimableGroup<dimensions, T>* Animable<dimensions, T>::group() {
return static_cast<AnimableGroup<dimensions, T>*>(AbstractBasicGroupedFeature<dimensions, Animable<dimensions, T>, T>::group());
return static_cast<AnimableGroup<dimensions, T>*>(AbstractGroupedFeature<dimensions, Animable<dimensions, T>, T>::group());
}
template<UnsignedInt dimensions, class T> const AnimableGroup<dimensions, T>* Animable<dimensions, T>::group() const {
return static_cast<const AnimableGroup<dimensions, T>*>(AbstractBasicGroupedFeature<dimensions, Animable<dimensions, T>, T>::group());
return static_cast<const AnimableGroup<dimensions, T>*>(AbstractGroupedFeature<dimensions, Animable<dimensions, T>, T>::group());
}
template<UnsignedInt dimensions, class T> void AnimableGroup<dimensions, T>::step(const Float time, const Float delta) {

2
src/SceneGraph/AnimableGroup.h

@ -41,7 +41,7 @@ See Animable for more information.
@see @ref scenegraph, @ref BasicAnimableGroup2D, @ref BasicAnimableGroup3D,
@ref AnimableGroup2D, @ref AnimableGroup3D
*/
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AnimableGroup: public BasicFeatureGroup<dimensions, Animable<dimensions, T>, T> {
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AnimableGroup: public FeatureGroup<dimensions, Animable<dimensions, T>, T> {
friend class Animable<dimensions, T>;
public:

8
src/SceneGraph/Drawable.h

@ -116,7 +116,7 @@ void MyApplication::drawEvent() {
@see Drawable2D, Drawable3D, @ref scenegraph, DrawableGroup2D, DrawableGroup3D
*/
template<UnsignedInt dimensions, class T> class BasicDrawable: public AbstractBasicGroupedFeature<dimensions, BasicDrawable<dimensions, T>, T> {
template<UnsignedInt dimensions, class T> class BasicDrawable: public AbstractGroupedFeature<dimensions, BasicDrawable<dimensions, T>, T> {
public:
/**
* @brief Constructor
@ -126,7 +126,7 @@ template<UnsignedInt dimensions, class T> class BasicDrawable: public AbstractBa
* Adds the feature to the object and also to the group, if specified.
* Otherwise you can use BasicDrawableGroup::add().
*/
explicit BasicDrawable(AbstractObject<dimensions, T>* object, BasicDrawableGroup<dimensions, T>* drawables = nullptr): AbstractBasicGroupedFeature<dimensions, BasicDrawable<dimensions, T>, T>(object, drawables) {}
explicit BasicDrawable(AbstractObject<dimensions, T>* object, BasicDrawableGroup<dimensions, T>* drawables = nullptr): AbstractGroupedFeature<dimensions, BasicDrawable<dimensions, T>, T>(object, drawables) {}
/**
* @brief Draw the object using given camera
@ -160,9 +160,9 @@ See Drawable for more information.
@see @ref scenegraph, DrawableGroup2D, DrawableGroup3D
*/
#ifndef CORRADE_GCC46_COMPATIBILITY
template<UnsignedInt dimensions, class T> using BasicDrawableGroup = BasicFeatureGroup<dimensions, BasicDrawable<dimensions, T>, T>;
template<UnsignedInt dimensions, class T> using BasicDrawableGroup = FeatureGroup<dimensions, BasicDrawable<dimensions, T>, T>;
#else
template<UnsignedInt dimensions, class T> class BasicDrawableGroup: public BasicFeatureGroup<dimensions, BasicDrawable<dimensions, T>, T> {};
template<UnsignedInt dimensions, class T> class BasicDrawableGroup: public FeatureGroup<dimensions, BasicDrawable<dimensions, T>, T> {};
#endif
/**

87
src/SceneGraph/FeatureGroup.h

@ -25,7 +25,7 @@
*/
/** @file
* @brief Class Magnum::SceneGraph::AbstractBasicFeatureGroup, Magnum::SceneGraph::BasicFeatureGroup, alias Magnum::SceneGraph::FeatureGroup2D, Magnum::SceneGraph::FeatureGroup3D
* @brief Class Magnum::SceneGraph::AbstractFeatureGroup, Magnum::SceneGraph::FeatureGroup, alias Magnum::SceneGraph::BasicFeatureGroup2D, Magnum::SceneGraph::BasicFeatureGroup3D, Magnum::SceneGraph::FeatureGroup2D, Magnum::SceneGraph::FeatureGroup3D
*/
#include <vector>
@ -39,38 +39,39 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base for group of features
See BasicFeatureGroup.
See FeatureGroup.
*/
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicFeatureGroup {
template<UnsignedInt, class, class> friend class BasicFeatureGroup;
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractFeatureGroup {
template<UnsignedInt, class, class> friend class FeatureGroup;
explicit AbstractBasicFeatureGroup();
virtual ~AbstractBasicFeatureGroup();
explicit AbstractFeatureGroup();
virtual ~AbstractFeatureGroup();
void add(AbstractBasicFeature<dimensions, T>* feature);
void remove(AbstractBasicFeature<dimensions, T>* feature);
void add(AbstractFeature<dimensions, T>* feature);
void remove(AbstractFeature<dimensions, T>* feature);
std::vector<AbstractBasicFeature<dimensions, T>*> features;
std::vector<AbstractFeature<dimensions, T>*> features;
};
/**
@brief Group of features
See AbstractBasicGroupedFeature for more information.
@see @ref FeatureGroup2D, @ref FeatureGroup3D, @ref scenegraph
See AbstractGroupedFeature for more information.
@see @ref scenegraph, @ref BasicFeatureGroup2D, @ref BasicFeatureGroup3D,
@ref FeatureGroup2D, @ref FeatureGroup3D
*/
template<UnsignedInt dimensions, class Feature, class T> class BasicFeatureGroup: public AbstractBasicFeatureGroup<dimensions, T> {
friend class AbstractBasicGroupedFeature<dimensions, Feature, T>;
template<UnsignedInt dimensions, class Feature, class T> class FeatureGroup: public AbstractFeatureGroup<dimensions, T> {
friend class AbstractGroupedFeature<dimensions, Feature, T>;
public:
explicit BasicFeatureGroup() = default;
explicit FeatureGroup() = default;
/**
* @brief Destructor
*
* Removes all features belonging to this group, but not deletes them.
*/
~BasicFeatureGroup();
~FeatureGroup();
/** @brief Whether the group is empty */
bool isEmpty() const { return this->features.empty(); }
@ -93,9 +94,9 @@ template<UnsignedInt dimensions, class Feature, class T> class BasicFeatureGroup
* @return Pointer to self (for method chaining)
*
* If the features is part of another group, it is removed from it.
* @see remove(), AbstractBasicGroupedFeature::AbstractBasicGroupedFeature()
* @see remove(), AbstractGroupedFeature::AbstractGroupedFeature()
*/
BasicFeatureGroup<dimensions, Feature, T>* add(Feature* feature);
FeatureGroup<dimensions, Feature, T>* add(Feature* feature);
/**
* @brief Remove feature from the group
@ -104,51 +105,75 @@ template<UnsignedInt dimensions, class Feature, class T> class BasicFeatureGroup
* The feature must be part of the group.
* @see add()
*/
BasicFeatureGroup<dimensions, Feature, T>* remove(Feature* feature);
FeatureGroup<dimensions, Feature, T>* remove(Feature* feature);
};
#ifndef CORRADE_GCC46_COMPATIBILITY
/**
@brief Base feature for two-dimensional float scenes
@brief Base feature group for two-dimensional scenes
Convenience alternative to <tt>%BasicFeatureGroup<2, Feature, Float></tt>.
@note Not available on GCC < 4.7. Use <tt>%BasicFeatureGroup<2, Feature, Float></tt>
Convenience alternative to <tt>%FeatureGroup<2, Feature, T></tt>. See
AbstractGroupedFeature for more information.
@note Not available on GCC < 4.7. Use <tt>%FeatureGroup<2, Feature, T></tt>
instead.
@see @ref FeatureGroup2D, @ref BasicFeatureGroup3D
*/
template<class Feature, class T> using BasicFeatureGroup2D = FeatureGroup<2, Feature, T>;
/**
@brief Base feature group for two-dimensional float scenes
Convenience alternative to <tt>%BasicFeatureGroup2D<Feature, Float></tt>. See
AbstractGroupedFeature for more information.
@note Not available on GCC < 4.7. Use <tt>%FeatureGroup<2, Feature, Float></tt>
instead.
@see @ref FeatureGroup3D
*/
template<class Feature> using FeatureGroup2D = BasicFeatureGroup<2, Feature, Float>;
template<class Feature> using FeatureGroup2D = BasicFeatureGroup2D<Feature, Float>;
/**
@brief Base feature group for three-dimensional scenes
Convenience alternative to <tt>%FeatureGroup<3, Feature, T></tt>. See
AbstractGroupedFeature for more information.
@note Not available on GCC < 4.7. Use <tt>%FeatureGroup<3, Feature, T></tt>
instead.
@see @ref FeatureGroup3D, @ref BasicFeatureGroup2D
*/
template<class Feature, class T> using BasicFeatureGroup3D = FeatureGroup<3, Feature, T>;
/**
@brief Base feature for three-dimensional float scenes
@brief Base feature group for three-dimensional float scenes
Convenience alternative to <tt>%BasicFeatureGroup<3, Feature, Float></tt>.
Convenience alternative to <tt>%BasicFeatureGroup3D<Feature, Float></tt>. See
AbstractGroupedFeature for more information.
@note Not available on GCC < 4.7. Use <tt>%FeatureGroup<3, Feature, Float></tt>
instead.
@see @ref FeatureGroup2D
*/
template<class Feature> using FeatureGroup3D = BasicFeatureGroup<3, Feature, Float>;
template<class Feature> using FeatureGroup3D = BasicFeatureGroup3D<Feature, Float>;
#endif
template<UnsignedInt dimensions, class Feature, class T> BasicFeatureGroup<dimensions, Feature, T>::~BasicFeatureGroup() {
template<UnsignedInt dimensions, class Feature, class T> FeatureGroup<dimensions, Feature, T>::~FeatureGroup() {
for(auto i: this->features) static_cast<Feature*>(i)->_group = nullptr;
}
template<UnsignedInt dimensions, class Feature, class T> BasicFeatureGroup<dimensions, Feature, T>* BasicFeatureGroup<dimensions, Feature, T>::add(Feature* feature) {
template<UnsignedInt dimensions, class Feature, class T> FeatureGroup<dimensions, Feature, T>* FeatureGroup<dimensions, Feature, T>::add(Feature* feature) {
/* Remove from previous group */
if(feature->_group)
feature->_group->remove(feature);
/* Crossreference the feature and group together */
AbstractBasicFeatureGroup<dimensions, T>::add(feature);
AbstractFeatureGroup<dimensions, T>::add(feature);
feature->_group = this;
return this;
}
template<UnsignedInt dimensions, class Feature, class T> BasicFeatureGroup<dimensions, Feature, T>* BasicFeatureGroup<dimensions, Feature, T>::remove(Feature* feature) {
template<UnsignedInt dimensions, class Feature, class T> FeatureGroup<dimensions, Feature, T>* FeatureGroup<dimensions, Feature, T>::remove(Feature* feature) {
CORRADE_ASSERT(feature->_group == this,
"SceneGraph::AbstractBasicFeatureGroup::remove(): feature is not part of this group", this);
"SceneGraph::AbstractFeatureGroup::remove(): feature is not part of this group", this);
AbstractBasicFeatureGroup<dimensions, T>::remove(feature);
AbstractFeatureGroup<dimensions, T>::remove(feature);
feature->_group = nullptr;
return this;
}

8
src/SceneGraph/FeatureGroup.hpp

@ -34,14 +34,14 @@
namespace Magnum { namespace SceneGraph {
template<UnsignedInt dimensions, class T> AbstractBasicFeatureGroup<dimensions, T>::AbstractBasicFeatureGroup() = default;
template<UnsignedInt dimensions, class T> AbstractBasicFeatureGroup<dimensions, T>::~AbstractBasicFeatureGroup() = default;
template<UnsignedInt dimensions, class T> AbstractFeatureGroup<dimensions, T>::AbstractFeatureGroup() = default;
template<UnsignedInt dimensions, class T> AbstractFeatureGroup<dimensions, T>::~AbstractFeatureGroup() = default;
template<UnsignedInt dimensions, class T> void AbstractBasicFeatureGroup<dimensions, T>::add(AbstractBasicFeature<dimensions, T>* feature) {
template<UnsignedInt dimensions, class T> void AbstractFeatureGroup<dimensions, T>::add(AbstractFeature<dimensions, T>* feature) {
features.push_back(feature);
}
template<UnsignedInt dimensions, class T> void AbstractBasicFeatureGroup<dimensions, T>::remove(AbstractBasicFeature<dimensions, T>* feature) {
template<UnsignedInt dimensions, class T> void AbstractFeatureGroup<dimensions, T>::remove(AbstractFeature<dimensions, T>* feature) {
features.erase(std::find(features.begin(), features.end(), feature));
}

4
src/SceneGraph/Object.hpp

@ -112,7 +112,7 @@ template<class Transformation> void Object<Transformation>::setDirty() {
Object<Transformation>* self = static_cast<Object<Transformation>*>(this);
/* Make all features dirty */
for(AbstractBasicFeature<Transformation::Dimensions, typename Transformation::Type>* i = self->firstFeature(); i; i = i->nextFeature())
for(AbstractFeature<Transformation::Dimensions, typename Transformation::Type>* i = self->firstFeature(); i; i = i->nextFeature())
i->markDirty();
/* Make all children dirty */
@ -376,7 +376,7 @@ template<class Transformation> void Object<Transformation>::setClean(const typen
MatrixType matrix, invertedMatrix;
/* Clean all features */
for(AbstractBasicFeature<Transformation::Dimensions, typename Transformation::Type>* i = this->firstFeature(); i; i = i->nextFeature()) {
for(AbstractFeature<Transformation::Dimensions, typename Transformation::Type>* i = this->firstFeature(); i; i = i->nextFeature()) {
/* Cached absolute transformation, compute it if it wasn't
computed already */
if(i->cachedTransformations() & CachedTransformation::Absolute) {

35
src/SceneGraph/SceneGraph.h

@ -44,18 +44,25 @@ typedef AbstractBasicCamera<3, Float> AbstractCamera3D;
/* Enum CachedTransformation and CachedTransformations used only directly */
template<UnsignedInt, class> class AbstractBasicFeature;
typedef AbstractBasicFeature<2, Float> AbstractFeature2D;
typedef AbstractBasicFeature<3, Float> AbstractFeature3D;
template<UnsignedInt, class> class AbstractFeature;
#ifndef CORRADE_GCC46_COMPATIBILITY
template<class T> using AbstractBasicFeature2D = AbstractFeature<2, T>;
template<class T> using AbstractBasicFeature3D = AbstractFeature<3, T>;
typedef AbstractBasicFeature2D<Float> AbstractFeature2D;
typedef AbstractBasicFeature3D<Float> AbstractFeature3D;
#else
typedef AbstractFeature<2, Float> AbstractFeature2D;
typedef AbstractFeature<3, Float> AbstractFeature3D;
#endif
template<UnsignedInt, class> class AbstractBasicFeatureGroup;
typedef AbstractBasicFeatureGroup<2, Float> AbstractFeatureGroup2D;
typedef AbstractBasicFeatureGroup<3, Float> AbstractFeatureGroup3D;
/* AbstractFeatureGroup shouldn't be used directly */
template<UnsignedInt dimensions, class Derived, class T> class AbstractBasicGroupedFeature;
template<UnsignedInt, class, class> class AbstractGroupedFeature;
#ifndef CORRADE_GCC46_COMPATIBILITY
template<class Derived> using AbstractGroupedFeature2D = AbstractBasicGroupedFeature<2, Derived, Float>;
template<class Derived> using AbstractGroupedFeature3D = AbstractBasicGroupedFeature<3, Derived, Float>;
template<class Derived, class T> using AbstractBasicGroupedFeature2D = AbstractGroupedFeature<2, Derived, T>;
template<class Derived, class T> using AbstractBasicGroupedFeature3D = AbstractGroupedFeature<3, Derived, T>;
template<class Derived> using AbstractGroupedFeature2D = AbstractBasicGroupedFeature2D<Derived, Float>;
template<class Derived> using AbstractGroupedFeature3D = AbstractBasicGroupedFeature3D<Derived, Float>;
#endif
template<UnsignedInt, class> class AbstractObject;
@ -123,14 +130,16 @@ template<class> class BasicDualQuaternionTransformation;
typedef BasicDualComplexTransformation<Float> DualComplexTransformation;
typedef BasicDualQuaternionTransformation<Float> DualQuaternionTransformation;
template<UnsignedInt dimensions, class Feature, class T> class BasicFeatureGroup;
template<UnsignedInt, class, class> class FeatureGroup;
#ifndef CORRADE_GCC46_COMPATIBILITY
template<class Feature> using BasicFeatureGroup2D = BasicFeatureGroup<2, Feature, Float>;
template<class Feature> using BasicFeatureGroup3D = BasicFeatureGroup<3, Feature, Float>;
template<class Feature, class T> using BasicFeatureGroup2D = FeatureGroup<2, Feature, T>;
template<class Feature, class T> using BasicFeatureGroup3D = FeatureGroup<3, Feature, T>;
template<class Feature> using FeatureGroup2D = BasicFeatureGroup2D<Feature, Float>;
template<class Feature> using FeatureGroup3D = BasicFeatureGroup3D<Feature, Float>;
#endif
#ifndef CORRADE_GCC46_COMPATIBILITY
template<UnsignedInt dimensions, class T> using BasicDrawableGroup = BasicFeatureGroup<dimensions, BasicDrawable<dimensions, T>, T>;
template<UnsignedInt dimensions, class T> using BasicDrawableGroup = FeatureGroup<dimensions, BasicDrawable<dimensions, T>, T>;
#else
template<UnsignedInt, class> class BasicDrawableGroup;
#endif

8
src/SceneGraph/instantiation.cpp

@ -42,10 +42,10 @@ template class MAGNUM_SCENEGRAPH_EXPORT AbstractObject<3, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicTransformation<2, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicTransformation<3, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicFeature<2, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicFeature<3, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicFeatureGroup<2, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractBasicFeatureGroup<3, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractFeature<2, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractFeature<3, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractFeatureGroup<2, Float>;
template class MAGNUM_SCENEGRAPH_EXPORT AbstractFeatureGroup<3, Float>;
template class AbstractBasicCamera<2, Float>;
template class AbstractBasicCamera<3, Float>;

6
src/Shapes/AbstractShape.cpp

@ -31,16 +31,16 @@
namespace Magnum { namespace Shapes {
template<UnsignedInt dimensions> AbstractShape<dimensions>::AbstractShape(SceneGraph::AbstractObject<dimensions, Float>* object, ShapeGroup<dimensions>* group): SceneGraph::AbstractBasicGroupedFeature<dimensions, AbstractShape<dimensions>, Float>(object, group) {
template<UnsignedInt dimensions> AbstractShape<dimensions>::AbstractShape(SceneGraph::AbstractObject<dimensions, Float>* object, ShapeGroup<dimensions>* group): SceneGraph::AbstractGroupedFeature<dimensions, AbstractShape<dimensions>, Float>(object, group) {
this->setCachedTransformations(SceneGraph::CachedTransformation::Absolute);
}
template<UnsignedInt dimensions> ShapeGroup<dimensions>* AbstractShape<dimensions>::group() {
return static_cast<ShapeGroup<dimensions>*>(SceneGraph::AbstractBasicGroupedFeature<dimensions, AbstractShape<dimensions>, Float>::group());
return static_cast<ShapeGroup<dimensions>*>(SceneGraph::AbstractGroupedFeature<dimensions, AbstractShape<dimensions>, Float>::group());
}
template<UnsignedInt dimensions> const ShapeGroup<dimensions>* AbstractShape<dimensions>::group() const {
return static_cast<const ShapeGroup<dimensions>*>(SceneGraph::AbstractBasicGroupedFeature<dimensions, AbstractShape<dimensions>, Float>::group());
return static_cast<const ShapeGroup<dimensions>*>(SceneGraph::AbstractGroupedFeature<dimensions, AbstractShape<dimensions>, Float>::group());
}
template<UnsignedInt dimensions> auto AbstractShape<dimensions>::type() const -> Type {

2
src/Shapes/AbstractShape.h

@ -49,7 +49,7 @@ This class is not directly instantiable, see Shape instead. See @ref shapes for
brief introduction.
@see AbstractShape2D, AbstractShape3D
*/
template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT AbstractShape: public SceneGraph::AbstractBasicGroupedFeature<dimensions, AbstractShape<dimensions>, Float> {
template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT AbstractShape: public SceneGraph::AbstractGroupedFeature<dimensions, AbstractShape<dimensions>, Float> {
friend const Implementation::AbstractShape<dimensions>* Implementation::getAbstractShape<>(const AbstractShape<dimensions>*);
public:

2
src/Shapes/ShapeGroup.h

@ -43,7 +43,7 @@ namespace Magnum { namespace Shapes {
See Shape for more information. See @ref shapes for brief introduction.
@see @ref scenegraph, ShapeGroup2D, ShapeGroup3D
*/
template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT ShapeGroup: public SceneGraph::BasicFeatureGroup<dimensions, AbstractShape<dimensions>, Float> {
template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT ShapeGroup: public SceneGraph::FeatureGroup<dimensions, AbstractShape<dimensions>, Float> {
friend class AbstractShape<dimensions>;
public:

Loading…
Cancel
Save