#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2013 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library 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
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion // CPL License
#ifndef NUCLEX_SCENE_GRAPH_ENTITY_H
#define NUCLEX_SCENE_GRAPH_ENTITY_H
#include "Nuclex/Scene/Config.h"
#include "Nuclex/Scene/Graph/ComponentSet.h"
#include "Nuclex/Scene/Graph/ChildEntitySet.h"
namespace Nuclex { namespace Scene { namespace Graph {
// ------------------------------------------------------------------------------------------- //
/// Hierarchical container that houses a number of components
///
///
/// Entities form a tree and can store components. Components can be anything, from
/// primitive data types such as an integer to POD types or objects from a third-party
/// library.
///
///
/// Typically, entities are used in one of two ways:
///
///
/// -
/// As services:
///
/// Here, the entity performs a management task and stores components that
/// provide services to other components or interface with the game itself. This
/// type of entity does not have a position, but may draw to the screen.
///
///
/// -
/// As scene nodes:
///
/// If used as a scene node, the entity has a transformation (position,
/// orientation and scale) and is used to build a hierarchical scene: there might
/// be a Car entity that has four child Wheel entities, with
/// the children's transformation typically being relative to their parent.
///
///
///
///
/// Example use case of an entity
///
/// std::shared_ptr bicycle = std::make_shared();
/// bicycle->Components.Add(std::make_unique());
///
/// bicycle->Children.Add(std::make_shared());
/// bicycle->Children.Add(std::make_shared());
///
/// for(std::shared_ptr wheel : bicycle->Children) {
/// wheel->Components.Add(std::make_unique());
/// }
///
///
///
class Entity : public std::enable_shared_from_this {
friend ChildEntitySet;
/// Components carried by the entity
public: ComponentSet Components;
/// The entity's children
public: ChildEntitySet Children;
/// Initializes a new entity
public: NUCLEX_SCENE_API Entity() : Children(*this) {}
/// Retrieves the parent of this entity, if any
/// The parent of this entity, if it has a parent
public: NUCLEX_SCENE_API Entity *GetParent() {
return this->parent;
}
/// Retrieves the parent of this entity, if any
/// The parent of this entity, if it has a parent
public: NUCLEX_SCENE_API const Entity *GetParent() const {
return this->parent;
}
/// Assigns the parent of this entity or clears it
/// Parent that will be assigned to the entity
/// The parent of this entity, if it has a parent
protected: NUCLEX_SCENE_API void SetParent(Entity *parent) {
this->parent = parent;
}
/// Registers a component that is a permanent part of the entity
/// Type of component that will be registered
/// Component that will be registered
///
///
/// While a component/entity system is data driven, sometimes you have a type of
/// entities that have to contain certain elements. A bone in a bone-animated
/// mesh for example would always have a position, orientation and scale. And sometimes,
/// you just want to reduce the number of allocations needed or allow an entity to
/// be pooled, like shots from a weapon.
///
///
/// Built-in components allow you to create special entity types that include some
/// components with them as direct members.
///
///
protected: template void RegisterBuiltInComponent(
TComponent *component
) {
this->Components.Add(
typeid(TComponent),
component,
[](void *component) { delete static_cast(component); }
);
}
/// Points to the parent entity of this entity
///
/// Not a shared_ptr because that would keep the parent alive indefinitely
/// (circular relationship) and not a weak_ptr because the parent may be used
/// inline and not have a shared_ptr pointing to it.
///
private: Entity *parent;
};
// ------------------------------------------------------------------------------------------- //
}}} // namespace Nuclex::Scene::Graph
#endif // NUCLEX_SCENE_GRAPH_ENTITY_H