|
|
|
|
#ifndef Magnum_SceneGraph_Object_h
|
|
|
|
|
#define Magnum_SceneGraph_Object_h
|
|
|
|
|
/*
|
|
|
|
|
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
|
|
|
|
|
|
|
|
|
|
This file is part of Magnum.
|
|
|
|
|
|
|
|
|
|
Magnum is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU Lesser General Public License version 3
|
|
|
|
|
only, as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
|
|
Magnum is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU Lesser General Public License version 3 for more details.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** @file
|
|
|
|
|
* @brief Class Magnum::SceneGraph::Object
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <Containers/EnumSet.h>
|
|
|
|
|
|
|
|
|
|
#include "AbstractFeature.h"
|
|
|
|
|
#include "AbstractObject.h"
|
|
|
|
|
|
|
|
|
|
#include "magnumSceneGraphVisibility.h"
|
|
|
|
|
|
|
|
|
|
namespace Magnum { namespace SceneGraph {
|
|
|
|
|
|
|
|
|
|
template<class Transformation> class Scene;
|
|
|
|
|
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
namespace Implementation {
|
|
|
|
|
enum class ObjectFlag: std::uint8_t {
|
|
|
|
|
Dirty = 1 << 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef Corrade::Containers::EnumSet<ObjectFlag, std::uint8_t> ObjectFlags;
|
|
|
|
|
|
|
|
|
|
CORRADE_ENUMSET_OPERATORS(ObjectFlags)
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief %Object
|
|
|
|
|
|
|
|
|
|
Base of scene graph. Contains specific transformation implementation, takes
|
|
|
|
|
care of parent/children relationships and contains features. See
|
|
|
|
|
@ref scenegraph for introduction.
|
|
|
|
|
|
|
|
|
|
@section Object-explicit-specializations Explicit template specializations
|
|
|
|
|
|
|
|
|
|
The following specialization are explicitly compiled into SceneGraph library.
|
|
|
|
|
For other specializations you have to use Object.hpp implementation file to
|
|
|
|
|
avoid linker errors. See @ref compilation-speedup-hpp for more information.
|
|
|
|
|
|
|
|
|
|
- @ref MatrixTransformation2D "Object<MatrixTransformation2D<>>"
|
|
|
|
|
- @ref MatrixTransformation3D "Object<MatrixTransformation3D<>>"
|
|
|
|
|
|
|
|
|
|
@see Scene, AbstractFeature, AbstractTransformation
|
|
|
|
|
*/
|
|
|
|
|
template<class Transformation> class Object: public AbstractObject<Transformation::Dimensions, typename Transformation::Type>, public Transformation
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
, private Corrade::Containers::LinkedList<Object<Transformation>>, private Corrade::Containers::LinkedListItem<Object<Transformation>, Object<Transformation>>
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
friend class Corrade::Containers::LinkedList<Object<Transformation>>;
|
|
|
|
|
friend class Corrade::Containers::LinkedListItem<Object<Transformation>, Object<Transformation>>;
|
|
|
|
|
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
|
|
|
|
Object(const Object<Transformation>& other) = delete;
|
|
|
|
|
Object(Object<Transformation>&& other) = delete;
|
|
|
|
|
Object<Transformation>& operator=(const Object<Transformation>& other) = delete;
|
|
|
|
|
Object<Transformation>& operator=(Object<Transformation>&& other) = delete;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Constructor
|
|
|
|
|
* @param parent Parent object
|
|
|
|
|
*/
|
|
|
|
|
inline Object(Object<Transformation>* parent = nullptr): flags(Flag::Dirty) {
|
|
|
|
|
setParent(parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Destructor
|
|
|
|
|
*
|
|
|
|
|
* Removes itself from parent's children list and destroys all own
|
|
|
|
|
* children.
|
|
|
|
|
*/
|
|
|
|
|
inline virtual ~Object() {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @{ @name Scene hierarchy
|
|
|
|
|
*
|
|
|
|
|
* See @ref scenegraph-hierarchy for more information.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** @brief Whether this object is scene */
|
|
|
|
|
virtual inline bool isScene() const { return false; }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief %Scene
|
|
|
|
|
* @return %Scene or `nullptr`, if the object is not part of any scene.
|
|
|
|
|
*/
|
|
|
|
|
Scene<Transformation>* scene();
|
|
|
|
|
|
|
|
|
|
/** @overload */
|
|
|
|
|
const Scene<Transformation>* scene() const;
|
|
|
|
|
|
|
|
|
|
/** @brief Parent object or `nullptr`, if this is root object */
|
|
|
|
|
inline Object<Transformation>* parent() {
|
|
|
|
|
return Corrade::Containers::LinkedListItem<Object<Transformation>, Object<Transformation>>::list();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @overload */
|
|
|
|
|
inline const Object<Transformation>* parent() const {
|
|
|
|
|
return Corrade::Containers::LinkedListItem<Object<Transformation>, Object<Transformation>>::list();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @brief Previous sibling object or `nullptr`, if this is first object */
|
|
|
|
|
inline Object<Transformation>* previousSibling() {
|
|
|
|
|
return Corrade::Containers::LinkedListItem<Object<Transformation>, Object<Transformation>>::previous();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @overload */
|
|
|
|
|
inline const Object<Transformation>* previousSibling() const {
|
|
|
|
|
return Corrade::Containers::LinkedListItem<Object<Transformation>, Object<Transformation>>::previous();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @brief Next sibling object or `nullptr`, if this is last object */
|
|
|
|
|
inline Object<Transformation>* nextSibling() {
|
|
|
|
|
return Corrade::Containers::LinkedListItem<Object<Transformation>, Object<Transformation>>::next();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @overload */
|
|
|
|
|
inline const Object<Transformation>* nextSibling() const {
|
|
|
|
|
return Corrade::Containers::LinkedListItem<Object<Transformation>, Object<Transformation>>::next();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @brief Whether this object has children */
|
|
|
|
|
inline bool hasChildren() const {
|
|
|
|
|
return !Corrade::Containers::LinkedList<Object<Transformation>>::isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @brief First child object or `nullptr`, if this object has no children */
|
|
|
|
|
inline Object<Transformation>* firstChild() {
|
|
|
|
|
return Corrade::Containers::LinkedList<Object<Transformation>>::first();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @overload */
|
|
|
|
|
inline const Object<Transformation>* firstChild() const {
|
|
|
|
|
return Corrade::Containers::LinkedList<Object<Transformation>>::first();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @brief Last child object or `nullptr`, if this object has no children */
|
|
|
|
|
inline Object<Transformation>* lastChild() {
|
|
|
|
|
return Corrade::Containers::LinkedList<Object<Transformation>>::last();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @overload */
|
|
|
|
|
inline const Object<Transformation>* lastChild() const {
|
|
|
|
|
return Corrade::Containers::LinkedList<Object<Transformation>>::last();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set parent object
|
|
|
|
|
* @return Pointer to self (for method chaining)
|
|
|
|
|
*/
|
|
|
|
|
Object<Transformation>* setParent(Object<Transformation>* parent);
|
|
|
|
|
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
/** @{ @name Object transformation */
|
|
|
|
|
|
|
|
|
|
inline typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType absoluteTransformationMatrix() const override {
|
|
|
|
|
return Transformation::toMatrix(absoluteTransformation());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Transformation relative to root object
|
|
|
|
|
*
|
|
|
|
|
* @see absoluteTransformationMatrix()
|
|
|
|
|
*/
|
|
|
|
|
typename Transformation::DataType absoluteTransformation() const;
|
|
|
|
|
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @{ @name Transformation caching
|
|
|
|
|
*
|
|
|
|
|
* See @ref scenegraph-caching for more information.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Whether absolute transformation is dirty
|
|
|
|
|
*
|
|
|
|
|
* Returns `true` if transformation of the object or any parent has
|
|
|
|
|
* changed since last call to setClean(), `false` otherwise.
|
|
|
|
|
*
|
|
|
|
|
* All objects are dirty by default.
|
|
|
|
|
*
|
|
|
|
|
* @see @ref scenegraph-caching
|
|
|
|
|
*/
|
|
|
|
|
inline bool isDirty() const { return !!(flags & Flag::Dirty); }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set object absolute transformation as dirty
|
|
|
|
|
*
|
|
|
|
|
* Calls AbstractFeature::markDirty() on all object features and
|
|
|
|
|
* recursively calls setDirty() on every child object which is not
|
|
|
|
|
* already dirty. If the object is already marked as dirty, the
|
|
|
|
|
* function does nothing.
|
|
|
|
|
* @see @ref scenegraph-caching, setClean(), isDirty()
|
|
|
|
|
*/
|
|
|
|
|
void setDirty();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Clean object absolute transformation
|
|
|
|
|
*
|
|
|
|
|
* Calls AbstractFeature::clean() and/or AbstractFeature::cleanInverted()
|
|
|
|
|
* on all object features which have caching enabled and recursively
|
|
|
|
|
* calls setClean() on every parent which is not already clean. If the
|
|
|
|
|
* object is already clean, the function does nothing.
|
|
|
|
|
* @see @ref scenegraph-caching, setDirty(), isDirty()
|
|
|
|
|
*/
|
|
|
|
|
void setClean();
|
|
|
|
|
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef Implementation::ObjectFlag Flag;
|
|
|
|
|
typedef Implementation::ObjectFlags Flags;
|
|
|
|
|
Flags flags;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
#endif
|