Skip to content

Commit d81cbc2

Browse files
authored
feat(ECS): Added support for serialisation names
Add support for ECS serialisation names.
2 parents c0cd932 + adcd3f4 commit d81cbc2

24 files changed

+138
-84
lines changed

include/NovelRT.Interop/Ecs/NrtComponentBufferMemoryContainer.h

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extern "C"
1515
void* deleteInstructionState,
1616
size_t sizeOfDataTypeInBytes,
1717
NrtComponentUpdateFnPtr fnPtr,
18+
const char* serialisedTypeName,
1819
void* context);
1920

2021
void Nrt_ComponentBufferMemoryContainer_PrepContainerForFrame(NrtComponentBufferMemoryContainerHandle container,

include/NovelRT.Interop/Ecs/NrtComponentCache.h

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ extern "C"
1717
size_t sizeOfDataType,
1818
const void* deleteInstructionState,
1919
NrtComponentUpdateFnPtr updateFnPtr,
20+
const char* serialisedTypeName,
2021
void* context,
2122
NrtComponentTypeId* outputResult);
2223

include/NovelRT/Ecs/ComponentBuffer.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,20 @@ namespace NovelRT::Ecs
3636
*
3737
*
3838
* @param poolSize The amount of worker threads being utilised in this instance of the ECS.
39+
* @param serialisedTypeName The type name to use for serialisation of this data type.
3940
* @param deleteInstructionState The component state to treat as the delete instruction. When this state is
4041
* passed in during an update, the ComponentBuffer will delete the component from the target entity during
4142
* resolution.
4243
*/
43-
ComponentBuffer(size_t poolSize, T deleteInstructionState) noexcept
44+
ComponentBuffer(size_t poolSize, T deleteInstructionState, const std::string& serialisedTypeName) noexcept
4445
: _innerContainer(std::make_shared<ComponentBufferMemoryContainer>(
4546
poolSize,
4647
&deleteInstructionState,
4748
sizeof(T),
4849
[](auto rootComponent, auto updateComponent, auto) {
4950
*reinterpret_cast<T*>(rootComponent) += *reinterpret_cast<const T*>(updateComponent);
50-
}))
51+
},
52+
serialisedTypeName))
5153
{
5254
static_assert(std::is_trivially_copyable<T>::value,
5355
"Value type must be trivially copyable for use with a ComponentBuffer. See the documentation "
@@ -197,6 +199,16 @@ namespace NovelRT::Ecs
197199
return _innerContainer->HasComponent(entity);
198200
}
199201

202+
/**
203+
* @brief Gets the serialised type name used for the loading and unloading to and from serialised data.
204+
*
205+
* @return The serialised type name as a string.
206+
*/
207+
[[nodiscard]] const std::string& GetSerialisedTypeName() const noexcept
208+
{
209+
return _innerContainer->GetSerialisedTypeName();
210+
}
211+
200212
/**
201213
* @brief Gets the length of the current immutable data snapshot within the buffer.
202214
*

include/NovelRT/Ecs/ComponentBufferMemoryContainer.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace NovelRT::Ecs
1818
std::vector<uint8_t> _deleteInstructionState;
1919
size_t _sizeOfDataTypeInBytes;
2020
std::function<void(void*, const void*, size_t)> _componentUpdateLogic;
21+
std::string _serialisedTypeName;
2122

2223
public:
2324
class ImmutableDataView
@@ -46,7 +47,8 @@ namespace NovelRT::Ecs
4647
ComponentBufferMemoryContainer(size_t poolSize,
4748
const void* deleteInstructionState,
4849
size_t sizeOfDataTypeInBytes,
49-
std::function<void(void*, const void*, size_t)> componentUpdateLogic) noexcept;
50+
std::function<void(void*, const void*, size_t)> componentUpdateLogic,
51+
const std::string& serialisedTypeName) noexcept;
5052

5153
void PrepContainerForFrame(const std::vector<EntityId>& destroyedEntities) noexcept;
5254

@@ -61,6 +63,11 @@ namespace NovelRT::Ecs
6163

6264
[[nodiscard]] size_t GetImmutableDataLength() const noexcept;
6365

66+
[[nodiscard]] inline const std::string& GetSerialisedTypeName() const noexcept
67+
{
68+
return _serialisedTypeName;
69+
}
70+
6471
[[nodiscard]] SparseSetMemoryContainer::ConstIterator begin() const noexcept;
6572

6673
[[nodiscard]] SparseSetMemoryContainer::ConstIterator end() const noexcept;

include/NovelRT/Ecs/ComponentCache.h

+11-6
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ namespace NovelRT::Ecs
2626
std::shared_ptr<ComponentBufferMemoryContainer> CreateContainer(
2727
size_t sizeOfDataType,
2828
const void* deleteInstructionState,
29-
const std::function<void(void*, const void*, size_t)>& componentUpdateLogic) const;
29+
const std::function<void(void*, const void*, size_t)>& componentUpdateLogic,
30+
const std::string& serialisedTypeName) const;
3031

3132
public:
3233
/**
@@ -49,6 +50,7 @@ namespace NovelRT::Ecs
4950
* @param sizeOfDataType The size of the object type, in bytes.
5051
* @param deleteInstructionState The object state that indicates that the component should be deleted.
5152
* @param componentUpdateLogic The function to use for concurrent update consolidation.
53+
* @param serialisedTypeName The type name to use for data serialisation.
5254
* @return the ID of the new component type and associated ComponentBufferMemoryContainer
5355
* instance.
5456
*
@@ -58,7 +60,8 @@ namespace NovelRT::Ecs
5860
[[nodiscard]] ComponentTypeId RegisterComponentTypeUnsafe(
5961
size_t sizeOfDataType,
6062
const void* deleteInstructionState,
61-
const std::function<void(void*, const void*, size_t)>& componentUpdateLogic);
63+
const std::function<void(void*, const void*, size_t)>& componentUpdateLogic,
64+
const std::string& serialisedTypeName);
6265

6366
/**
6467
* @brief Registers a new component type to the cache.
@@ -74,12 +77,14 @@ namespace NovelRT::Ecs
7477
* @exception std::bad_alloc when a ComponentBuffer could not be allocated in memory for the given component
7578
* type.
7679
*/
77-
template<typename T> void RegisterComponentType(T deleteInstructionState)
80+
template<typename T> void RegisterComponentType(T deleteInstructionState, const std::string& serialisedTypeName)
7881
{
79-
std::shared_ptr<ComponentBufferMemoryContainer> ptr =
80-
CreateContainer(sizeof(T), &deleteInstructionState, [](auto rootComponent, auto updateComponent, auto) {
82+
std::shared_ptr<ComponentBufferMemoryContainer> ptr = CreateContainer(
83+
sizeof(T), &deleteInstructionState,
84+
[](auto rootComponent, auto updateComponent, auto) {
8185
*reinterpret_cast<T*>(rootComponent) += *reinterpret_cast<const T*>(updateComponent);
82-
});
86+
},
87+
serialisedTypeName);
8388
_bufferPrepEvent += [ptr](auto vec) { ptr->PrepContainerForFrame(vec); };
8489
_componentMap.emplace(GetComponentTypeId<T>(), ptr);
8590
}

include/NovelRT/Ecs/Configurator.h

+21-11
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,28 @@ namespace NovelRT::Ecs
2828

2929
inline void AddDefaultComponentsAndSystems(SystemScheduler& target)
3030
{
31-
target.GetComponentCache().RegisterComponentType(Graphics::RenderComponent{0, 0, 0, 0, true});
31+
target.GetComponentCache().RegisterComponentType(Graphics::RenderComponent{0, 0, 0, 0, true},
32+
"NovelRT::Ecs::Graphics::RenderComponent");
3233

33-
target.GetComponentCache().RegisterComponentType(EntityGraphComponent{
34-
false, std::numeric_limits<EntityId>::max(), std::numeric_limits<EntityId>::max()});
34+
target.GetComponentCache().RegisterComponentType(
35+
EntityGraphComponent{false, std::numeric_limits<EntityId>::max(), std::numeric_limits<EntityId>::max()},
36+
"NovelRT::Ecs::EntityGraphComponent");
3537

36-
target.GetComponentCache().RegisterComponentType(LinkedEntityListNodeComponent{
37-
false, std::numeric_limits<EntityId>::max(), std::numeric_limits<EntityId>::max()});
38+
target.GetComponentCache().RegisterComponentType(
39+
LinkedEntityListNodeComponent{false, std::numeric_limits<EntityId>::max(),
40+
std::numeric_limits<EntityId>::max()},
41+
"NovelRT::Ecs::LinkedEntityListNodeComponent");
3842

3943
target.GetComponentCache().RegisterComponentType(
40-
TransformComponent{Maths::GeoVector3F::uniform(NAN), Maths::GeoVector2F::uniform(NAN), NAN});
44+
TransformComponent{Maths::GeoVector3F::uniform(NAN), Maths::GeoVector2F::uniform(NAN), NAN},
45+
"NovelRT::Ecs::TransformComponent");
4146

4247
target.RegisterSystem(std::make_shared<Ecs::Graphics::DefaultRenderingSystem>(
4348
_graphicsPluginProvider, _windowingPluginProvider, _resourceManagementPluginProvider));
4449

4550
target.GetComponentCache().RegisterComponentType(
46-
Ecs::Input::InputEventComponent{0, NovelRT::Input::KeyState::Idle, 0, 0});
51+
Input::InputEventComponent{0, NovelRT::Input::KeyState::Idle, 0, 0},
52+
"NovelRT::Ecs::Input::InputEventComponent");
4753

