Skip to content

Commit 48390ff

Browse files
authored
Merge pull request #111 from GsLogiMaker:feature/component-data-property-list
Implement `_get_property_list` for entities and components
2 parents abe88cf + 034048d commit 48390ff

File tree

8 files changed

+625
-272
lines changed

8 files changed

+625
-272
lines changed

cpp/src/component.cpp

Lines changed: 46 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "godot_cpp/variant/variant.hpp"
1111
#include "registerable_entity.h"
1212
#include "utils.h"
13+
#include "world.h"
1314

1415
#include <cstdint>
1516
#include <stdint.h>
@@ -49,6 +50,19 @@ Ref<GFComponent> GFComponent::from_id_no_source(
4950
return comp_ref;
5051
}
5152

53+
bool GFComponent::_get(StringName property, Variant& out) {
54+
out = getm(property);
55+
return out != Variant();
56+
}
57+
58+
void GFComponent::_get_property_list(List<PropertyInfo>* p_list) {
59+
return get_world()->_comp_get_property_list(get_source_id(), get_id(), p_list);
60+
}
61+
62+
bool GFComponent::_set(StringName property, Variant value) {
63+
return setm(property, value);
64+
}
65+
5266
void GFComponent::_register_internal() {
5367
// Build component
5468
Ref<GFComponentBuilder> b = memnew(GFComponentBuilder(get_world()));
@@ -65,188 +79,29 @@ void GFComponent::_register_internal() {
6579
}
6680

6781
bool GFComponent::setm(const String member, const Variant value) const {
68-
if (!setm_no_notify(member, value)) {
69-
return false;
70-
}
71-
ecs_modified_id(get_world()->raw(), get_source_id(), get_id());
72-
return true;
82+
return get_world()->_comp_setm(
83+
get_source_id(),
84+
get_id(),
85+
member,
86+
value
87+
);
7388
}
7489

7590
bool GFComponent::setm_no_notify(const String member, const Variant value) const {
76-
ecs_world_t* raw = get_world()->raw();
77-
78-
// Get member data
79-
const EcsMember* member_data = get_member_data(member);
80-
if (member_data == nullptr) {
81-
// Member data is null. This should never happen.
82-
ERR(false,
83-
"Member metadata is null"
84-
);
85-
}
86-
void* member_ptr = get_member_ptr_mut_at(member_data->offset);
87-
if (member_ptr == nullptr) {
88-
ERR(false,
89-
"Member pointer is null"
90-
);
91-
}
92-
93-
Utils::set_type_from_variant(value, member_data->type, raw, member_ptr);
94-
return true;
91+
return get_world()->_comp_setm_no_notify(
92+
get_source_id(),
93+
get_id(),
94+
member,
95+
value
96+
);
9597
}
9698

9799
Variant GFComponent::getm(const String member) const {
98-
ecs_world_t* raw = get_world()->raw();
99-
100-
if (!ecs_has_id(raw, get_source_id(), get_id())) {
101-
ERR(nullptr, "Failed to get member",
102-
"\n Entity ",
103-
get_source_entity(),
104-
" does not have component ",
105-
get_world()->id_to_text(get_id())
106-
);
107-
}
108-
109-
// Get member data
110-
const EcsMember* member_data = get_member_data(member);
111-
if (member_data == nullptr) {
112-
// Member data is null. This should never happen.
113-
ERR(nullptr,
114-
"Member metadata is null"
115-
);
116-
}
117-
void* member_value_ptr = get_member_ptr_mut_at(member_data->offset);
118-
if (member_value_ptr == nullptr) {
119-
ERR(nullptr,
120-
"Member value is null"
121-
);
122-
}
123-
124-
return member_value_as_type(member_value_ptr, member_data->type);
125-
}
126-
127-
void* GFComponent::get_member_ptr_mut_at(int offset) const {
128-
ecs_world_t* raw = get_world()->raw();
129-
int8_t* bytes = static_cast<int8_t*>(
130-
ecs_get_mut_id(raw, get_source_id(), get_id())
100+
return get_world()->_comp_getm(
101+
get_source_id(),
102+
get_id(),
103+
member
131104
);
132-
return static_cast<void*>(&bytes[offset]);
133-
}
134-
135-
const EcsMember* GFComponent::get_member_data(const String member) const {
136-
ecs_world_t* raw = get_world()->raw();
137-
const char* c_str = member.utf8().get_data();
138-
139-
ecs_entity_t main_id = get_world()->get_main_id(get_id());
140-
141-
// Get member ID
142-
ecs_entity_t member_id = ecs_lookup_child(raw, main_id, c_str);
143-
144-
if (member_id == 0) {
145-
ERR(nullptr,
146-
"No member named \"",
147-
member,
148-
"\" found in component \"",
149-
get_world()->id_to_text(get_id()),
150-
"\""
151-
);
152-
}
153-
154-
// Get member data
155-
const EcsMember* member_data = ecs_get(raw, member_id, EcsMember);
156-
157-
return member_data;
158-
}
159-
160-
Variant GFComponent::member_value_as_primitive(
161-
const void* ptr,
162-
ecs_primitive_kind_t primitive
163-
) const {
164-
switch (primitive) {
165-
case ecs_primitive_kind_t::EcsBool: return *static_cast<const bool*>(ptr);
166-
case ecs_primitive_kind_t::EcsChar: return *static_cast<const char*>(ptr);
167-
case ecs_primitive_kind_t::EcsByte: return *static_cast<const uint8_t*>(ptr);
168-
case ecs_primitive_kind_t::EcsU8: return *static_cast<const uint8_t*>(ptr);
169-
case ecs_primitive_kind_t::EcsU16: return *static_cast<const uint16_t*>(ptr);
170-
case ecs_primitive_kind_t::EcsU32: return *static_cast<const uint32_t*>(ptr);
171-
case ecs_primitive_kind_t::EcsU64: return *static_cast<const uint64_t*>(ptr);
172-
case ecs_primitive_kind_t::EcsI8: return *static_cast<const int8_t*>(ptr);
173-
case ecs_primitive_kind_t::EcsI16: return *static_cast<const int16_t*>(ptr);
174-
case ecs_primitive_kind_t::EcsI32: return *static_cast<const int32_t*>(ptr);
175-
case ecs_primitive_kind_t::EcsI64: return *static_cast<const int64_t*>(ptr);
176-
case ecs_primitive_kind_t::EcsF32: return *static_cast<const float*>(ptr);
177-
case ecs_primitive_kind_t::EcsF64: return *static_cast<const double*>(ptr);
178-
case ecs_primitive_kind_t::EcsUPtr: ERR(nullptr, "Can't get primitive\nCan't handle uptr");
179-
case ecs_primitive_kind_t::EcsIPtr: ERR(nullptr, "Can't get primitive\nCan't handle iptr");
180-
case ecs_primitive_kind_t::EcsString: return *static_cast<char* const *>(ptr);
181-
case ecs_primitive_kind_t::EcsEntity: return *static_cast<const ecs_entity_t*>(ptr);
182-
case ecs_primitive_kind_t::EcsId: return *static_cast<const ecs_entity_t*>(ptr);
183-
default: ERR(nullptr, "Can't get primitive\nUnknown primitive type");
184-
}
185-
}
186-
187-
Variant GFComponent::member_value_as_type(
188-
const void* ptr,
189-
ecs_entity_t type
190-
) const {
191-
ecs_world_t* raw = get_world()->raw();
192-
Variant::Type vari_type = get_world()->id_to_variant_type(type);
193-
194-
switch (vari_type) {
195-
case(Variant::Type::NIL): {
196-
// Member is not a Godot type. Try to get from Flecs primitive
197-
if (ecs_has_id(raw, type, ecs_id(EcsPrimitive))) {
198-
return member_value_as_primitive(
199-
ptr,
200-
ecs_get(raw, type, EcsPrimitive)->kind
201-
);
202-
}
203-
204-
ERR(nullptr,
205-
"Can't convert type ", get_world()->id_to_text(type), " to Variant"
206-
);
207-
}
208-
case(Variant::Type::BOOL): return Variant( *static_cast<const bool*>(ptr) );
209-
case(Variant::Type::INT): return Variant( *static_cast<const int64_t*>(ptr) );
210-
case(Variant::Type::FLOAT): return Variant( *static_cast<const double*>(ptr) );
211-
case(Variant::Type::STRING): return Variant( *static_cast<const String*>(ptr) );
212-
case(Variant::Type::VECTOR2): return Variant( *static_cast<const Vector2*>(ptr) );
213-
case(Variant::Type::VECTOR2I): return Variant( *static_cast<const Vector2i*>(ptr) );
214-
case(Variant::Type::RECT2): return Variant( *static_cast<const Rect2*>(ptr) );
215-
case(Variant::Type::RECT2I): return Variant( *static_cast<const Rect2i*>(ptr) );
216-
case(Variant::Type::VECTOR3): return Variant( *static_cast<const Vector3*>(ptr) );
217-
case(Variant::Type::VECTOR3I): return Variant( *static_cast<const Vector3i*>(ptr) );
218-
case(Variant::Type::TRANSFORM2D): return Variant( *static_cast<const Transform2D*>(ptr) );
219-
case(Variant::Type::VECTOR4): return Variant( *static_cast<const Vector4*>(ptr) );
220-
case(Variant::Type::VECTOR4I): return Variant( *static_cast<const Vector4i*>(ptr) );
221-
case(Variant::Type::PLANE): return Variant( *static_cast<const Plane*>(ptr) );
222-
case(Variant::Type::QUATERNION): return Variant( *static_cast<const Quaternion*>(ptr) );
223-
case(Variant::Type::AABB): return Variant( *static_cast<const AABB*>(ptr) );
224-
case(Variant::Type::BASIS): return Variant( *static_cast<const Basis*>(ptr) );
225-
case(Variant::Type::TRANSFORM3D): return Variant( *static_cast<const Transform3D*>(ptr) );
226-
case(Variant::Type::PROJECTION): return Variant( *static_cast<const Projection*>(ptr) );
227-
case(Variant::Type::COLOR): return Variant( *static_cast<const Color*>(ptr) );
228-
case(Variant::Type::STRING_NAME): return Variant( *static_cast<const StringName*>(ptr) );
229-
case(Variant::Type::NODE_PATH): return Variant( *static_cast<const NodePath*>(ptr) );
230-
case(Variant::Type::RID): return Variant( *static_cast<const RID*>(ptr) );
231-
case(Variant::Type::OBJECT): return Variant( *static_cast<const Variant*>(ptr) );
232-
case(Variant::Type::CALLABLE): return Variant( *static_cast<const Callable*>(ptr) );
233-
case(Variant::Type::SIGNAL): return Variant( *static_cast<const Signal*>(ptr) );
234-
case(Variant::Type::DICTIONARY): return *static_cast<const Dictionary*>(ptr);
235-
case(Variant::Type::ARRAY): return *static_cast<const Array*>(ptr);
236-
case(Variant::Type::PACKED_BYTE_ARRAY): return Variant( *static_cast<const PackedByteArray*>(ptr) );
237-
case(Variant::Type::PACKED_INT32_ARRAY): return Variant( *static_cast<const PackedInt32Array*>(ptr) );
238-
case(Variant::Type::PACKED_INT64_ARRAY): return Variant( *static_cast<const PackedInt64Array*>(ptr) );
239-
case(Variant::Type::PACKED_FLOAT32_ARRAY): return Variant( *static_cast<const PackedFloat32Array*>(ptr) );
240-
case(Variant::Type::PACKED_FLOAT64_ARRAY): return Variant( *static_cast<const PackedFloat64Array*>(ptr) );
241-
case(Variant::Type::PACKED_STRING_ARRAY): return Variant( *static_cast<const PackedStringArray*>(ptr) );
242-
case(Variant::Type::PACKED_VECTOR2_ARRAY): return Variant( *static_cast<const PackedVector2Array*>(ptr) );
243-
case(Variant::Type::PACKED_VECTOR3_ARRAY): return Variant( *static_cast<const PackedVector3Array*>(ptr) );
244-
case(Variant::Type::PACKED_COLOR_ARRAY): return Variant( *static_cast<const PackedColorArray*>(ptr) );
245-
case(Variant::Type::PACKED_VECTOR4_ARRAY): return Variant( *static_cast<const PackedVector4Array*>(ptr) );
246-
case(Variant::Type::VARIANT_MAX): throw "Can't get type VARIANT_MAX";
247-
}
248-
249-
throw "Unreachable";
250105
}
251106

252107
String GFComponent::_to_string() const {
@@ -295,13 +150,13 @@ void GFComponent::build_data_from_variant(
295150
Variant vari,
296151
void* output
297152
) const {
298-
ecs_world_t* raw = get_world()->raw();
153+
GFWorld* w = get_world();
299154

300-
const EcsStruct* struct_data = ecs_get(raw, get_id(), EcsStruct);
155+
const EcsStruct* struct_data = ecs_get(w->raw(), get_id(), EcsStruct);
301156
if (struct_data == nullptr) {
302157
ERR(/**/,
303158
"Could not build data from Variant\n",
304-
"Component is not a struct."
159+
" Component is not a struct."
305160
);
306161
}
307162

@@ -312,7 +167,10 @@ void GFComponent::build_data_from_variant(
312167
for (int i=0; i != keys.size(); i++) {
313168
String member_name = keys[i];
314169
Variant value = dict[member_name];
315-
const EcsMember* member_data = get_member_data(member_name);
170+
const EcsMember* member_data = w->_comp_get_member_data(
171+
get_id(),
172+
member_name
173+
);
316174
if (member_data == nullptr) {
317175
// No member with that name exists, skip
318176
continue;
@@ -321,7 +179,12 @@ void GFComponent::build_data_from_variant(
321179
static_cast<uint8_t*>(output) + member_data->offset
322180
);
323181
// Set member from dictionary
324-
Utils::set_type_from_variant(value, member_data->type, raw, member_ptr);
182+
Utils::set_type_from_variant(
183+
value,
184+
member_data->type,
185+
w,
186+
member_ptr
187+
);
325188
}
326189
break;
327190
}
@@ -336,13 +199,13 @@ void GFComponent::build_data_from_variant(
336199
static_cast<uint8_t*>(output) + member_data->offset
337200
);
338201
// Set member from array
339-
Utils::set_type_from_variant(value, member_data->type, raw, member_ptr);
202+
Utils::set_type_from_variant(value, member_data->type, w, member_ptr);
340203
}
341204
break;
342205
}
343206
default: ERR(/**/,
344207
"Could not build data from Variant\n",
345-
"Variant type ", Variant::get_type_name(vari.get_type()),
208+
" Variant type ", Variant::get_type_name(vari.get_type()),
346209
" can't be built into component data."
347210
);
348211
}
@@ -368,8 +231,6 @@ void GFComponent::build_data_from_members(
368231
ecs_entity_t component_id,
369232
const GFWorld* world
370233
) {
371-
ecs_world_t* w_raw = world->raw();
372-
373234
const EcsStruct* struct_data = GFComponent::get_struct_ptr(world, component_id);
374235
if (struct_data == nullptr) {
375236
ERR(/**/,
@@ -391,7 +252,7 @@ void GFComponent::build_data_from_members(
391252
static_cast<uint8_t*>(output) + member_data->offset
392253
);
393254
// Set member value
394-
Utils::set_type_from_variant(value, member_data->type, w_raw, member_ptr);
255+
Utils::set_type_from_variant(value, member_data->type, world, member_ptr);
395256
}
396257
}
397258

cpp/src/component.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "component_builder.h"
66
#include "entity.h"
77
#include "godot_cpp/core/gdvirtual.gen.inc"
8+
#include "godot_cpp/core/property_info.hpp"
89
#include "registerable_entity.h"
910
#include "world.h"
1011

@@ -44,6 +45,10 @@ namespace godot {
4445
static Ref<GFComponent> from_id(ecs_entity_t c, ecs_entity_t e, GFWorld*);
4546
static Ref<GFComponent> from_id_no_source(ecs_entity_t comp, GFWorld* world);
4647

48+
bool _get(StringName, Variant&);
49+
void _get_property_list(List<PropertyInfo> *p_list);
50+
bool _set(StringName, Variant);
51+
4752
Variant getm(const String) const;
4853
bool setm(const String, const Variant) const;
4954
bool setm_no_notify(const String, const Variant) const;
@@ -72,12 +77,6 @@ namespace godot {
7277
protected:
7378
static void _bind_methods();
7479

75-
void* get_member_ptr_mut_at(int offset) const;
76-
const EcsMember* get_member_data(const String) const;
77-
78-
Variant member_value_as_primitive(const void*, ecs_primitive_kind_t) const;
79-
Variant member_value_as_type(const void*, ecs_entity_t) const;
80-
8180
private:
8281
ecs_entity_t source_entity_id {0};
8382
};

0 commit comments

Comments
 (0)