Cogs.Core
FieldSetter.h
1// Set of utilities to set field values (and one getField to get valuePtr).
2#pragma once
3
4#include "BridgeApi.h"
5
6#include "Context.h"
7#include "Engine.h"
8#include "EntityStore.h"
9
10#include "Foundation/ComponentModel/Component.h"
11#include "Foundation/Reflection/TypeDatabase.h"
12
13#include <algorithm>
14
15COGSCORE_DLL_API const Cogs::Reflection::Field* getComponentField(
16 BridgeContext* ctx,
17 EntityId entityId,
18 ComponentId componentId,
19 FieldId fieldId,
21
22namespace Cogs
23{
26 {
28 component->setFieldChanged(fieldId);
29 }
30 context->engine->setDirty();
31 }
32
34 template<typename DataType>
35 void assignField(Cogs::Core::Context * context, EntityId entityId, const ComponentId componentId, const Cogs::Reflection::FieldId fieldId, const DataType * data, int count)
36 {
37 using FieldType = std::vector<DataType>;
38
40 auto field = getComponentField(context, entityId, componentId, fieldId, component);
41 if (!component || !field) return;
42
43 // Make sure the destination type at least has enough storage to receive data from the source.
44 assert(Reflection::TypeDatabase::getType(field->getTypeId()).getSize() >= Reflection::TypeDatabase::getType<FieldType>().getSize());
45
46 auto fieldPointer = field->getPtr<FieldType>(component);
47
48 fieldPointer->assign(data, data + count);
49
50 setChanged(context, component, fieldId);
51 }
52
53 template<typename DataType>
54 void assignFieldSubset(Cogs::Core::Context * context, EntityId entityId, const ComponentId componentId, const Cogs::Reflection::FieldId fieldId, const DataType * data, int offset, int count)
55 {
56 using FieldType = std::vector<DataType>;
57
59 auto field = getComponentField(context, entityId, componentId, fieldId, component);
60 if (!component || !field) return;
61
62 // Make sure the destination type at least has enough storage to receive data from the source.
63 assert(Reflection::TypeDatabase::getType(field->getTypeId()).getSize() >= Reflection::TypeDatabase::getType<FieldType>().getSize());
64
65 auto fieldPointer = field->getPtr<FieldType>(component);
66
67 count = std::max(0, std::min(count, static_cast<int>(fieldPointer->size()) - offset));
68 if (count) {
69 std::copy_n(data, count, fieldPointer->begin() + offset);
70 }
71
72 setChanged(context, component, fieldId);
73 }
74
75 template<typename FieldType>
76 FieldType * getField(Cogs::Core::Context * context, EntityId entityId, const ComponentId componentId, const Cogs::Reflection::FieldId fieldId)
77 {
78 using FieldValueType = typename std::remove_const_t<typename std::remove_reference_t<FieldType>>;
79
81 auto field = getComponentField(context, entityId, componentId, fieldId, component);
82 if (!component || !field) return nullptr;
83
84 return field->getPtr<FieldValueType>(component);
85 }
86
87 template<typename FieldType>
88 void setField(Cogs::Core::Context * context, EntityId entityId, const ComponentId componentId, const Cogs::Reflection::FieldId fieldId, FieldType && data)
89 {
90 using FieldValueType = typename std::remove_const_t<typename std::remove_reference_t<FieldType>>;
91
93 auto field = getComponentField(context, entityId, componentId, fieldId, component);
94 if (!component || !field) return;
95
96 // Make sure the destination type at least has enough storage to receive data from the source.
97 assert(Reflection::TypeDatabase::getType(field->getTypeId()).getSize() >= Reflection::TypeDatabase::getType<FieldValueType>().getSize());
98
99 auto fieldPointer = field->getPtr<FieldValueType>(component);
100
101 *fieldPointer = std::forward<FieldType>(data);
102
103 setChanged(context, component, fieldId);
104 }
105
106 template<typename FieldType>
107 void setVectorField(Cogs::Core::Context * context, EntityId entityId, const ComponentId componentId, const Cogs::Reflection::FieldId fieldId, FieldType && data, size_t index)
108 {
109 using FieldValueType = typename std::remove_const_t<typename std::remove_reference_t<FieldType>>;
110
112 auto field = getComponentField(context, entityId, componentId, fieldId, component);
113 if (!component || !field) return;
114
115 // Make sure the destination type at least has enough storage to receive data from the source.
116 assert(Reflection::TypeDatabase::getType(field->getTypeId()).getSize() >= Reflection::TypeDatabase::getType<FieldValueType>().getSize());
117
118 auto fieldPointer = field->getPtr< std::vector<FieldValueType>>(component);
119 assert(fieldPointer->size() > index);
120 (*fieldPointer)[index] = std::forward<FieldType>(data);
121
122 setChanged(context, component, fieldId);
123 }
124}
Base class for Component instances.
Definition: Component.h:143
void setFieldChanged(const Reflection::FieldId fieldId)
Sets the component to the ComponentFlags::Changed state without carry.
Definition: Component.h:218
constexpr bool isSet(const uint32_t flag) const
Checks if the given flag is set. Requires exact bit match if test of several bits.
Definition: Component.h:374
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
std::unique_ptr< class Engine > engine
Engine instance.
Definition: Context.h:222
Field definition describing a single data member of a data structure.
Definition: Field.h:68
static const Type & getType()
Get the Type of the given template argument.
Definition: TypeDatabase.h:168
constexpr size_t getSize() const
Get the size of an instance of the reflected type, in bytes.
Definition: Type.h:201
uint16_t FieldId
Type used to index fields.
Definition: Name.h:54
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
void setChanged(Cogs::Core::Context *context, Cogs::ComponentModel::Component *component, Reflection::FieldId fieldId)
Must be Called after changing a Component field. Mark field changed. Request engine update.
Definition: FieldSetter.h:25
void assignField(Cogs::Core::Context *context, EntityId entityId, const ComponentId componentId, const Cogs::Reflection::FieldId fieldId, const DataType *data, int count)
Assign value to a Component field.
Definition: FieldSetter.h:35
@ DisableTracking
No change tracking should be performed on the component.
Definition: Component.h:41