4854
target.RegisterSystem(
4955
std::make_shared<Ecs::Input::InputSystem>(_windowingPluginProvider, _inputPluginProvider));
@@ -179,12 +185,14 @@ namespace NovelRT::Ecs
179185
* This is the final method you should call to obtain the ECS instance.
180186
*
181187
* @tparam TComponentTypes List of component types to register with this ECS instance.
182-
* @param deleteInstructionStates The state of the given component type that signals this component is to be
183-
* deleted to the ECS.
188+
* @tparam Names List of the names to used for type serialisation.
189+
* @param deleteInstructionStatesAndSerialisedTypeNames The state of the given component type that signals this
190+
* component is to be, accompanied by the serialised type name. deleted to the ECS.
184191
* @returns An instance of the ECS SystemScheduler root object based on the provided configuration.
185192
*/
186193
template<typename... TComponentTypes>
187-
[[nodiscard]] SystemScheduler InitialiseAndRegisterComponents(TComponentTypes... deleteInstructionStates)
194+
[[nodiscard]] SystemScheduler InitialiseAndRegisterComponents(
195+
std::tuple<TComponentTypes, std::string>... deleteInstructionStatesAndSerialisedTypeNames)
188196
{
189197
SystemScheduler scheduler(_threadCount.value_or(0));
190198

@@ -198,7 +206,9 @@ namespace NovelRT::Ecs
198206
scheduler.RegisterSystem(system);
199207
}
200208

