You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
8.3 KiB

#ifndef Magnum_SceneGraph_Object_h
#define Magnum_SceneGraph_Object_h
/*
15 years ago
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
14 years ago
/**
@brief %Object
14 years ago
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
14 years ago
* @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();
}
14 years ago
/**
* @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()
14 years ago
*/
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