Nebula
Loading...
Searching...
No Matches
attributeregistry.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
9//------------------------------------------------------------------------------
10#include "attribute.h"
11#include "util/stringatom.h"
12
13namespace MemDb
14{
15
17{
18public:
20 template<typename TYPE>
21 static AttributeId Register(Util::StringAtom name, TYPE defaultValue, uint32_t flags = 0);
22
23 template <typename TYPE>
24 static AttributeId Register(Attribute* attribute);
25
27 template <typename TYPE>
28 static bool IsRegistered();
29
31 static AttributeId Register(Util::StringAtom name, SizeT typeSize, void const* defaultValue, uint32_t flags = 0);
32
36 static Attribute* GetAttribute(AttributeId descriptor);
38 static SizeT TypeSize(AttributeId descriptor);
40 static uint32_t Flags(AttributeId descriptor);
42 static void const* const DefaultValue(AttributeId descriptor);
45
46private:
48 static void Destroy();
49
52
54
57};
58
60uint16_t GenerateNewAttributeId();
61
62//------------------------------------------------------------------------------
65template <typename ATTRIBUTE>
68{
69 static_assert(!std::is_polymorphic<ATTRIBUTE>(), "ATTRIBUTE must not be polymorpic.");
70 static_assert(!std::is_abstract<ATTRIBUTE>(), "ATTRIBUTE must not be abstract.");
71 static const uint16_t id = MemDb::GenerateNewAttributeId();
72 return AttributeId(id);
73}
74
75//------------------------------------------------------------------------------
78template<typename TYPE>
79inline bool
81{
82 auto* reg = Instance();
84 if (id < reg->componentDescriptions.Size())
85 {
86 return reg->componentDescriptions[id.id] != nullptr;
87 }
88 return false;
89}
90
91//------------------------------------------------------------------------------
98template<typename TYPE>
99inline AttributeId
100AttributeRegistry::Register(Util::StringAtom name, TYPE defaultValue, uint32_t flags)
101{
102 // Special case for string atoms since they actually are trivial to copy and destroy
103 //if constexpr (!std::is_same<TYPE, Util::StringAtom>())
104 //{
105 // static_assert(std::is_trivially_copyable<TYPE>(), "TYPE must be trivially copyable.");
106 // static_assert(std::is_trivially_destructible<TYPE>(), "TYPE must be trivially destructible.");
107 //}
108
109 static_assert(!std::is_polymorphic<TYPE>(), "TYPE must not be polymorpic.");
110 static_assert(!std::is_abstract<TYPE>(), "TYPE must not be abstract.");
111
112 auto* reg = Instance();
113 if (!reg->registry.Contains(name))
114 {
115 // setup a state description with the default values from the type
116 Attribute* desc = new Attribute(name, defaultValue, flags);
117
119 if (descriptor.id >= reg->componentDescriptions.Size())
120 {
121 SizeT prevSize = reg->componentDescriptions.Size();
122 reg->componentDescriptions.Resize(descriptor.id + 1); // fixed increment
123 SizeT num = reg->componentDescriptions.Size() - prevSize;
124 reg->componentDescriptions.Fill(prevSize, num, nullptr); // make sure new entries are null, since we use this to check if attributes are registered or not.
125 }
126
127 reg->componentDescriptions[descriptor.id] = desc;
128 reg->registry.Add(name, descriptor);
129
130 return descriptor;
131 }
132 else
133 {
134 n_error("Tried to register component named %s: Cannot register two components with same name!", name.Value());
135 }
136
137 return AttributeId::Invalid();
138}
139
140
141//------------------------------------------------------------------------------
144template <typename TYPE>
145inline AttributeId
147{
148 static_assert(!std::is_polymorphic<TYPE>(), "TYPE must not be polymorpic.");
149 static_assert(!std::is_abstract<TYPE>(), "TYPE must not be abstract.");
150
151 auto* reg = Instance();
152 if (!reg->registry.Contains(desc->name))
153 {
155 if (attrId.id >= reg->componentDescriptions.Size())
156 {
157 SizeT prevSize = reg->componentDescriptions.Size();
158 reg->componentDescriptions.Resize(attrId.id + 1); // fixed increment
159 SizeT num = reg->componentDescriptions.Size() - prevSize;
160 reg->componentDescriptions.Fill(
161 prevSize, num, nullptr
162 ); // make sure new entries are null, since we use this to check if attributes are registered or not.
163 }
164
165 reg->componentDescriptions[attrId.id] = desc;
166 reg->registry.Add(desc->name, attrId);
167
168 return attrId;
169 }
170 else
171 {
172 n_error("Tried to register component named %s: Cannot register two components with same name!", desc->name.Value());
173 }
174
175 return AttributeId::Invalid();
176}
177
178//------------------------------------------------------------------------------
181inline AttributeId
182AttributeRegistry::Register(Util::StringAtom name, SizeT typeSize, void const* defaultValue, uint32_t flags)
183{
184 auto* reg = Instance();
185 if (!reg->registry.Contains(name))
186 {
187 // setup a state description with the default values from the type
188 Attribute* desc = new Attribute(name, typeSize, defaultValue, flags);
189
191 if (descriptor.id >= reg->componentDescriptions.Size())
192 {
193 reg->componentDescriptions.Resize(descriptor.id + 1);
194
195 }
196
197 reg->componentDescriptions[descriptor.id] = desc;
198 reg->registry.Add(name, descriptor);
199 return descriptor;
200 }
201 else
202 {
203 n_error("Tried to register component named %s: Cannot register two components with same name!", name.Value());
204 }
205
206 return AttributeId::Invalid();
207}
208
209//------------------------------------------------------------------------------
212inline AttributeId
214{
215 auto* reg = Instance();
216 IndexT index = reg->registry.FindIndex(name);
217 if (index != InvalidIndex)
218 {
219 return reg->registry.ValueAtIndex(index);
220 }
221
222 return AttributeId::Invalid();
223}
224
225//------------------------------------------------------------------------------
228inline Attribute*
230{
231 auto* reg = Instance();
232 if (descriptor.id >= 0 && descriptor.id < reg->componentDescriptions.Size())
233 {
234 n_assert2(
235 reg->componentDescriptions[descriptor.id] != nullptr, "Trying to get description of attribute that is not registered!"
236 );
237 return reg->componentDescriptions[descriptor.id];
238 }
239
240 return nullptr;
241}
242
243//------------------------------------------------------------------------------
246inline SizeT
248{
249 auto* reg = Instance();
250 n_assert(descriptor.id >= 0 && descriptor.id < reg->componentDescriptions.Size());
251 return reg->componentDescriptions[descriptor.id]->typeSize;
252}
253
254//------------------------------------------------------------------------------
257inline uint32_t
259{
260 auto* reg = Instance();
261 n_assert(descriptor.id >= 0 && descriptor.id < reg->componentDescriptions.Size());
262 return reg->componentDescriptions[descriptor.id]->externalFlags;
263}
264
265//------------------------------------------------------------------------------
268inline void const* const
270{
271 auto* reg = Instance();
272 n_assert(descriptor.id >= 0 && descriptor.id < reg->componentDescriptions.Size());
273 return reg->componentDescriptions[descriptor.id]->defVal;
274}
275
276//------------------------------------------------------------------------------
281{
282 auto* reg = Instance();
283 return reg->componentDescriptions;
284}
285
286} // namespace MemDb
Definition attribute.h:29
Util::StringAtom name
name of attribute
Definition attribute.h:49
Util::FixedArray< Attribute * > componentDescriptions
Definition attributeregistry.h:55
static AttributeId Register(Util::StringAtom name, TYPE defaultValue, uint32_t flags=0)
register a type (templated)
Definition attributeregistry.h:100
static AttributeRegistry * Instance()
The registry's constructor is called by the Instance() method, and nobody else.
Definition attributeregistry.cc:18
static uint32_t Flags(AttributeId descriptor)
get flags by attribute id
Definition attributeregistry.h:258
~AttributeRegistry()
Definition attributeregistry.cc:55
Util::Dictionary< Util::StringAtom, AttributeId > registry
Definition attributeregistry.h:56
static void const *const DefaultValue(AttributeId descriptor)
get attribute default value pointer
Definition attributeregistry.h:269
AttributeRegistry()
Definition attributeregistry.cc:47
static AttributeId GetAttributeId(Util::StringAtom name)
get attribute id from name
Definition attributeregistry.h:213
static void Destroy()
This static method is used to destroy the registry object and should be called right before the main ...
Definition attributeregistry.cc:35
static SizeT TypeSize(AttributeId descriptor)
get type size by attribute id
Definition attributeregistry.h:247
static Util::FixedArray< Attribute * > const & GetAllAttributes()
get an array of all attributes
Definition attributeregistry.h:280
static Attribute * GetAttribute(AttributeId descriptor)
get attribute description by id
Definition attributeregistry.h:229
static AttributeRegistry * Singleton
Definition attributeregistry.h:53
static bool IsRegistered()
Check if a type is registered.
Definition attributeregistry.h:80
A collection of key/value pairs with quick value retrieval by key at roughly O(log n).
Definition dictionary.h:34
Implements a fixed size one-dimensional array.
Definition fixedarray.h:20
A StringAtom.
Definition stringatom.h:22
const char * Value() const
get contained string as char ptr (fast)
Definition stringatom.h:362
void __cdecl n_error(const char *msg,...)
This function is called when a serious situation is encountered which requires abortion of the applic...
Definition debug.cc:138
#define n_assert2(exp, msg)
Definition debug.h:51
#define n_assert(exp)
Definition debug.h:50
Attribute.
Definition attribute.h:26
uint16_t GenerateNewAttributeId()
Do not use.
Definition attributeregistry.cc:65
AttributeId GetAttributeId()
Definition attributeregistry.h:67
Definition attributeid.h:19
static const int InvalidIndex
Definition types.h:47
int SizeT
Definition types.h:42
int IndexT
Definition types.h:41