201-
scheduler.GetComponentCache().RegisterComponentType<TComponentTypes...>(deleteInstructionStates...);
209+
scheduler.GetComponentCache().RegisterComponentType<TComponentTypes...>(
210+
std::get<0>(deleteInstructionStatesAndSerialisedTypeNames)...,
211+
std::get<1>(deleteInstructionStatesAndSerialisedTypeNames)...);
202212
scheduler.SpinThreads();
203213

204214
return scheduler;

src/NovelRT.Interop/Ecs/Audio/NrtAudioSystem.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ extern "C"
4040

4141
auto sys = reinterpret_cast<Ecs::SystemScheduler*>(system);
4242
auto deleteState = Ecs::Audio::AudioEmitterComponent();
43-
sys->GetComponentCache().RegisterComponentType(deleteState);
43+
sys->GetComponentCache().RegisterComponentType(deleteState, "NovelRT::Ecs::Audio::AudioEmitterComponent");
4444
sys->GetComponentCache().RegisterComponentType(
45-
Ecs::Audio::AudioEmitterStateComponent{Ecs::Audio::AudioEmitterState::Done});
45+
Ecs::Audio::AudioEmitterStateComponent{Ecs::Audio::AudioEmitterState::Done},
46+
"NovelRT::Ecs::Audio::AudioEmitterStateComponent");
4647
return NRT_SUCCESS;
4748
}
4849

src/NovelRT.Interop/Ecs/NrtComponentBufferMemoryContainer.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ extern "C"
1818
void* deleteInstructionState,
1919
size_t sizeOfDataTypeInBytes,
2020
NrtComponentUpdateFnPtr fnPtr,
21+
const char* serialisedTypeName,
2122
void* context)
2223
{
2324
auto func = [=](void* lhs, const void* rhs, size_t size) { fnPtr(lhs, rhs, size, context); };
2425

25-
return reinterpret_cast<NrtComponentBufferMemoryContainerHandle>(
26-
new ComponentBufferMemoryContainer(poolSize, deleteInstructionState, sizeOfDataTypeInBytes, func));
26+
return reinterpret_cast<NrtComponentBufferMemoryContainerHandle>(new ComponentBufferMemoryContainer(
27+
poolSize, deleteInstructionState, sizeOfDataTypeInBytes, func, std::string(serialisedTypeName)));
2728
}
2829

2930
// TODO: Not sure if I should add safety here?

src/NovelRT.Interop/Ecs/NrtComponentCache.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ extern "C"
1717
size_t sizeOfDataType,
1818
const void* deleteInstructionState,
1919
NrtComponentUpdateFnPtr updateFnPtr,
20+
const char* serialisedTypeName,
2021
void* context,
2122
NrtComponentTypeId* outputResult)
2223
{
@@ -35,11 +36,13 @@ extern "C"
3536
*outputResult =
3637
reinterpret_cast<ComponentCache*>(componentCache)
3738
->RegisterComponentTypeUnsafe(
38-
sizeOfDataType, deleteInstructionState, [=](auto lhs, auto rhs, auto size) {
39+
sizeOfDataType, deleteInstructionState,
40+
[=](auto lhs, auto rhs, auto size) {
3941
updateFnPtr(reinterpret_cast<NrtSparseSetMemoryContainer_ByteIteratorViewHandle>(&lhs),
4042
reinterpret_cast<NrtSparseSetMemoryContainer_ByteIteratorViewHandle>(&rhs),
4143
size, context);
42-
});
44+
},
45+
std::string(serialisedTypeName));
4346

