1/**************************************************************************/
2/* variant_setget.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "variant_setget.h"
32
33struct VariantSetterGetterInfo {
34 void (*setter)(Variant *base, const Variant *value, bool &valid);
35 void (*getter)(const Variant *base, Variant *value);
36 Variant::ValidatedSetter validated_setter;
37 Variant::ValidatedGetter validated_getter;
38 Variant::PTRSetter ptr_setter;
39 Variant::PTRGetter ptr_getter;
40 Variant::Type member_type;
41};
42
43static LocalVector<VariantSetterGetterInfo> variant_setters_getters[Variant::VARIANT_MAX];
44static LocalVector<StringName> variant_setters_getters_names[Variant::VARIANT_MAX]; //one next to another to make it cache friendly
45
46template <class T>
47static void register_member(Variant::Type p_type, const StringName &p_member) {
48 VariantSetterGetterInfo sgi;
49 sgi.setter = T::set;
50 sgi.validated_setter = T::validated_set;
51 sgi.ptr_setter = T::ptr_set;
52
53 sgi.getter = T::get;
54 sgi.validated_getter = T::validated_get;
55 sgi.ptr_getter = T::ptr_get;
56
57 sgi.member_type = T::get_type();
58
59 variant_setters_getters[p_type].push_back(sgi);
60 variant_setters_getters_names[p_type].push_back(p_member);
61}
62
63void register_named_setters_getters() {
64#define REGISTER_MEMBER(m_base_type, m_member) register_member<VariantSetGet_##m_base_type##_##m_member>(GetTypeInfo<m_base_type>::VARIANT_TYPE, #m_member)
65
66 REGISTER_MEMBER(Vector2, x);
67 REGISTER_MEMBER(Vector2, y);
68
69 REGISTER_MEMBER(Vector2i, x);
70 REGISTER_MEMBER(Vector2i, y);
71
72 REGISTER_MEMBER(Vector3, x);
73 REGISTER_MEMBER(Vector3, y);
74 REGISTER_MEMBER(Vector3, z);
75
76 REGISTER_MEMBER(Vector3i, x);
77 REGISTER_MEMBER(Vector3i, y);
78 REGISTER_MEMBER(Vector3i, z);
79
80 REGISTER_MEMBER(Vector4, x);
81 REGISTER_MEMBER(Vector4, y);
82 REGISTER_MEMBER(Vector4, z);
83 REGISTER_MEMBER(Vector4, w);
84
85 REGISTER_MEMBER(Vector4i, x);
86 REGISTER_MEMBER(Vector4i, y);
87 REGISTER_MEMBER(Vector4i, z);
88 REGISTER_MEMBER(Vector4i, w);
89
90 REGISTER_MEMBER(Rect2, position);
91 REGISTER_MEMBER(Rect2, size);
92 REGISTER_MEMBER(Rect2, end);
93
94 REGISTER_MEMBER(Rect2i, position);
95 REGISTER_MEMBER(Rect2i, size);
96 REGISTER_MEMBER(Rect2i, end);
97
98 REGISTER_MEMBER(AABB, position);
99 REGISTER_MEMBER(AABB, size);
100 REGISTER_MEMBER(AABB, end);
101
102 REGISTER_MEMBER(Transform2D, x);
103 REGISTER_MEMBER(Transform2D, y);
104 REGISTER_MEMBER(Transform2D, origin);
105
106 REGISTER_MEMBER(Plane, x);
107 REGISTER_MEMBER(Plane, y);
108 REGISTER_MEMBER(Plane, z);
109 REGISTER_MEMBER(Plane, d);
110 REGISTER_MEMBER(Plane, normal);
111
112 REGISTER_MEMBER(Quaternion, x);
113 REGISTER_MEMBER(Quaternion, y);
114 REGISTER_MEMBER(Quaternion, z);
115 REGISTER_MEMBER(Quaternion, w);
116
117 REGISTER_MEMBER(Basis, x);
118 REGISTER_MEMBER(Basis, y);
119 REGISTER_MEMBER(Basis, z);
120
121 REGISTER_MEMBER(Transform3D, basis);
122 REGISTER_MEMBER(Transform3D, origin);
123
124 REGISTER_MEMBER(Projection, x);
125 REGISTER_MEMBER(Projection, y);
126 REGISTER_MEMBER(Projection, z);
127 REGISTER_MEMBER(Projection, w);
128
129 REGISTER_MEMBER(Color, r);
130 REGISTER_MEMBER(Color, g);
131 REGISTER_MEMBER(Color, b);
132 REGISTER_MEMBER(Color, a);
133
134 REGISTER_MEMBER(Color, r8);
135 REGISTER_MEMBER(Color, g8);
136 REGISTER_MEMBER(Color, b8);
137 REGISTER_MEMBER(Color, a8);
138
139 REGISTER_MEMBER(Color, h);
140 REGISTER_MEMBER(Color, s);
141 REGISTER_MEMBER(Color, v);
142}
143
144void unregister_named_setters_getters() {
145 for (int i = 0; i < Variant::VARIANT_MAX; i++) {
146 variant_setters_getters[i].clear();
147 variant_setters_getters_names[i].clear();
148 }
149}
150
151bool Variant::has_member(Variant::Type p_type, const StringName &p_member) {
152 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
153
154 for (const StringName &member : variant_setters_getters_names[p_type]) {
155 if (member == p_member) {
156 return true;
157 }
158 }
159 return false;
160}
161
162Variant::Type Variant::get_member_type(Variant::Type p_type, const StringName &p_member) {
163 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX);
164
165 for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) {
166 if (variant_setters_getters_names[p_type][i] == p_member) {
167 return variant_setters_getters[p_type][i].member_type;
168 }
169 }
170
171 return Variant::NIL;
172}
173
174void Variant::get_member_list(Variant::Type p_type, List<StringName> *r_members) {
175 for (const StringName &member : variant_setters_getters_names[p_type]) {
176 r_members->push_back(member);
177 }
178}
179
180int Variant::get_member_count(Type p_type) {
181 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
182 return variant_setters_getters_names[p_type].size();
183}
184
185Variant::ValidatedSetter Variant::get_member_validated_setter(Variant::Type p_type, const StringName &p_member) {
186 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
187
188 for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) {
189 if (variant_setters_getters_names[p_type][i] == p_member) {
190 return variant_setters_getters[p_type][i].validated_setter;
191 }
192 }
193
194 return nullptr;
195}
196Variant::ValidatedGetter Variant::get_member_validated_getter(Variant::Type p_type, const StringName &p_member) {
197 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
198
199 for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) {
200 if (variant_setters_getters_names[p_type][i] == p_member) {
201 return variant_setters_getters[p_type][i].validated_getter;
202 }
203 }
204
205 return nullptr;
206}
207
208Variant::PTRSetter Variant::get_member_ptr_setter(Variant::Type p_type, const StringName &p_member) {
209 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
210
211 for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) {
212 if (variant_setters_getters_names[p_type][i] == p_member) {
213 return variant_setters_getters[p_type][i].ptr_setter;
214 }
215 }
216
217 return nullptr;
218}
219
220Variant::PTRGetter Variant::get_member_ptr_getter(Variant::Type p_type, const StringName &p_member) {
221 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
222
223 for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) {
224 if (variant_setters_getters_names[p_type][i] == p_member) {
225 return variant_setters_getters[p_type][i].ptr_getter;
226 }
227 }
228
229 return nullptr;
230}
231
232void Variant::set_named(const StringName &p_member, const Variant &p_value, bool &r_valid) {
233 uint32_t s = variant_setters_getters[type].size();
234 if (s) {
235 for (uint32_t i = 0; i < s; i++) {
236 if (variant_setters_getters_names[type][i] == p_member) {
237 variant_setters_getters[type][i].setter(this, &p_value, r_valid);
238 return;
239 }
240 }
241 r_valid = false;
242
243 } else if (type == Variant::OBJECT) {
244 Object *obj = get_validated_object();
245 if (!obj) {
246 r_valid = false;
247 } else {
248 obj->set(p_member, p_value, &r_valid);
249 return;
250 }
251 } else if (type == Variant::DICTIONARY) {
252 Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member);
253 if (v) {
254 *v = p_value;
255 r_valid = true;
256 } else {
257 VariantGetInternalPtr<Dictionary>::get_ptr(this)->operator[](p_member) = p_value;
258 r_valid = true;
259 }
260
261 } else {
262 r_valid = false;
263 }
264}
265
266Variant Variant::get_named(const StringName &p_member, bool &r_valid) const {
267 Variant ret;
268 uint32_t s = variant_setters_getters[type].size();
269 if (s) {
270 for (uint32_t i = 0; i < s; i++) {
271 if (variant_setters_getters_names[type][i] == p_member) {
272 variant_setters_getters[type][i].getter(this, &ret);
273 r_valid = true;
274 return ret;
275 }
276 }
277
278 r_valid = false;
279
280 } else if (type == Variant::OBJECT) {
281 Object *obj = get_validated_object();
282 if (!obj) {
283 r_valid = false;
284 return "Instance base is null.";
285 } else {
286 return obj->get(p_member, &r_valid);
287 }
288 } else if (type == Variant::DICTIONARY) {
289 const Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member);
290 if (v) {
291 r_valid = true;
292
293 return *v;
294 } else {
295 r_valid = false;
296 }
297
298 } else {
299 r_valid = false;
300 }
301
302 return ret;
303}
304
305/**** INDEXED SETTERS AND GETTERS ****/
306
307#ifdef DEBUG_ENABLED
308
309#define OOB_TEST(m_idx, m_v) \
310 ERR_FAIL_INDEX(m_idx, m_v)
311
312#else
313
314#define OOB_TEST(m_idx, m_v)
315
316#endif
317
318#ifdef DEBUG_ENABLED
319
320#define NULL_TEST(m_key) \
321 ERR_FAIL_NULL(m_key)
322
323#else
324
325#define NULL_TEST(m_key)
326
327#endif
328
329#define INDEXED_SETGET_STRUCT_TYPED(m_base_type, m_elem_type) \
330 struct VariantIndexedSetGet_##m_base_type { \
331 static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \
332 int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \
333 if (index < 0) { \
334 index += size; \
335 } \
336 if (index < 0 || index >= size) { \
337 *oob = true; \
338 return; \
339 } \
340 VariantTypeAdjust<m_elem_type>::adjust(value); \
341 *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index]; \
342 *oob = false; \
343 } \
344 static void ptr_get(const void *base, int64_t index, void *member) { \
345 /* avoid ptrconvert for performance*/ \
346 const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \
347 if (index < 0) \
348 index += v.size(); \
349 OOB_TEST(index, v.size()); \
350 PtrToArg<m_elem_type>::encode(v[index], member); \
351 } \
352 static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \
353 if (value->get_type() != GetTypeInfo<m_elem_type>::VARIANT_TYPE) { \
354 *oob = false; \
355 *valid = false; \
356 return; \
357 } \
358 int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \
359 if (index < 0) { \
360 index += size; \
361 } \
362 if (index < 0 || index >= size) { \
363 *oob = true; \
364 *valid = false; \
365 return; \
366 } \
367 (*VariantGetInternalPtr<m_base_type>::get_ptr(base)).write[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \
368 *oob = false; \
369 *valid = true; \
370 } \
371 static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \
372 int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \
373 if (index < 0) { \
374 index += size; \
375 } \
376 if (index < 0 || index >= size) { \
377 *oob = true; \
378 return; \
379 } \
380 (*VariantGetInternalPtr<m_base_type>::get_ptr(base)).write[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \
381 *oob = false; \
382 } \
383 static void ptr_set(void *base, int64_t index, const void *member) { \
384 /* avoid ptrconvert for performance*/ \
385 m_base_type &v = *reinterpret_cast<m_base_type *>(base); \
386 if (index < 0) \
387 index += v.size(); \
388 OOB_TEST(index, v.size()); \
389 v.write[index] = PtrToArg<m_elem_type>::convert(member); \
390 } \
391 static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
392 static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
393 static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \
394 };
395
396#define INDEXED_SETGET_STRUCT_TYPED_NUMERIC(m_base_type, m_elem_type, m_assign_type) \
397 struct VariantIndexedSetGet_##m_base_type { \
398 static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \
399 int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \
400 if (index < 0) { \
401 index += size; \
402 } \
403 if (index < 0 || index >= size) { \
404 *oob = true; \
405 return; \
406 } \
407 VariantTypeAdjust<m_elem_type>::adjust(value); \
408 *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index]; \
409 *oob = false; \
410 } \
411 static void ptr_get(const void *base, int64_t index, void *member) { \
412 /* avoid ptrconvert for performance*/ \
413 const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \
414 if (index < 0) \
415 index += v.size(); \
416 OOB_TEST(index, v.size()); \
417 PtrToArg<m_elem_type>::encode(v[index], member); \
418 } \
419 static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \
420 int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \
421 if (index < 0) { \
422 index += size; \
423 } \
424 if (index < 0 || index >= size) { \
425 *oob = true; \
426 *valid = false; \
427 return; \
428 } \
429 m_assign_type num; \
430 if (value->get_type() == Variant::INT) { \
431 num = (m_assign_type)*VariantGetInternalPtr<int64_t>::get_ptr(value); \
432 } else if (value->get_type() == Variant::FLOAT) { \
433 num = (m_assign_type)*VariantGetInternalPtr<double>::get_ptr(value); \
434 } else { \
435 *oob = false; \
436 *valid = false; \
437 return; \
438 } \
439 (*VariantGetInternalPtr<m_base_type>::get_ptr(base)).write[index] = num; \
440 *oob = false; \
441 *valid = true; \
442 } \
443 static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \
444 int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \
445 if (index < 0) { \
446 index += size; \
447 } \
448 if (index < 0 || index >= size) { \
449 *oob = true; \
450 return; \
451 } \
452 (*VariantGetInternalPtr<m_base_type>::get_ptr(base)).write[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \
453 *oob = false; \
454 } \
455 static void ptr_set(void *base, int64_t index, const void *member) { \
456 /* avoid ptrconvert for performance*/ \
457 m_base_type &v = *reinterpret_cast<m_base_type *>(base); \
458 if (index < 0) \
459 index += v.size(); \
460 OOB_TEST(index, v.size()); \
461 v.write[index] = PtrToArg<m_elem_type>::convert(member); \
462 } \
463 static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
464 static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
465 static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \
466 };
467
468#define INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(m_base_type, m_elem_type, m_assign_type, m_max) \
469 struct VariantIndexedSetGet_##m_base_type { \
470 static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \
471 if (index < 0 || index >= m_max) { \
472 *oob = true; \
473 return; \
474 } \
475 VariantTypeAdjust<m_elem_type>::adjust(value); \
476 *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index]; \
477 *oob = false; \
478 } \
479 static void ptr_get(const void *base, int64_t index, void *member) { \
480 /* avoid ptrconvert for performance*/ \
481 const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \
482 OOB_TEST(index, m_max); \
483 PtrToArg<m_elem_type>::encode(v[index], member); \
484 } \
485 static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \
486 if (index < 0 || index >= m_max) { \
487 *oob = true; \
488 *valid = false; \
489 return; \
490 } \
491 m_assign_type num; \
492 if (value->get_type() == Variant::INT) { \
493 num = (m_assign_type)*VariantGetInternalPtr<int64_t>::get_ptr(value); \
494 } else if (value->get_type() == Variant::FLOAT) { \
495 num = (m_assign_type)*VariantGetInternalPtr<double>::get_ptr(value); \
496 } else { \
497 *oob = false; \
498 *valid = false; \
499 return; \
500 } \
501 (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = num; \
502 *oob = false; \
503 *valid = true; \
504 } \
505 static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \
506 if (index < 0 || index >= m_max) { \
507 *oob = true; \
508 return; \
509 } \
510 (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \
511 *oob = false; \
512 } \
513 static void ptr_set(void *base, int64_t index, const void *member) { \
514 /* avoid ptrconvert for performance*/ \
515 m_base_type &v = *reinterpret_cast<m_base_type *>(base); \
516 OOB_TEST(index, m_max); \
517 v[index] = PtrToArg<m_elem_type>::convert(member); \
518 } \
519 static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
520 static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
521 static uint64_t get_indexed_size(const Variant *base) { return m_max; } \
522 };
523
524#define INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(m_base_type, m_elem_type, m_accessor, m_max) \
525 struct VariantIndexedSetGet_##m_base_type { \
526 static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \
527 if (index < 0 || index >= m_max) { \
528 *oob = true; \
529 return; \
530 } \
531 VariantTypeAdjust<m_elem_type>::adjust(value); \
532 *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))m_accessor[index]; \
533 *oob = false; \
534 } \
535 static void ptr_get(const void *base, int64_t index, void *member) { \
536 /* avoid ptrconvert for performance*/ \
537 const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \
538 OOB_TEST(index, m_max); \
539 PtrToArg<m_elem_type>::encode(v m_accessor[index], member); \
540 } \
541 static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \
542 if (value->get_type() != GetTypeInfo<m_elem_type>::VARIANT_TYPE) { \
543 *oob = false; \
544 *valid = false; \
545 } \
546 if (index < 0 || index >= m_max) { \
547 *oob = true; \
548 *valid = false; \
549 return; \
550 } \
551 (*VariantGetInternalPtr<m_base_type>::get_ptr(base)) m_accessor[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \
552 *oob = false; \
553 *valid = true; \
554 } \
555 static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \
556 if (index < 0 || index >= m_max) { \
557 *oob = true; \
558 return; \
559 } \
560 (*VariantGetInternalPtr<m_base_type>::get_ptr(base)) m_accessor[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \
561 *oob = false; \
562 } \
563 static void ptr_set(void *base, int64_t index, const void *member) { \
564 /* avoid ptrconvert for performance*/ \
565 m_base_type &v = *reinterpret_cast<m_base_type *>(base); \
566 OOB_TEST(index, m_max); \
567 v m_accessor[index] = PtrToArg<m_elem_type>::convert(member); \
568 } \
569 static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
570 static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
571 static uint64_t get_indexed_size(const Variant *base) { return m_max; } \
572 };
573
574#define INDEXED_SETGET_STRUCT_BULTIN_FUNC(m_base_type, m_elem_type, m_set, m_get, m_max) \
575 struct VariantIndexedSetGet_##m_base_type { \
576 static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \
577 if (index < 0 || index >= m_max) { \
578 *oob = true; \
579 return; \
580 } \
581 VariantTypeAdjust<m_elem_type>::adjust(value); \
582 *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_get(index); \
583 *oob = false; \
584 } \
585 static void ptr_get(const void *base, int64_t index, void *member) { \
586 /* avoid ptrconvert for performance*/ \
587 const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \
588 OOB_TEST(index, m_max); \
589 PtrToArg<m_elem_type>::encode(v.m_get(index), member); \
590 } \
591 static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \
592 if (value->get_type() != GetTypeInfo<m_elem_type>::VARIANT_TYPE) { \
593 *oob = false; \
594 *valid = false; \
595 } \
596 if (index < 0 || index >= m_max) { \
597 *oob = true; \
598 *valid = false; \
599 return; \
600 } \
601 VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_set(index, *VariantGetInternalPtr<m_elem_type>::get_ptr(value)); \
602 *oob = false; \
603 *valid = true; \
604 } \
605 static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \
606 if (index < 0 || index >= m_max) { \
607 *oob = true; \
608 return; \
609 } \
610 VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_set(index, *VariantGetInternalPtr<m_elem_type>::get_ptr(value)); \
611 *oob = false; \
612 } \
613 static void ptr_set(void *base, int64_t index, const void *member) { \
614 /* avoid ptrconvert for performance*/ \
615 m_base_type &v = *reinterpret_cast<m_base_type *>(base); \
616 OOB_TEST(index, m_max); \
617 v.m_set(index, PtrToArg<m_elem_type>::convert(member)); \
618 } \
619 static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \
620 static uint32_t get_index_usage() { return GetTypeInfo<m_elem_type>::get_class_info().usage; } \
621 static uint64_t get_indexed_size(const Variant *base) { return m_max; } \
622 };
623
624struct VariantIndexedSetGet_Array {
625 static void get(const Variant *base, int64_t index, Variant *value, bool *oob) {
626 int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size();
627 if (index < 0) {
628 index += size;
629 }
630 if (index < 0 || index >= size) {
631 *oob = true;
632 return;
633 }
634 *value = (*VariantGetInternalPtr<Array>::get_ptr(base))[index];
635 *oob = false;
636 }
637 static void ptr_get(const void *base, int64_t index, void *member) {
638 /* avoid ptrconvert for performance*/
639 const Array &v = *reinterpret_cast<const Array *>(base);
640 if (index < 0) {
641 index += v.size();
642 }
643 OOB_TEST(index, v.size());
644 PtrToArg<Variant>::encode(v[index], member);
645 }
646 static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) {
647 if (VariantGetInternalPtr<Array>::get_ptr(base)->is_read_only()) {
648 *valid = false;
649 *oob = true;
650 return;
651 }
652 int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size();
653 if (index < 0) {
654 index += size;
655 }
656 if (index < 0 || index >= size) {
657 *oob = true;
658 *valid = false;
659 return;
660 }
661 VariantGetInternalPtr<Array>::get_ptr(base)->set(index, *value);
662 *oob = false;
663 *valid = true;
664 }
665 static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) {
666 if (VariantGetInternalPtr<Array>::get_ptr(base)->is_read_only()) {
667 *oob = true;
668 return;
669 }
670 int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size();
671 if (index < 0) {
672 index += size;
673 }
674 if (index < 0 || index >= size) {
675 *oob = true;
676 return;
677 }
678 VariantGetInternalPtr<Array>::get_ptr(base)->set(index, *value);
679 *oob = false;
680 }
681 static void ptr_set(void *base, int64_t index, const void *member) {
682 /* avoid ptrconvert for performance*/
683 Array &v = *reinterpret_cast<Array *>(base);
684 if (index < 0) {
685 index += v.size();
686 }
687 OOB_TEST(index, v.size());
688 v.set(index, PtrToArg<Variant>::convert(member));
689 }
690 static Variant::Type get_index_type() { return Variant::NIL; }
691 static uint32_t get_index_usage() { return PROPERTY_USAGE_NIL_IS_VARIANT; }
692 static uint64_t get_indexed_size(const Variant *base) { return 0; }
693};
694
695struct VariantIndexedSetGet_String {
696 static void get(const Variant *base, int64_t index, Variant *value, bool *oob) {
697 int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
698 if (index < 0) {
699 index += length;
700 }
701 if (index < 0 || index >= length) {
702 *oob = true;
703 return;
704 }
705 char32_t result = (*VariantGetInternalPtr<String>::get_ptr(base))[index];
706 *value = String(&result, 1);
707 *oob = false;
708 }
709 static void ptr_get(const void *base, int64_t index, void *member) {
710 /* avoid ptrconvert for performance*/
711 const String &v = *reinterpret_cast<const String *>(base);
712 if (index < 0) {
713 index += v.length();
714 }
715 OOB_TEST(index, v.length());
716 char32_t c = v[index];
717 PtrToArg<String>::encode(String(&c, 1), member);
718 }
719 static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) {
720 if (value->get_type() != Variant::STRING) {
721 *oob = false;
722 *valid = false;
723 return;
724 }
725 int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
726 if (index < 0) {
727 index += length;
728 }
729 if (index < 0 || index >= length) {
730 *oob = true;
731 *valid = false;
732 return;
733 }
734 String *b = VariantGetInternalPtr<String>::get_ptr(base);
735 const String *v = VariantInternal::get_string(value);
736 if (v->length() == 0) {
737 b->remove_at(index);
738 } else {
739 b->set(index, v->get(0));
740 }
741 *oob = false;
742 *valid = true;
743 }
744 static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) {
745 int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
746 if (index < 0) {
747 index += length;
748 }
749 if (index < 0 || index >= length) {
750 *oob = true;
751 return;
752 }
753 String *b = VariantGetInternalPtr<String>::get_ptr(base);
754 const String *v = VariantInternal::get_string(value);
755 if (v->length() == 0) {
756 b->remove_at(index);
757 } else {
758 b->set(index, v->get(0));
759 }
760 *oob = false;
761 }
762 static void ptr_set(void *base, int64_t index, const void *member) {
763 /* avoid ptrconvert for performance*/
764 String &v = *reinterpret_cast<String *>(base);
765 if (index < 0) {
766 index += v.length();
767 }
768 OOB_TEST(index, v.length());
769 const String &m = *reinterpret_cast<const String *>(member);
770 if (unlikely(m.length() == 0)) {
771 v.remove_at(index);
772 } else {
773 v.set(index, m.unicode_at(0));
774 }
775 }
776 static Variant::Type get_index_type() { return Variant::STRING; }
777 static uint32_t get_index_usage() { return PROPERTY_USAGE_DEFAULT; }
778 static uint64_t get_indexed_size(const Variant *base) { return VariantInternal::get_string(base)->length(); }
779};
780
781#define INDEXED_SETGET_STRUCT_DICT(m_base_type) \
782 struct VariantIndexedSetGet_##m_base_type { \
783 static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \
784 const Variant *ptr = VariantGetInternalPtr<m_base_type>::get_ptr(base)->getptr(index); \
785 if (!ptr) { \
786 *oob = true; \
787 return; \
788 } \
789 *value = *ptr; \
790 *oob = false; \
791 } \
792 static void ptr_get(const void *base, int64_t index, void *member) { \
793 /* avoid ptrconvert for performance*/ \
794 const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \
795 const Variant *ptr = v.getptr(index); \
796 NULL_TEST(ptr); \
797 PtrToArg<Variant>::encode(*ptr, member); \
798 } \
799 static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \
800 if (VariantGetInternalPtr<m_base_type>::get_ptr(base)->is_read_only()) { \
801 *valid = false; \
802 *oob = true; \
803 return; \
804 } \
805 (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \
806 *oob = false; \
807 *valid = true; \
808 } \
809 static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \
810 if (VariantGetInternalPtr<m_base_type>::get_ptr(base)->is_read_only()) { \
811 *oob = true; \
812 return; \
813 } \
814 (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \
815 *oob = false; \
816 } \
817 static void ptr_set(void *base, int64_t index, const void *member) { \
818 m_base_type &v = *reinterpret_cast<m_base_type *>(base); \
819 v[index] = PtrToArg<Variant>::convert(member); \
820 } \
821 static Variant::Type get_index_type() { return Variant::NIL; } \
822 static uint32_t get_index_usage() { return PROPERTY_USAGE_DEFAULT; } \
823 static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \
824 };
825
826INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2, double, real_t, 2)
827INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2i, int64_t, int32_t, 2)
828INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3, double, real_t, 3)
829INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3i, int64_t, int32_t, 3)
830INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector4, double, real_t, 4)
831INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector4i, int64_t, int32_t, 4)
832INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Quaternion, double, real_t, 4)
833INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Color, double, float, 4)
834
835INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Transform2D, Vector2, .columns, 3)
836INDEXED_SETGET_STRUCT_BULTIN_FUNC(Basis, Vector3, set_column, get_column, 3)
837INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Projection, Vector4, .columns, 4)
838
839INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedByteArray, int64_t, uint8_t)
840INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt32Array, int64_t, int32_t)
841INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt64Array, int64_t, int64_t)
842INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedFloat32Array, double, float)
843INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedFloat64Array, double, double)
844INDEXED_SETGET_STRUCT_TYPED(PackedVector2Array, Vector2)
845INDEXED_SETGET_STRUCT_TYPED(PackedVector3Array, Vector3)
846INDEXED_SETGET_STRUCT_TYPED(PackedStringArray, String)
847INDEXED_SETGET_STRUCT_TYPED(PackedColorArray, Color)
848
849INDEXED_SETGET_STRUCT_DICT(Dictionary)
850
851struct VariantIndexedSetterGetterInfo {
852 void (*setter)(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) = nullptr;
853 void (*getter)(const Variant *base, int64_t index, Variant *value, bool *oob) = nullptr;
854
855 Variant::ValidatedIndexedSetter validated_setter = nullptr;
856 Variant::ValidatedIndexedGetter validated_getter = nullptr;
857
858 Variant::PTRIndexedSetter ptr_setter = nullptr;
859 Variant::PTRIndexedGetter ptr_getter = nullptr;
860
861 uint64_t (*get_indexed_size)(const Variant *base) = nullptr;
862
863 Variant::Type index_type = Variant::NIL;
864 uint32_t index_usage = PROPERTY_USAGE_DEFAULT;
865
866 bool valid = false;
867};
868
869static VariantIndexedSetterGetterInfo variant_indexed_setters_getters[Variant::VARIANT_MAX];
870
871template <class T>
872static void register_indexed_member(Variant::Type p_type) {
873 VariantIndexedSetterGetterInfo &sgi = variant_indexed_setters_getters[p_type];
874
875 sgi.setter = T::set;
876 sgi.validated_setter = T::validated_set;
877 sgi.ptr_setter = T::ptr_set;
878
879 sgi.getter = T::get;
880 sgi.validated_getter = T::get;
881 sgi.ptr_getter = T::ptr_get;
882
883 sgi.index_type = T::get_index_type();
884 sgi.index_usage = T::get_index_usage();
885 sgi.get_indexed_size = T::get_indexed_size;
886
887 sgi.valid = true;
888}
889
890void register_indexed_setters_getters() {
891#define REGISTER_INDEXED_MEMBER(m_base_type) register_indexed_member<VariantIndexedSetGet_##m_base_type>(GetTypeInfo<m_base_type>::VARIANT_TYPE)
892
893 REGISTER_INDEXED_MEMBER(String);
894 REGISTER_INDEXED_MEMBER(Vector2);
895 REGISTER_INDEXED_MEMBER(Vector2i);
896 REGISTER_INDEXED_MEMBER(Vector3);
897 REGISTER_INDEXED_MEMBER(Vector3i);
898 REGISTER_INDEXED_MEMBER(Vector4);
899 REGISTER_INDEXED_MEMBER(Vector4i);
900 REGISTER_INDEXED_MEMBER(Quaternion);
901 REGISTER_INDEXED_MEMBER(Color);
902 REGISTER_INDEXED_MEMBER(Transform2D);
903 REGISTER_INDEXED_MEMBER(Basis);
904 REGISTER_INDEXED_MEMBER(Projection);
905
906 REGISTER_INDEXED_MEMBER(PackedByteArray);
907 REGISTER_INDEXED_MEMBER(PackedInt32Array);
908 REGISTER_INDEXED_MEMBER(PackedInt64Array);
909 REGISTER_INDEXED_MEMBER(PackedFloat32Array);
910 REGISTER_INDEXED_MEMBER(PackedFloat64Array);
911 REGISTER_INDEXED_MEMBER(PackedVector2Array);
912 REGISTER_INDEXED_MEMBER(PackedVector3Array);
913 REGISTER_INDEXED_MEMBER(PackedStringArray);
914 REGISTER_INDEXED_MEMBER(PackedColorArray);
915
916 REGISTER_INDEXED_MEMBER(Array);
917 REGISTER_INDEXED_MEMBER(Dictionary);
918}
919
920static void unregister_indexed_setters_getters() {
921}
922
923bool Variant::has_indexing(Variant::Type p_type) {
924 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
925 return variant_indexed_setters_getters[p_type].valid;
926}
927
928Variant::Type Variant::get_indexed_element_type(Variant::Type p_type) {
929 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX);
930 return variant_indexed_setters_getters[p_type].index_type;
931}
932
933uint32_t Variant::get_indexed_element_usage(Variant::Type p_type) {
934 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, PROPERTY_USAGE_DEFAULT);
935 return variant_indexed_setters_getters[p_type].index_usage;
936}
937
938Variant::ValidatedIndexedSetter Variant::get_member_validated_indexed_setter(Variant::Type p_type) {
939 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
940 return variant_indexed_setters_getters[p_type].validated_setter;
941}
942Variant::ValidatedIndexedGetter Variant::get_member_validated_indexed_getter(Variant::Type p_type) {
943 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
944 return variant_indexed_setters_getters[p_type].validated_getter;
945}
946
947Variant::PTRIndexedSetter Variant::get_member_ptr_indexed_setter(Variant::Type p_type) {
948 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
949 return variant_indexed_setters_getters[p_type].ptr_setter;
950}
951Variant::PTRIndexedGetter Variant::get_member_ptr_indexed_getter(Variant::Type p_type) {
952 ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
953 return variant_indexed_setters_getters[p_type].ptr_getter;
954}
955
956void Variant::set_indexed(int64_t p_index, const Variant &p_value, bool &r_valid, bool &r_oob) {
957 if (likely(variant_indexed_setters_getters[type].valid)) {
958 variant_indexed_setters_getters[type].setter(this, p_index, &p_value, &r_valid, &r_oob);
959 } else {
960 r_valid = false;
961 r_oob = false;
962 }
963}
964Variant Variant::get_indexed(int64_t p_index, bool &r_valid, bool &r_oob) const {
965 if (likely(variant_indexed_setters_getters[type].valid)) {
966 Variant ret;
967 variant_indexed_setters_getters[type].getter(this, p_index, &ret, &r_oob);
968 r_valid = !r_oob;
969 return ret;
970 } else {
971 r_valid = false;
972 r_oob = false;
973 return Variant();
974 }
975}
976
977uint64_t Variant::get_indexed_size() const {
978 if (likely(variant_indexed_setters_getters[type].valid && variant_indexed_setters_getters[type].get_indexed_size)) {
979 return variant_indexed_setters_getters[type].get_indexed_size(this);
980 } else {
981 return 0;
982 }
983}
984
985struct VariantKeyedSetGetDictionary {
986 static void get(const Variant *base, const Variant *key, Variant *value, bool *r_valid) {
987 const Variant *ptr = VariantGetInternalPtr<Dictionary>::get_ptr(base)->getptr(*key);
988 if (!ptr) {
989 *r_valid = false;
990 return;
991 }
992 *value = *ptr;
993 *r_valid = true;
994 }
995 static void ptr_get(const void *base, const void *key, void *value) {
996 /* avoid ptrconvert for performance*/
997 const Dictionary &v = *reinterpret_cast<const Dictionary *>(base);
998 const Variant *ptr = v.getptr(PtrToArg<Variant>::convert(key));
999 NULL_TEST(ptr);
1000 PtrToArg<Variant>::encode(*ptr, value);
1001 }
1002 static void set(Variant *base, const Variant *key, const Variant *value, bool *r_valid) {
1003 if (VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only()) {
1004 *r_valid = false;
1005 return;
1006 }
1007 (*VariantGetInternalPtr<Dictionary>::get_ptr(base))[*key] = *value;
1008 *r_valid = true;
1009 }
1010 static void ptr_set(void *base, const void *key, const void *value) {
1011 Dictionary &v = *reinterpret_cast<Dictionary *>(base);
1012 v[PtrToArg<Variant>::convert(key)] = PtrToArg<Variant>::convert(value);
1013 }
1014
1015 static bool has(const Variant *base, const Variant *key, bool *r_valid) {
1016 *r_valid = true;
1017 return VariantGetInternalPtr<Dictionary>::get_ptr(base)->has(*key);
1018 }
1019 static uint32_t ptr_has(const void *base, const void *key) {
1020 /* avoid ptrconvert for performance*/
1021 const Dictionary &v = *reinterpret_cast<const Dictionary *>(base);
1022 return v.has(PtrToArg<Variant>::convert(key));
1023 }
1024};
1025
1026struct VariantKeyedSetGetObject {
1027 static void get(const Variant *base, const Variant *key, Variant *value, bool *r_valid) {
1028 Object *obj = base->get_validated_object();
1029
1030 if (!obj) {
1031 *r_valid = false;
1032 *value = Variant();
1033 return;
1034 }
1035 *value = obj->getvar(*key, r_valid);
1036 }
1037 static void ptr_get(const void *base, const void *key, void *value) {
1038 const Object *obj = PtrToArg<Object *>::convert(base);
1039 NULL_TEST(obj);
1040 Variant v = obj->getvar(PtrToArg<Variant>::convert(key));
1041 PtrToArg<Variant>::encode(v, value);
1042 }
1043 static void set(Variant *base, const Variant *key, const Variant *value, bool *r_valid) {
1044 Object *obj = base->get_validated_object();
1045
1046 if (!obj) {
1047 *r_valid = false;
1048 return;
1049 }
1050 obj->setvar(*key, *value, r_valid);
1051 }
1052 static void ptr_set(void *base, const void *key, const void *value) {
1053 Object *obj = PtrToArg<Object *>::convert(base);
1054 NULL_TEST(obj);
1055 obj->setvar(PtrToArg<Variant>::convert(key), PtrToArg<Variant>::convert(value));
1056 }
1057
1058 static bool has(const Variant *base, const Variant *key, bool *r_valid) {
1059 Object *obj = base->get_validated_object();
1060 if (!obj) {
1061 *r_valid = false;
1062 return false;
1063 }
1064 *r_valid = true;
1065 bool exists;
1066 obj->getvar(*key, &exists);
1067 return exists;
1068 }
1069 static uint32_t ptr_has(const void *base, const void *key) {
1070 const Object *obj = PtrToArg<Object *>::convert(base);
1071 ERR_FAIL_NULL_V(obj, false);
1072 bool valid;
1073 obj->getvar(PtrToArg<Variant>::convert(key), &valid);
1074 return valid;
1075 }
1076};
1077
1078struct VariantKeyedSetterGetterInfo {
1079 Variant::ValidatedKeyedSetter validated_setter = nullptr;
1080 Variant::ValidatedKeyedGetter validated_getter = nullptr;
1081 Variant::ValidatedKeyedChecker validated_checker = nullptr;
1082
1083 Variant::PTRKeyedSetter ptr_setter = nullptr;
1084 Variant::PTRKeyedGetter ptr_getter = nullptr;
1085 Variant::PTRKeyedChecker ptr_checker = nullptr;
1086
1087 bool valid = false;
1088};
1089
1090static VariantKeyedSetterGetterInfo variant_keyed_setters_getters[Variant::VARIANT_MAX];
1091
1092template <class T>
1093static void register_keyed_member(Variant::Type p_type) {
1094 VariantKeyedSetterGetterInfo &sgi = variant_keyed_setters_getters[p_type];
1095
1096 sgi.validated_setter = T::set;
1097 sgi.ptr_setter = T::ptr_set;
1098
1099 sgi.validated_getter = T::get;
1100 sgi.ptr_getter = T::ptr_get;
1101
1102 sgi.validated_checker = T::has;
1103 sgi.ptr_checker = T::ptr_has;
1104
1105 sgi.valid = true;
1106}
1107
1108static void register_keyed_setters_getters() {
1109 register_keyed_member<VariantKeyedSetGetDictionary>(Variant::DICTIONARY);
1110 register_keyed_member<VariantKeyedSetGetObject>(Variant::OBJECT);
1111}
1112bool Variant::is_keyed(Variant::Type p_type) {
1113 ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, false);
1114 return variant_keyed_setters_getters[p_type].valid;
1115}
1116
1117Variant::ValidatedKeyedSetter Variant::get_member_validated_keyed_setter(Variant::Type p_type) {
1118 ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr);
1119 return variant_keyed_setters_getters[p_type].validated_setter;
1120}
1121Variant::ValidatedKeyedGetter Variant::get_member_validated_keyed_getter(Variant::Type p_type) {
1122 ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr);
1123 return variant_keyed_setters_getters[p_type].validated_getter;
1124}
1125Variant::ValidatedKeyedChecker Variant::get_member_validated_keyed_checker(Variant::Type p_type) {
1126 ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr);
1127 return variant_keyed_setters_getters[p_type].validated_checker;
1128}
1129
1130Variant::PTRKeyedSetter Variant::get_member_ptr_keyed_setter(Variant::Type p_type) {
1131 ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr);
1132 return variant_keyed_setters_getters[p_type].ptr_setter;
1133}
1134Variant::PTRKeyedGetter Variant::get_member_ptr_keyed_getter(Variant::Type p_type) {
1135 ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr);
1136 return variant_keyed_setters_getters[p_type].ptr_getter;
1137}
1138Variant::PTRKeyedChecker Variant::get_member_ptr_keyed_checker(Variant::Type p_type) {
1139 ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr);
1140 return variant_keyed_setters_getters[p_type].ptr_checker;
1141}
1142
1143void Variant::set_keyed(const Variant &p_key, const Variant &p_value, bool &r_valid) {
1144 if (likely(variant_keyed_setters_getters[type].valid)) {
1145 variant_keyed_setters_getters[type].validated_setter(this, &p_key, &p_value, &r_valid);
1146 } else {
1147 r_valid = false;
1148 }
1149}
1150Variant Variant::get_keyed(const Variant &p_key, bool &r_valid) const {
1151 if (likely(variant_keyed_setters_getters[type].valid)) {
1152 Variant ret;
1153 variant_keyed_setters_getters[type].validated_getter(this, &p_key, &ret, &r_valid);
1154 return ret;
1155 } else {
1156 r_valid = false;
1157 return Variant();
1158 }
1159}
1160bool Variant::has_key(const Variant &p_key, bool &r_valid) const {
1161 if (likely(variant_keyed_setters_getters[type].valid)) {
1162 return variant_keyed_setters_getters[type].validated_checker(this, &p_key, &r_valid);
1163 } else {
1164 r_valid = false;
1165 return false;
1166 }
1167}
1168
1169void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) {
1170 if (type == DICTIONARY || type == OBJECT) {
1171 bool valid;
1172 set_keyed(p_index, p_value, valid);
1173 if (r_valid) {
1174 *r_valid = valid;
1175 }
1176 } else {
1177 bool valid = false;
1178 if (p_index.get_type() == STRING_NAME) {
1179 set_named(*VariantGetInternalPtr<StringName>::get_ptr(&p_index), p_value, valid);
1180 } else if (p_index.get_type() == INT) {
1181 bool obb;
1182 set_indexed(*VariantGetInternalPtr<int64_t>::get_ptr(&p_index), p_value, valid, obb);
1183 if (obb) {
1184 valid = false;
1185 }
1186 } else if (p_index.get_type() == STRING) { // less efficient version of named
1187 set_named(*VariantGetInternalPtr<String>::get_ptr(&p_index), p_value, valid);
1188 } else if (p_index.get_type() == FLOAT) { // less efficient version of indexed
1189 bool obb;
1190 set_indexed(*VariantGetInternalPtr<double>::get_ptr(&p_index), p_value, valid, obb);
1191 if (obb) {
1192 valid = false;
1193 }
1194 }
1195 if (r_valid) {
1196 *r_valid = valid;
1197 }
1198 }
1199}
1200
1201Variant Variant::get(const Variant &p_index, bool *r_valid) const {
1202 Variant ret;
1203 if (type == DICTIONARY || type == OBJECT) {
1204 bool valid;
1205 ret = get_keyed(p_index, valid);
1206 if (r_valid) {
1207 *r_valid = valid;
1208 }
1209 } else {
1210 bool valid = false;
1211 if (p_index.get_type() == STRING_NAME) {
1212 ret = get_named(*VariantGetInternalPtr<StringName>::get_ptr(&p_index), valid);
1213 } else if (p_index.get_type() == INT) {
1214 bool obb;
1215 ret = get_indexed(*VariantGetInternalPtr<int64_t>::get_ptr(&p_index), valid, obb);
1216 if (obb) {
1217 valid = false;
1218 }
1219 } else if (p_index.get_type() == STRING) { // less efficient version of named
1220 ret = get_named(*VariantGetInternalPtr<String>::get_ptr(&p_index), valid);
1221 } else if (p_index.get_type() == FLOAT) { // less efficient version of indexed
1222 bool obb;
1223 ret = get_indexed(*VariantGetInternalPtr<double>::get_ptr(&p_index), valid, obb);
1224 if (obb) {
1225 valid = false;
1226 }
1227 }
1228 if (r_valid) {
1229 *r_valid = valid;
1230 }
1231 }
1232
1233 return ret;
1234}
1235
1236void Variant::get_property_list(List<PropertyInfo> *p_list) const {
1237 if (type == DICTIONARY) {
1238 const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem);
1239 List<Variant> keys;
1240 dic->get_key_list(&keys);
1241 for (const Variant &E : keys) {
1242 if (E.get_type() == Variant::STRING) {
1243 p_list->push_back(PropertyInfo(Variant::STRING, E));
1244 }
1245 }
1246 } else if (type == OBJECT) {
1247 Object *obj = get_validated_object();
1248 ERR_FAIL_NULL(obj);
1249 obj->get_property_list(p_list);
1250
1251 } else {
1252 List<StringName> members;
1253 get_member_list(type, &members);
1254 for (const StringName &E : members) {
1255 PropertyInfo pi;
1256 pi.name = E;
1257 pi.type = get_member_type(type, E);
1258 p_list->push_back(pi);
1259 }
1260 }
1261}
1262
1263bool Variant::iter_init(Variant &r_iter, bool &valid) const {
1264 valid = true;
1265 switch (type) {
1266 case INT: {
1267 r_iter = 0;
1268 return _data._int > 0;
1269 } break;
1270 case FLOAT: {
1271 r_iter = 0.0;
1272 return _data._float > 0.0;
1273 } break;
1274 case VECTOR2: {
1275 double from = reinterpret_cast<const Vector2 *>(_data._mem)->x;
1276 double to = reinterpret_cast<const Vector2 *>(_data._mem)->y;
1277
1278 r_iter = from;
1279
1280 return from < to;
1281 } break;
1282 case VECTOR2I: {
1283 int64_t from = reinterpret_cast<const Vector2i *>(_data._mem)->x;
1284 int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y;
1285
1286 r_iter = from;
1287
1288 return from < to;
1289 } break;
1290 case VECTOR3: {
1291 double from = reinterpret_cast<const Vector3 *>(_data._mem)->x;
1292 double to = reinterpret_cast<const Vector3 *>(_data._mem)->y;
1293 double step = reinterpret_cast<const Vector3 *>(_data._mem)->z;
1294
1295 r_iter = from;
1296
1297 if (from == to) {
1298 return false;
1299 } else if (from < to) {
1300 return step > 0;
1301 }
1302 return step < 0;
1303 } break;
1304 case VECTOR3I: {
1305 int64_t from = reinterpret_cast<const Vector3i *>(_data._mem)->x;
1306 int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y;
1307 int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z;
1308
1309 r_iter = from;
1310
1311 if (from == to) {
1312 return false;
1313 } else if (from < to) {
1314 return step > 0;
1315 }
1316 return step < 0;
1317 } break;
1318 case OBJECT: {
1319 if (!_get_obj().obj) {
1320 valid = false;
1321 return false;
1322 }
1323
1324#ifdef DEBUG_ENABLED
1325
1326 if (EngineDebugger::is_active() && !_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
1327 valid = false;
1328 return false;
1329 }
1330
1331#endif
1332 Callable::CallError ce;
1333 ce.error = Callable::CallError::CALL_OK;
1334 Array ref;
1335 ref.push_back(r_iter);
1336 Variant vref = ref;
1337 const Variant *refp[] = { &vref };
1338 Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce);
1339
1340 if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
1341 valid = false;
1342 return false;
1343 }
1344
1345 r_iter = ref[0];
1346 return ret;
1347 } break;
1348
1349 case STRING: {
1350 const String *str = reinterpret_cast<const String *>(_data._mem);
1351 if (str->is_empty()) {
1352 return false;
1353 }
1354 r_iter = 0;
1355 return true;
1356 } break;
1357 case DICTIONARY: {
1358 const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem);
1359 if (dic->is_empty()) {
1360 return false;
1361 }
1362
1363 const Variant *next = dic->next(nullptr);
1364 r_iter = *next;
1365 return true;
1366
1367 } break;
1368 case ARRAY: {
1369 const Array *arr = reinterpret_cast<const Array *>(_data._mem);
1370 if (arr->is_empty()) {
1371 return false;
1372 }
1373 r_iter = 0;
1374 return true;
1375 } break;
1376 case PACKED_BYTE_ARRAY: {
1377 const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
1378 if (arr->size() == 0) {
1379 return false;
1380 }
1381 r_iter = 0;
1382 return true;
1383
1384 } break;
1385 case PACKED_INT32_ARRAY: {
1386 const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array);
1387 if (arr->size() == 0) {
1388 return false;
1389 }
1390 r_iter = 0;
1391 return true;
1392
1393 } break;
1394 case PACKED_INT64_ARRAY: {
1395 const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array);
1396 if (arr->size() == 0) {
1397 return false;
1398 }
1399 r_iter = 0;
1400 return true;
1401
1402 } break;
1403 case PACKED_FLOAT32_ARRAY: {
1404 const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array);
1405 if (arr->size() == 0) {
1406 return false;
1407 }
1408 r_iter = 0;
1409 return true;
1410
1411 } break;
1412 case PACKED_FLOAT64_ARRAY: {
1413 const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array);
1414 if (arr->size() == 0) {
1415 return false;
1416 }
1417 r_iter = 0;
1418 return true;
1419
1420 } break;
1421 case PACKED_STRING_ARRAY: {
1422 const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
1423 if (arr->size() == 0) {
1424 return false;
1425 }
1426 r_iter = 0;
1427 return true;
1428 } break;
1429 case PACKED_VECTOR2_ARRAY: {
1430 const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
1431 if (arr->size() == 0) {
1432 return false;
1433 }
1434 r_iter = 0;
1435 return true;
1436 } break;
1437 case PACKED_VECTOR3_ARRAY: {
1438 const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
1439 if (arr->size() == 0) {
1440 return false;
1441 }
1442 r_iter = 0;
1443 return true;
1444 } break;
1445 case PACKED_COLOR_ARRAY: {
1446 const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
1447 if (arr->size() == 0) {
1448 return false;
1449 }
1450 r_iter = 0;
1451 return true;
1452
1453 } break;
1454 default: {
1455 }
1456 }
1457
1458 valid = false;
1459 return false;
1460}
1461
1462bool Variant::iter_next(Variant &r_iter, bool &valid) const {
1463 valid = true;
1464 switch (type) {
1465 case INT: {
1466 int64_t idx = r_iter;
1467 idx++;
1468 if (idx >= _data._int) {
1469 return false;
1470 }
1471 r_iter = idx;
1472 return true;
1473 } break;
1474 case FLOAT: {
1475 double idx = r_iter;
1476 idx++;
1477 if (idx >= _data._float) {
1478 return false;
1479 }
1480 r_iter = idx;
1481 return true;
1482 } break;
1483 case VECTOR2: {
1484 double to = reinterpret_cast<const Vector2 *>(_data._mem)->y;
1485
1486 double idx = r_iter;
1487 idx++;
1488
1489 if (idx >= to) {
1490 return false;
1491 }
1492
1493 r_iter = idx;
1494 return true;
1495 } break;
1496 case VECTOR2I: {
1497 int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y;
1498
1499 int64_t idx = r_iter;
1500 idx++;
1501
1502 if (idx >= to) {
1503 return false;
1504 }
1505
1506 r_iter = idx;
1507 return true;
1508 } break;
1509 case VECTOR3: {
1510 double to = reinterpret_cast<const Vector3 *>(_data._mem)->y;
1511 double step = reinterpret_cast<const Vector3 *>(_data._mem)->z;
1512
1513 double idx = r_iter;
1514 idx += step;
1515
1516 if (step < 0 && idx <= to) {
1517 return false;
1518 }
1519
1520 if (step > 0 && idx >= to) {
1521 return false;
1522 }
1523
1524 r_iter = idx;
1525 return true;
1526 } break;
1527 case VECTOR3I: {
1528 int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y;
1529 int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z;
1530
1531 int64_t idx = r_iter;
1532 idx += step;
1533
1534 if (step < 0 && idx <= to) {
1535 return false;
1536 }
1537
1538 if (step > 0 && idx >= to) {
1539 return false;
1540 }
1541
1542 r_iter = idx;
1543 return true;
1544 } break;
1545 case OBJECT: {
1546 if (!_get_obj().obj) {
1547 valid = false;
1548 return false;
1549 }
1550
1551#ifdef DEBUG_ENABLED
1552
1553 if (EngineDebugger::is_active() && !_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
1554 valid = false;
1555 return false;
1556 }
1557
1558#endif
1559 Callable::CallError ce;
1560 ce.error = Callable::CallError::CALL_OK;
1561 Array ref;
1562 ref.push_back(r_iter);
1563 Variant vref = ref;
1564 const Variant *refp[] = { &vref };
1565 Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce);
1566
1567 if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
1568 valid = false;
1569 return false;
1570 }
1571
1572 r_iter = ref[0];
1573
1574 return ret;
1575 } break;
1576
1577 case STRING: {
1578 const String *str = reinterpret_cast<const String *>(_data._mem);
1579 int idx = r_iter;
1580 idx++;
1581 if (idx >= str->length()) {
1582 return false;
1583 }
1584 r_iter = idx;
1585 return true;
1586 } break;
1587 case DICTIONARY: {
1588 const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem);
1589 const Variant *next = dic->next(&r_iter);
1590 if (!next) {
1591 return false;
1592 }
1593
1594 r_iter = *next;
1595 return true;
1596
1597 } break;
1598 case ARRAY: {
1599 const Array *arr = reinterpret_cast<const Array *>(_data._mem);
1600 int idx = r_iter;
1601 idx++;
1602 if (idx >= arr->size()) {
1603 return false;
1604 }
1605 r_iter = idx;
1606 return true;
1607 } break;
1608 case PACKED_BYTE_ARRAY: {
1609 const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
1610 int idx = r_iter;
1611 idx++;
1612 if (idx >= arr->size()) {
1613 return false;
1614 }
1615 r_iter = idx;
1616 return true;
1617
1618 } break;
1619 case PACKED_INT32_ARRAY: {
1620 const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array);
1621 int32_t idx = r_iter;
1622 idx++;
1623 if (idx >= arr->size()) {
1624 return false;
1625 }
1626 r_iter = idx;
1627 return true;
1628
1629 } break;
1630 case PACKED_INT64_ARRAY: {
1631 const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array);
1632 int64_t idx = r_iter;
1633 idx++;
1634 if (idx >= arr->size()) {
1635 return false;
1636 }
1637 r_iter = idx;
1638 return true;
1639
1640 } break;
1641 case PACKED_FLOAT32_ARRAY: {
1642 const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array);
1643 int idx = r_iter;
1644 idx++;
1645 if (idx >= arr->size()) {
1646 return false;
1647 }
1648 r_iter = idx;
1649 return true;
1650
1651 } break;
1652 case PACKED_FLOAT64_ARRAY: {
1653 const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array);
1654 int idx = r_iter;
1655 idx++;
1656 if (idx >= arr->size()) {
1657 return false;
1658 }
1659 r_iter = idx;
1660 return true;
1661
1662 } break;
1663 case PACKED_STRING_ARRAY: {
1664 const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
1665 int idx = r_iter;
1666 idx++;
1667 if (idx >= arr->size()) {
1668 return false;
1669 }
1670 r_iter = idx;
1671 return true;
1672 } break;
1673 case PACKED_VECTOR2_ARRAY: {
1674 const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
1675 int idx = r_iter;
1676 idx++;
1677 if (idx >= arr->size()) {
1678 return false;
1679 }
1680 r_iter = idx;
1681 return true;
1682 } break;
1683 case PACKED_VECTOR3_ARRAY: {
1684 const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
1685 int idx = r_iter;
1686 idx++;
1687 if (idx >= arr->size()) {
1688 return false;
1689 }
1690 r_iter = idx;
1691 return true;
1692 } break;
1693 case PACKED_COLOR_ARRAY: {
1694 const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
1695 int idx = r_iter;
1696 idx++;
1697 if (idx >= arr->size()) {
1698 return false;
1699 }
1700 r_iter = idx;
1701 return true;
1702 } break;
1703 default: {
1704 }
1705 }
1706
1707 valid = false;
1708 return false;
1709}
1710
1711Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
1712 r_valid = true;
1713 switch (type) {
1714 case INT: {
1715 return r_iter;
1716 } break;
1717 case FLOAT: {
1718 return r_iter;
1719 } break;
1720 case VECTOR2: {
1721 return r_iter;
1722 } break;
1723 case VECTOR2I: {
1724 return r_iter;
1725 } break;
1726 case VECTOR3: {
1727 return r_iter;
1728 } break;
1729 case VECTOR3I: {
1730 return r_iter;
1731 } break;
1732 case OBJECT: {
1733 if (!_get_obj().obj) {
1734 r_valid = false;
1735 return Variant();
1736 }
1737#ifdef DEBUG_ENABLED
1738 if (EngineDebugger::is_active() && !_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
1739 r_valid = false;
1740 return Variant();
1741 }
1742
1743#endif
1744 Callable::CallError ce;
1745 ce.error = Callable::CallError::CALL_OK;
1746 const Variant *refp[] = { &r_iter };
1747 Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce);
1748
1749 if (ce.error != Callable::CallError::CALL_OK) {
1750 r_valid = false;
1751 return Variant();
1752 }
1753
1754 //r_iter=ref[0];
1755
1756 return ret;
1757 } break;
1758
1759 case STRING: {
1760 const String *str = reinterpret_cast<const String *>(_data._mem);
1761 return str->substr(r_iter, 1);
1762 } break;
1763 case DICTIONARY: {
1764 return r_iter; //iterator is the same as the key
1765
1766 } break;
1767 case ARRAY: {
1768 const Array *arr = reinterpret_cast<const Array *>(_data._mem);
1769 int idx = r_iter;
1770#ifdef DEBUG_ENABLED
1771 if (idx < 0 || idx >= arr->size()) {
1772 r_valid = false;
1773 return Variant();
1774 }
1775#endif
1776 return arr->get(idx);
1777 } break;
1778 case PACKED_BYTE_ARRAY: {
1779 const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array);
1780 int idx = r_iter;
1781#ifdef DEBUG_ENABLED
1782 if (idx < 0 || idx >= arr->size()) {
1783 r_valid = false;
1784 return Variant();
1785 }
1786#endif
1787 return arr->get(idx);
1788 } break;
1789 case PACKED_INT32_ARRAY: {
1790 const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array);
1791 int32_t idx = r_iter;
1792#ifdef DEBUG_ENABLED
1793 if (idx < 0 || idx >= arr->size()) {
1794 r_valid = false;
1795 return Variant();
1796 }
1797#endif
1798 return arr->get(idx);
1799 } break;
1800 case PACKED_INT64_ARRAY: {
1801 const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array);
1802 int64_t idx = r_iter;
1803#ifdef DEBUG_ENABLED
1804 if (idx < 0 || idx >= arr->size()) {
1805 r_valid = false;
1806 return Variant();
1807 }
1808#endif
1809 return arr->get(idx);
1810 } break;
1811 case PACKED_FLOAT32_ARRAY: {
1812 const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array);
1813 int idx = r_iter;
1814#ifdef DEBUG_ENABLED
1815 if (idx < 0 || idx >= arr->size()) {
1816 r_valid = false;
1817 return Variant();
1818 }
1819#endif
1820 return arr->get(idx);
1821 } break;
1822 case PACKED_FLOAT64_ARRAY: {
1823 const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array);
1824 int idx = r_iter;
1825#ifdef DEBUG_ENABLED
1826 if (idx < 0 || idx >= arr->size()) {
1827 r_valid = false;
1828 return Variant();
1829 }
1830#endif
1831 return arr->get(idx);
1832 } break;
1833 case PACKED_STRING_ARRAY: {
1834 const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array);
1835 int idx = r_iter;
1836#ifdef DEBUG_ENABLED
1837 if (idx < 0 || idx >= arr->size()) {
1838 r_valid = false;
1839 return Variant();
1840 }
1841#endif
1842 return arr->get(idx);
1843 } break;
1844 case PACKED_VECTOR2_ARRAY: {
1845 const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array);
1846 int idx = r_iter;
1847#ifdef DEBUG_ENABLED
1848 if (idx < 0 || idx >= arr->size()) {
1849 r_valid = false;
1850 return Variant();
1851 }
1852#endif
1853 return arr->get(idx);
1854 } break;
1855 case PACKED_VECTOR3_ARRAY: {
1856 const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array);
1857 int idx = r_iter;
1858#ifdef DEBUG_ENABLED
1859 if (idx < 0 || idx >= arr->size()) {
1860 r_valid = false;
1861 return Variant();
1862 }
1863#endif
1864 return arr->get(idx);
1865 } break;
1866 case PACKED_COLOR_ARRAY: {
1867 const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array);
1868 int idx = r_iter;
1869#ifdef DEBUG_ENABLED
1870 if (idx < 0 || idx >= arr->size()) {
1871 r_valid = false;
1872 return Variant();
1873 }
1874#endif
1875 return arr->get(idx);
1876 } break;
1877 default: {
1878 }
1879 }
1880
1881 r_valid = false;
1882 return Variant();
1883}
1884
1885Variant Variant::duplicate(bool p_deep) const {
1886 return recursive_duplicate(p_deep, 0);
1887}
1888
1889Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const {
1890 switch (type) {
1891 case OBJECT: {
1892 /* breaks stuff :(
1893 if (p_deep && !_get_obj().ref.is_null()) {
1894 Ref<Resource> resource = _get_obj().ref;
1895 if (resource.is_valid()) {
1896 return resource->duplicate(true);
1897 }
1898 }
1899 */
1900 return *this;
1901 } break;
1902 case DICTIONARY:
1903 return operator Dictionary().recursive_duplicate(p_deep, recursion_count);
1904 case ARRAY:
1905 return operator Array().recursive_duplicate(p_deep, recursion_count);
1906 case PACKED_BYTE_ARRAY:
1907 return operator Vector<uint8_t>().duplicate();
1908 case PACKED_INT32_ARRAY:
1909 return operator Vector<int32_t>().duplicate();
1910 case PACKED_INT64_ARRAY:
1911 return operator Vector<int64_t>().duplicate();
1912 case PACKED_FLOAT32_ARRAY:
1913 return operator Vector<float>().duplicate();
1914 case PACKED_FLOAT64_ARRAY:
1915 return operator Vector<double>().duplicate();
1916 case PACKED_STRING_ARRAY:
1917 return operator Vector<String>().duplicate();
1918 case PACKED_VECTOR2_ARRAY:
1919 return operator Vector<Vector2>().duplicate();
1920 case PACKED_VECTOR3_ARRAY:
1921 return operator Vector<Vector3>().duplicate();
1922 case PACKED_COLOR_ARRAY:
1923 return operator Vector<Color>().duplicate();
1924 default:
1925 return *this;
1926 }
1927}
1928
1929void Variant::_register_variant_setters_getters() {
1930 register_named_setters_getters();
1931 register_indexed_setters_getters();
1932 register_keyed_setters_getters();
1933}
1934void Variant::_unregister_variant_setters_getters() {
1935 unregister_named_setters_getters();
1936 unregister_indexed_setters_getters();
1937}
1938