-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathentityfactory.hpp
More file actions
136 lines (130 loc) · 7.05 KB
/
entityfactory.hpp
File metadata and controls
136 lines (130 loc) · 7.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#pragma once
#include <fea/config.hpp>
#include <fea/entity/entitymanager.hpp>
#include <fea/entity/entitytemplate.hpp>
#include <fea/entity/entity.hpp>
#include <functional>
namespace fea
{
using Parameters = std::vector<std::string>;
using Setter = std::function<void(EntityPtr&)>;
using Parser = std::function<Setter(const std::string&)>;
using Registrator = std::function<Parser(const std::string&)>;
class FEA_API EntityFactory
{
public:
EntityFactory(EntityManager& entityManager);
template<typename Function>
void addDataType(const std::string& dataTypeName, Function parser);
template<typename Type>
void addDataType(const std::string& dataTypeName);
void registerAttribute(const std::string& attribute, const std::string& dataType);
void addTemplate(const std::string& name, const EntityTemplate& entityTemplate);
bool hasTemplate(const std::string& name) const;
WeakEntityPtr instantiate(const std::string& name);
private:
Parameters splitByDelimeter(const std::string& in, char delimeter) const;
struct Prototype
{
struct Value
{
bool operator<(const Value& other) const;
std::string mKey;
Setter mSetter;
};
std::set<std::string> attributes;
std::set<Value> values;
};
std::unordered_map<std::string, Prototype> mPrototypes;
std::unordered_map<std::string, Parser> mParsers;
std::unordered_map<std::string, Registrator> mRegistrators;
EntityManager& mManager;
};
#include <fea/entity/entityfactory.inl>
/** @addtogroup EntitySystem
*@{
* @class EntityFactory
*@}
***
* @class EntityFactory
* @brief Can create predefined entities based on entity templates.
*
* Entity templates help you create entities easier without having to specify all attributes manually every time. This is done using entity templates. A template has a name and a list of attributes and default values. For instance, this can be a template (in JSON format):
* @code
* "turtle":
* {
* "health":"140", "position":"0.0f,0.0f", "velocity":"0.0f,0.0f", "maxvelocity":"5.5f", "collisiontype":"solid"
* }
* @endcode
*
* This template describing a turtle entity has five attributes: health, position, velocity, maxvelocity and collisiontype. All of the attributes have to be registered at the entity manager. The numerical values next to the attribute names are their default values. These are the values that the attributes of a created turtle entity will attain. To give default values to an attribute, a parser function must be provided to the data type registration.
*
* This class needs a reference to an EntityManager instance.
***
* @fn EntityFactory::EntityFactory(EntityManager& entityManager)
* @brief Construct an EntityFactory.
* @param entityManager EntityManager to use.
***
* @fn void EntityFactory::addDataType(const std::string& dataTypeName, Function parser)
* @brief Add a data type with a parser to the entity factory.
*
* To be able to register any attributes, data types must first be added. Data types are the basic types that attributes can have. For example, you can have the attributes "position" and "velocity" which are both of the data type "vec2". By adding a data type with a parser, entity templates can be given comma separated default values. This code shows how to add the type glm::vec2 as "vec2" with a reasonable parser.
* @code
* factory.addDataType("vec2", [](const fea::Parameters& params)
* {
* FEA_ASSERT(params.size() == 2, "Wrong amount of parameters! Expected 2, got " + std::to_string(params.size()) + "!"); //Make sure the right amount of paramters are provided.
* return glm::vec2({std::stof(params[0]), std::stof(params[1])});
* });
* @endcode
*
* "vec2" is now a valid data type and can be used to register attributes using the EntityFactory::registerAttribute method.
*
* Assert/undefined behavior if the data type name already exists.
* @tparam Parser function. Can often be inferred automatically.
* @param dataTypeName Name of the data type.
* @param parser Parser function. Should return a valid instance of the type.
***
* @fn void EntityFactory::addDataType(const std::string& dataTypeName)
* @brief Add a data type without a parser to the entity factory.
*
* See EntityFactory::addDataType(const std::string& dataTypeName, Function parser) for more information.
*
* Assert/undefined behavior if the data type name already exists.
* @tparam Type Type of attribute to add.
* @param dataTypeName Name of the data type.
***
* @fn void EntityFactory::registerAttribute(const std::string& attribute, const std::string& dataType)
* @brief Register an attribute as a data type.
*
* Before any attribute is used, it has to be registered using this function. This will also register the attribute with the underlying EntityManager. The type provided must have been previously added using EntityFactory::addDataType. Example usage:
* @code
* factory.registerAttribute("position", "vec2"); //vec2 must have been previously added
* @endcode
*
* Assert/undefined behavior if the attribute name already exists or if the data type does not exist.
* @param attribute Name of the attribute.
* @param dataType Which type to register the attribute as.
***
* @fn void EntityFactory::addTemplate(const std::string& name, const EntityTemplate& entityTemplate)
* @brief Add an EntityTemplate.
*
* Assert/undefined behavior if the template already exists, contains invalid attributes or tries to inherit from an invalid template.
* @param name Name of the template.
* @param entityTemplate Template.
***
* @fn bool EntityFactory::hasTemplate(const std::string& name) const
* @brief Check if a template has been added.
* @param name Name of the template.
* @return True if it exists.
***
* @fn WeakEntityPtr EntityFactory::instantiate(const std::string& name)
* @brief Create an Entity from the given template.
*
* The template given must have been registered prior to creating the Entity. If the function succeeds in creating the Entity, it will be assigned a unique ID and a WeakEntityPtr pointing to the Entity will be returned. The returned pointer is not meant to be stored in a locked state since that entity would still become invalid if the entity is deleted using the EntityManager::removeEntity method.
*
* Assert/undefined behavior if the template given does not exist.
*
* @param name The name of the template to instantiate.
* @return A pointer to the created Entity.
***/
}