4447
return NRT_SUCCESS;
4548
}

src/NovelRT/Ecs/ComponentBufferMemoryContainer.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ namespace NovelRT::Ecs
1010
size_t poolSize,
1111
const void* deleteInstructionState,
1212
size_t sizeOfDataTypeInBytes,
13-
std::function<void(void*, const void*, size_t)> componentUpdateLogic) noexcept
13+
std::function<void(void*, const void*, size_t)> componentUpdateLogic,
14+
const std::string& serialisedTypeName) noexcept
1415
: _rootSet(SparseSetMemoryContainer(sizeOfDataTypeInBytes)),
1516
_updateSets(std::vector<SparseSetMemoryContainer>{}),
1617
_deleteInstructionState(std::vector<uint8_t>(sizeOfDataTypeInBytes)),
1718
_sizeOfDataTypeInBytes(sizeOfDataTypeInBytes),
18-
_componentUpdateLogic(std::move(componentUpdateLogic))
19+
_componentUpdateLogic(std::move(componentUpdateLogic)),
20+
_serialisedTypeName(serialisedTypeName)
1921
{
2022
std::memcpy(_deleteInstructionState.data(), deleteInstructionState, _sizeOfDataTypeInBytes);
2123
for (size_t i = 0; i < poolSize; i++)

src/NovelRT/Ecs/ComponentCache.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,24 @@ namespace NovelRT::Ecs
1717
std::shared_ptr<ComponentBufferMemoryContainer> ComponentCache::CreateContainer(
1818
size_t sizeOfDataType,
1919
const void* deleteInstructionState,
20-
const std::function<void(void*, const void*, size_t)>& componentUpdateLogic) const
20+
const std::function<void(void*, const void*, size_t)>& componentUpdateLogic,
21+
const std::string& serialisedTypeName) const
2122
{
2223
return std::make_shared<ComponentBufferMemoryContainer>(_poolSize, deleteInstructionState, sizeOfDataType,
23-
componentUpdateLogic);
24+
componentUpdateLogic, serialisedTypeName);
2425
}
2526

2627
ComponentTypeId ComponentCache::RegisterComponentTypeUnsafe(
2728
size_t sizeOfDataType,
2829
const void* deleteInstructionState,
29-
const std::function<void(void*, const void*, size_t)>& componentUpdateLogic)
30+
const std::function<void(void*, const void*, size_t)>& componentUpdateLogic,
31+
const std::string& serialisedTypeName)
3032
{
3133
static AtomFactory& _componentTypeIdFactory = AtomFactoryDatabase::GetFactory("ComponentTypeId");
3234

3335
ComponentTypeId returnId = _componentTypeIdFactory.GetNext();
3436
std::shared_ptr<ComponentBufferMemoryContainer> ptr =
35-
CreateContainer(sizeOfDataType, deleteInstructionState, componentUpdateLogic);
37+
CreateContainer(sizeOfDataType, deleteInstructionState, componentUpdateLogic, serialisedTypeName);
3638
_bufferPrepEvent += [ptr](auto vec) { ptr->PrepContainerForFrame(vec); };
3739
_componentMap.emplace(returnId, ptr);
3840
return returnId;

tests/NovelRT.Tests/Ecs/CatalogueTest.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ class CatalogueTest : public testing::Test
2020
{
2121
componentCache = ComponentCache(1);
2222
entityCache = EntityCache(1);
23-
componentCache.RegisterComponentType<int32_t>(-1);
24-
componentCache.RegisterComponentType<size_t>(-1);
25-
componentCache.RegisterComponentType<char>('e');
23+
componentCache.RegisterComponentType<int32_t>(-1, "THROW_AWAY");
24+
componentCache.RegisterComponentType<size_t>(-1, "THROW_AWAY_AGAIN");
25+
componentCache.RegisterComponentType<char>('e', "THROW_AWAY_AGAIN_AGAIN");
2626

2727
componentCache.GetComponentBuffer<int32_t>().PushComponentUpdateInstruction(0, 0, 10);
2828
componentCache.GetComponentBuffer<size_t>().PushComponentUpdateInstruction(0, 0, 100);

0 commit comments

Comments
 (0)