2014-02-10 02:10:30 +01:00
|
|
|
/**************************************************************************/
|
|
|
|
/* marshalls.cpp */
|
|
|
|
/**************************************************************************/
|
|
|
|
/* This file is part of: */
|
|
|
|
/* GODOT ENGINE */
|
|
|
|
/* https://godotengine.org */
|
|
|
|
/**************************************************************************/
|
|
|
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
|
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
|
|
/* */
|
|
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
|
|
/* a copy of this software and associated documentation files (the */
|
|
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
|
|
/* the following conditions: */
|
|
|
|
/* */
|
|
|
|
/* The above copyright notice and this permission notice shall be */
|
|
|
|
/* included in all copies or substantial portions of the Software. */
|
|
|
|
/* */
|
|
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
|
|
/**************************************************************************/
|
2018-01-05 00:50:27 +01:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
#include "marshalls.h"
|
2018-09-11 18:13:45 +02:00
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
#include "core/core_string_names.h"
|
|
|
|
#include "core/io/resource_loader.h"
|
2021-06-04 18:03:15 +02:00
|
|
|
#include "core/object/ref_counted.h"
|
2023-06-14 12:25:18 +02:00
|
|
|
#include "core/object/script_language.h"
|
2018-09-11 18:13:45 +02:00
|
|
|
#include "core/os/keyboard.h"
|
2020-11-07 23:33:38 +01:00
|
|
|
#include "core/string/print_string.h"
|
2018-09-11 18:13:45 +02:00
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
#include <limits.h>
|
2014-02-10 02:10:30 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
void EncodedObjectAsID::_bind_methods() {
|
|
|
|
ClassDB::bind_method(D_METHOD("set_object_id", "id"), &EncodedObjectAsID::set_object_id);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_object_id"), &EncodedObjectAsID::get_object_id);
|
2019-06-26 10:50:45 +02:00
|
|
|
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "object_id"), "set_object_id", "get_object_id");
|
2017-08-18 15:59:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void EncodedObjectAsID::set_object_id(ObjectID p_id) {
|
|
|
|
id = p_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectID EncodedObjectAsID::get_object_id() const {
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2021-08-09 19:28:08 +02:00
|
|
|
#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(((int32_t)(b)) < 0 || ((int32_t)(a)) < 0 || ((int32_t)(a)) > INT_MAX - ((int32_t)(b)), err)
|
|
|
|
#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(((int32_t)(a)) < 0 || ((int32_t)(b)) <= 0 || ((int32_t)(a)) > INT_MAX / ((int32_t)(b)), err)
|
2019-06-26 10:50:45 +02:00
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
// Byte 0: `Variant::Type`, byte 1: unused, bytes 2 and 3: additional data.
|
|
|
|
#define HEADER_TYPE_MASK 0xFF
|
|
|
|
|
|
|
|
// For `Variant::INT`, `Variant::FLOAT` and other math types.
|
|
|
|
#define HEADER_DATA_FLAG_64 (1 << 16)
|
|
|
|
|
|
|
|
// For `Variant::OBJECT`.
|
|
|
|
#define HEADER_DATA_FLAG_OBJECT_AS_ID (1 << 16)
|
|
|
|
|
|
|
|
// For `Variant::ARRAY`.
|
|
|
|
// Occupies bits 16 and 17.
|
|
|
|
#define HEADER_DATA_FIELD_TYPED_ARRAY_MASK (0b11 << 16)
|
|
|
|
#define HEADER_DATA_FIELD_TYPED_ARRAY_NONE (0b00 << 16)
|
|
|
|
#define HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN (0b01 << 16)
|
|
|
|
#define HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME (0b10 << 16)
|
|
|
|
#define HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT (0b11 << 16)
|
2017-01-09 00:58:39 +01:00
|
|
|
|
2017-08-14 16:58:10 +02:00
|
|
|
static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r_string) {
|
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t strlen = decode_uint32(buf);
|
|
|
|
int32_t pad = 0;
|
|
|
|
|
|
|
|
// Handle padding
|
|
|
|
if (strlen % 4) {
|
|
|
|
pad = 4 - strlen % 4;
|
|
|
|
}
|
|
|
|
|
2017-08-14 16:58:10 +02:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
2018-07-08 15:11:41 +02:00
|
|
|
|
|
|
|
// Ensure buffer is big enough
|
|
|
|
ERR_FAIL_ADD_OF(strlen, pad, ERR_FILE_EOF);
|
|
|
|
ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF);
|
2017-08-14 16:58:10 +02:00
|
|
|
|
|
|
|
String str;
|
2022-07-05 14:18:29 +02:00
|
|
|
ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA);
|
2017-08-14 16:58:10 +02:00
|
|
|
r_string = str;
|
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
// Add padding
|
|
|
|
strlen += pad;
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
// Update buffer pos, left data count, and return size
|
2017-08-14 16:58:10 +02:00
|
|
|
buf += strlen;
|
|
|
|
len -= strlen;
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 4 + strlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:04:05 +01:00
|
|
|
Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_objects, int p_depth) {
|
|
|
|
ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Variant is too deep. Bailing.");
|
2014-02-10 02:10:30 +01:00
|
|
|
const uint8_t *buf = p_buffer;
|
|
|
|
int len = p_len;
|
|
|
|
|
2019-06-20 16:59:48 +02:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
uint32_t header = decode_uint32(buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
ERR_FAIL_COND_V((header & HEADER_TYPE_MASK) >= Variant::VARIANT_MAX, ERR_INVALID_DATA);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2014-02-10 02:10:30 +01:00
|
|
|
*r_len = 4;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
// Note: We cannot use sizeof(real_t) for decoding, in case a different size is encoded.
|
|
|
|
// Decoding math types always checks for the encoded size, while encoding always uses compilation setting.
|
|
|
|
// This does lead to some code duplication for decoding, but compatibility is the priority.
|
2023-06-14 12:25:18 +02:00
|
|
|
switch (header & HEADER_TYPE_MASK) {
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::NIL: {
|
|
|
|
r_variant = Variant();
|
|
|
|
} break;
|
|
|
|
case Variant::BOOL: {
|
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
|
|
bool val = decode_uint32(buf);
|
|
|
|
r_variant = val;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2014-02-10 02:10:30 +01:00
|
|
|
(*r_len) += 4;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::INT: {
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
|
2017-01-09 00:58:39 +01:00
|
|
|
int64_t val = decode_uint64(buf);
|
|
|
|
r_variant = val;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2017-01-09 00:58:39 +01:00
|
|
|
(*r_len) += 8;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-01-09 00:58:39 +01:00
|
|
|
|
|
|
|
} else {
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2017-01-09 00:58:39 +01:00
|
|
|
int32_t val = decode_uint32(buf);
|
|
|
|
r_variant = val;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2017-01-09 00:58:39 +01:00
|
|
|
(*r_len) += 4;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-01-09 00:58:39 +01:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::FLOAT: {
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double), ERR_INVALID_DATA);
|
2017-01-09 00:58:39 +01:00
|
|
|
double val = decode_double(buf);
|
|
|
|
r_variant = val;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += sizeof(double);
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-01-09 00:58:39 +01:00
|
|
|
} else {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float), ERR_INVALID_DATA);
|
2017-01-09 00:58:39 +01:00
|
|
|
float val = decode_float(buf);
|
|
|
|
r_variant = val;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += sizeof(float);
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-01-09 00:58:39 +01:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
|
|
|
case Variant::STRING: {
|
|
|
|
String str;
|
2017-08-14 16:58:10 +02:00
|
|
|
Error err = _decode_string(buf, len, r_len, str);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (err) {
|
2017-08-14 16:58:10 +02:00
|
|
|
return err;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
r_variant = str;
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
2017-12-06 21:36:34 +01:00
|
|
|
// math types
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::VECTOR2: {
|
|
|
|
Vector2 val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 2, ERR_INVALID_DATA);
|
|
|
|
val.x = decode_double(&buf[0]);
|
|
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 2, ERR_INVALID_DATA);
|
|
|
|
val.x = decode_float(&buf[0]);
|
|
|
|
val.y = decode_float(&buf[sizeof(float)]);
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 2;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-24 17:00:40 +01:00
|
|
|
} break;
|
2020-02-22 04:26:41 +01:00
|
|
|
case Variant::VECTOR2I: {
|
|
|
|
ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA);
|
|
|
|
Vector2i val;
|
|
|
|
val.x = decode_uint32(&buf[0]);
|
|
|
|
val.y = decode_uint32(&buf[4]);
|
|
|
|
r_variant = val;
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-02-22 04:26:41 +01:00
|
|
|
(*r_len) += 4 * 2;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-02-22 04:26:41 +01:00
|
|
|
|
2020-02-24 17:00:40 +01:00
|
|
|
} break;
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::RECT2: {
|
|
|
|
Rect2 val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
|
|
val.position.x = decode_double(&buf[0]);
|
|
|
|
val.position.y = decode_double(&buf[sizeof(double)]);
|
|
|
|
val.size.x = decode_double(&buf[sizeof(double) * 2]);
|
|
|
|
val.size.y = decode_double(&buf[sizeof(double) * 3]);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 4;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA);
|
|
|
|
val.position.x = decode_float(&buf[0]);
|
|
|
|
val.position.y = decode_float(&buf[sizeof(float)]);
|
|
|
|
val.size.x = decode_float(&buf[sizeof(float) * 2]);
|
|
|
|
val.size.y = decode_float(&buf[sizeof(float) * 3]);
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 4;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-22 04:26:41 +01:00
|
|
|
} break;
|
|
|
|
case Variant::RECT2I: {
|
|
|
|
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
|
|
|
|
Rect2i val;
|
|
|
|
val.position.x = decode_uint32(&buf[0]);
|
|
|
|
val.position.y = decode_uint32(&buf[4]);
|
|
|
|
val.size.x = decode_uint32(&buf[8]);
|
|
|
|
val.size.y = decode_uint32(&buf[12]);
|
|
|
|
r_variant = val;
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-02-22 04:26:41 +01:00
|
|
|
(*r_len) += 4 * 4;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-02-22 04:26:41 +01:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::VECTOR3: {
|
|
|
|
Vector3 val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 3, ERR_INVALID_DATA);
|
|
|
|
val.x = decode_double(&buf[0]);
|
|
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
|
|
val.z = decode_double(&buf[sizeof(double) * 2]);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 3;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 3, ERR_INVALID_DATA);
|
|
|
|
val.x = decode_float(&buf[0]);
|
|
|
|
val.y = decode_float(&buf[sizeof(float)]);
|
|
|
|
val.z = decode_float(&buf[sizeof(float) * 2]);
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 3;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-22 04:26:41 +01:00
|
|
|
} break;
|
|
|
|
case Variant::VECTOR3I: {
|
|
|
|
ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA);
|
|
|
|
Vector3i val;
|
|
|
|
val.x = decode_uint32(&buf[0]);
|
|
|
|
val.y = decode_uint32(&buf[4]);
|
|
|
|
val.z = decode_uint32(&buf[8]);
|
|
|
|
r_variant = val;
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-02-22 04:26:41 +01:00
|
|
|
(*r_len) += 4 * 3;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-02-22 04:26:41 +01:00
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
} break;
|
|
|
|
case Variant::VECTOR4: {
|
|
|
|
Vector4 val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
|
|
val.x = decode_double(&buf[0]);
|
|
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
|
|
val.z = decode_double(&buf[sizeof(double) * 2]);
|
|
|
|
val.w = decode_double(&buf[sizeof(double) * 3]);
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 4;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA);
|
|
|
|
val.x = decode_float(&buf[0]);
|
|
|
|
val.y = decode_float(&buf[sizeof(float)]);
|
|
|
|
val.z = decode_float(&buf[sizeof(float) * 2]);
|
|
|
|
val.w = decode_float(&buf[sizeof(float) * 3]);
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_variant = val;
|
|
|
|
|
|
|
|
} break;
|
|
|
|
case Variant::VECTOR4I: {
|
|
|
|
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
|
|
|
|
Vector4i val;
|
|
|
|
val.x = decode_uint32(&buf[0]);
|
|
|
|
val.y = decode_uint32(&buf[4]);
|
|
|
|
val.z = decode_uint32(&buf[8]);
|
|
|
|
val.w = decode_uint32(&buf[12]);
|
|
|
|
r_variant = val;
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 4 * 4;
|
|
|
|
}
|
|
|
|
|
2013-04-10 10:37:04 +02:00
|
|
|
} break;
|
2017-01-11 04:52:51 +01:00
|
|
|
case Variant::TRANSFORM2D: {
|
|
|
|
Transform2D val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 2; j++) {
|
2022-04-24 23:59:24 +02:00
|
|
|
val.columns[i][j] = decode_double(&buf[(i * 2 + j) * sizeof(double)]);
|
2020-03-17 04:11:41 +01:00
|
|
|
}
|
2013-04-10 10:37:04 +02:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 6;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 6, ERR_INVALID_DATA);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 2; j++) {
|
2022-04-24 23:59:24 +02:00
|
|
|
val.columns[i][j] = decode_float(&buf[(i * 2 + j) * sizeof(float)]);
|
2020-03-17 04:11:41 +01:00
|
|
|
}
|
|
|
|
}
|
2013-04-10 10:37:04 +02:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 6;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2013-04-10 10:37:04 +02:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::PLANE: {
|
|
|
|
Plane val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
|
|
val.normal.x = decode_double(&buf[0]);
|
|
|
|
val.normal.y = decode_double(&buf[sizeof(double)]);
|
|
|
|
val.normal.z = decode_double(&buf[sizeof(double) * 2]);
|
|
|
|
val.d = decode_double(&buf[sizeof(double) * 3]);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 4;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA);
|
|
|
|
val.normal.x = decode_float(&buf[0]);
|
|
|
|
val.normal.y = decode_float(&buf[sizeof(float)]);
|
|
|
|
val.normal.z = decode_float(&buf[sizeof(float) * 2]);
|
|
|
|
val.d = decode_float(&buf[sizeof(float) * 3]);
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 4;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2021-01-20 08:02:02 +01:00
|
|
|
case Variant::QUATERNION: {
|
|
|
|
Quaternion val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
|
|
val.x = decode_double(&buf[0]);
|
|
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
|
|
val.z = decode_double(&buf[sizeof(double) * 2]);
|
|
|
|
val.w = decode_double(&buf[sizeof(double) * 3]);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 4;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA);
|
|
|
|
val.x = decode_float(&buf[0]);
|
|
|
|
val.y = decode_float(&buf[sizeof(float)]);
|
|
|
|
val.z = decode_float(&buf[sizeof(float) * 2]);
|
|
|
|
val.w = decode_float(&buf[sizeof(float) * 3]);
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 4;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2017-11-17 03:09:00 +01:00
|
|
|
case Variant::AABB: {
|
|
|
|
AABB val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA);
|
|
|
|
val.position.x = decode_double(&buf[0]);
|
|
|
|
val.position.y = decode_double(&buf[sizeof(double)]);
|
|
|
|
val.position.z = decode_double(&buf[sizeof(double) * 2]);
|
|
|
|
val.size.x = decode_double(&buf[sizeof(double) * 3]);
|
|
|
|
val.size.y = decode_double(&buf[sizeof(double) * 4]);
|
|
|
|
val.size.z = decode_double(&buf[sizeof(double) * 5]);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 6;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 6, ERR_INVALID_DATA);
|
|
|
|
val.position.x = decode_float(&buf[0]);
|
|
|
|
val.position.y = decode_float(&buf[sizeof(float)]);
|
|
|
|
val.position.z = decode_float(&buf[sizeof(float) * 2]);
|
|
|
|
val.size.x = decode_float(&buf[sizeof(float) * 3]);
|
|
|
|
val.size.y = decode_float(&buf[sizeof(float) * 4]);
|
|
|
|
val.size.z = decode_float(&buf[sizeof(float) * 5]);
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 6;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2017-01-11 04:52:51 +01:00
|
|
|
case Variant::BASIS: {
|
|
|
|
Basis val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 9, ERR_INVALID_DATA);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 3; j++) {
|
2022-04-25 00:07:35 +02:00
|
|
|
val.rows[i][j] = decode_double(&buf[(i * 3 + j) * sizeof(double)]);
|
2020-03-17 04:11:41 +01:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 9;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 9, ERR_INVALID_DATA);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 3; j++) {
|
2022-04-25 00:07:35 +02:00
|
|
|
val.rows[i][j] = decode_float(&buf[(i * 3 + j) * sizeof(float)]);
|
2020-03-17 04:11:41 +01:00
|
|
|
}
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 9;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2021-04-28 09:36:08 +02:00
|
|
|
case Variant::TRANSFORM3D: {
|
2020-10-17 07:08:21 +02:00
|
|
|
Transform3D val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 12, ERR_INVALID_DATA);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 3; j++) {
|
2022-04-25 00:07:35 +02:00
|
|
|
val.basis.rows[i][j] = decode_double(&buf[(i * 3 + j) * sizeof(double)]);
|
2020-03-17 04:11:41 +01:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
val.origin[0] = decode_double(&buf[sizeof(double) * 9]);
|
|
|
|
val.origin[1] = decode_double(&buf[sizeof(double) * 10]);
|
|
|
|
val.origin[2] = decode_double(&buf[sizeof(double) * 11]);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 12;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 12, ERR_INVALID_DATA);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 3; j++) {
|
2022-04-25 00:07:35 +02:00
|
|
|
val.basis.rows[i][j] = decode_float(&buf[(i * 3 + j) * sizeof(float)]);
|
2020-03-17 04:11:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
val.origin[0] = decode_float(&buf[sizeof(float) * 9]);
|
|
|
|
val.origin[1] = decode_float(&buf[sizeof(float) * 10]);
|
|
|
|
val.origin[2] = decode_float(&buf[sizeof(float) * 11]);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 12;
|
|
|
|
}
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_variant = val;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
} break;
|
|
|
|
case Variant::PROJECTION: {
|
|
|
|
Projection val;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 16, ERR_INVALID_DATA);
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
for (int j = 0; j < 4; j++) {
|
2022-10-04 18:44:48 +02:00
|
|
|
val.columns[i][j] = decode_double(&buf[(i * 4 + j) * sizeof(double)]);
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(double) * 16;
|
|
|
|
}
|
|
|
|
} else {
|
2022-09-01 18:07:01 +02:00
|
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 16, ERR_INVALID_DATA);
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
for (int j = 0; j < 4; j++) {
|
2022-10-04 18:44:48 +02:00
|
|
|
val.columns[i][j] = decode_float(&buf[(i * 4 + j) * sizeof(float)]);
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += sizeof(float) * 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_variant = val;
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
// misc types
|
|
|
|
case Variant::COLOR: {
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
|
2014-02-10 02:10:30 +01:00
|
|
|
Color val;
|
|
|
|
val.r = decode_float(&buf[0]);
|
|
|
|
val.g = decode_float(&buf[4]);
|
|
|
|
val.b = decode_float(&buf[8]);
|
|
|
|
val.a = decode_float(&buf[12]);
|
|
|
|
r_variant = val;
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += 4 * 4; // Colors should always be in single-precision.
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2020-02-20 22:58:05 +01:00
|
|
|
case Variant::STRING_NAME: {
|
|
|
|
String str;
|
|
|
|
Error err = _decode_string(buf, len, r_len, str);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (err) {
|
2020-02-20 22:58:05 +01:00
|
|
|
return err;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2020-02-20 22:58:05 +01:00
|
|
|
r_variant = StringName(str);
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::NODE_PATH: {
|
2016-03-09 00:00:52 +01:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t strlen = decode_uint32(buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2014-03-14 02:57:24 +01:00
|
|
|
if (strlen & 0x80000000) {
|
|
|
|
//new format
|
|
|
|
ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA);
|
|
|
|
Vector<StringName> names;
|
|
|
|
Vector<StringName> subnames;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2014-03-14 02:57:24 +01:00
|
|
|
uint32_t namecount = strlen &= 0x7FFFFFFF;
|
|
|
|
uint32_t subnamecount = decode_uint32(buf + 4);
|
2023-06-14 12:25:18 +02:00
|
|
|
uint32_t np_flags = decode_uint32(buf + 8);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2014-03-14 02:57:24 +01:00
|
|
|
len -= 12;
|
|
|
|
buf += 12;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
if (np_flags & 2) { // Obsolete format with property separate from subpath.
|
2017-05-30 22:20:15 +02:00
|
|
|
subnamecount++;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-05-30 22:20:15 +02:00
|
|
|
|
2017-08-31 23:30:35 +02:00
|
|
|
uint32_t total = namecount + subnamecount;
|
2014-03-14 02:57:24 +01:00
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2014-03-14 02:57:24 +01:00
|
|
|
(*r_len) += 12;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-03-14 02:57:24 +01:00
|
|
|
|
2017-08-31 23:30:35 +02:00
|
|
|
for (uint32_t i = 0; i < total; i++) {
|
2014-03-14 02:57:24 +01:00
|
|
|
String str;
|
2018-07-08 15:11:41 +02:00
|
|
|
Error err = _decode_string(buf, len, r_len, str);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (err) {
|
2018-07-08 15:11:41 +02:00
|
|
|
return err;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-03-14 02:57:24 +01:00
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (i < namecount) {
|
2014-03-14 02:57:24 +01:00
|
|
|
names.push_back(str);
|
2020-05-14 16:41:43 +02:00
|
|
|
} else {
|
2017-05-30 22:20:15 +02:00
|
|
|
subnames.push_back(str);
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-03-14 02:57:24 +01:00
|
|
|
}
|
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
r_variant = NodePath(names, subnames, np_flags & 1);
|
2014-03-14 02:57:24 +01:00
|
|
|
|
|
|
|
} else {
|
|
|
|
//old format, just a string
|
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_V(ERR_INVALID_DATA);
|
2014-03-14 02:57:24 +01:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2020-11-09 14:53:05 +01:00
|
|
|
case Variant::RID: {
|
2022-06-30 02:15:04 +02:00
|
|
|
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
|
|
|
|
uint64_t id = decode_uint64(buf);
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_variant = RID::from_uint64(id);
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::OBJECT: {
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_OBJECT_AS_ID) {
|
|
|
|
// This _is_ allowed.
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
|
2020-02-12 18:24:06 +01:00
|
|
|
ObjectID val = ObjectID(decode_uint64(buf));
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2017-08-18 15:59:31 +02:00
|
|
|
(*r_len) += 8;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2020-02-12 18:24:06 +01:00
|
|
|
if (val.is_null()) {
|
2020-04-02 01:20:12 +02:00
|
|
|
r_variant = (Object *)nullptr;
|
2017-08-18 15:59:31 +02:00
|
|
|
} else {
|
|
|
|
Ref<EncodedObjectAsID> obj_as_id;
|
2021-06-18 00:03:09 +02:00
|
|
|
obj_as_id.instantiate();
|
2017-08-18 15:59:31 +02:00
|
|
|
obj_as_id->set_object_id(val);
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
r_variant = obj_as_id;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V(!p_allow_objects, ERR_UNAUTHORIZED);
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
String str;
|
|
|
|
Error err = _decode_string(buf, len, r_len, str);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (err) {
|
2017-08-18 15:59:31 +02:00
|
|
|
return err;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2021-12-09 10:42:46 +01:00
|
|
|
if (str.is_empty()) {
|
2020-04-02 01:20:12 +02:00
|
|
|
r_variant = (Object *)nullptr;
|
2017-08-18 15:59:31 +02:00
|
|
|
} else {
|
2023-11-08 11:53:28 +01:00
|
|
|
ERR_FAIL_COND_V(!ClassDB::can_instantiate(str), ERR_INVALID_DATA);
|
|
|
|
|
2021-06-18 00:03:09 +02:00
|
|
|
Object *obj = ClassDB::instantiate(str);
|
2023-09-09 16:11:33 +02:00
|
|
|
ERR_FAIL_NULL_V(obj, ERR_UNAVAILABLE);
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2024-04-15 12:23:52 +02:00
|
|
|
// Avoid premature free `RefCounted`. This must be done before properties are initialized,
|
|
|
|
// since script functions (setters, implicit initializer) may be called. See GH-68666.
|
|
|
|
Variant variant;
|
|
|
|
if (Object::cast_to<RefCounted>(obj)) {
|
|
|
|
Ref<RefCounted> ref = Ref<RefCounted>(Object::cast_to<RefCounted>(obj));
|
|
|
|
variant = ref;
|
|
|
|
} else {
|
|
|
|
variant = obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2017-08-18 15:59:31 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
2017-08-14 16:58:10 +02:00
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += 4; // Size of count number.
|
2017-08-14 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
str = String();
|
|
|
|
err = _decode_string(buf, len, r_len, str);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (err) {
|
2017-08-18 15:59:31 +02:00
|
|
|
return err;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-08-18 15:59:31 +02:00
|
|
|
|
|
|
|
Variant value;
|
|
|
|
int used;
|
2022-02-14 21:04:05 +01:00
|
|
|
err = decode_variant(value, buf, len, &used, p_allow_objects, p_depth + 1);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (err) {
|
2017-08-18 15:59:31 +02:00
|
|
|
return err;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-08-18 15:59:31 +02:00
|
|
|
|
|
|
|
buf += used;
|
|
|
|
len -= used;
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += used;
|
|
|
|
}
|
|
|
|
|
2024-04-07 09:53:58 +02:00
|
|
|
if (str == "script" && value.get_type() != Variant::NIL) {
|
2023-06-14 12:25:18 +02:00
|
|
|
ERR_FAIL_COND_V_MSG(value.get_type() != Variant::STRING, ERR_INVALID_DATA, "Invalid value for \"script\" property, expected script path as String.");
|
|
|
|
String path = value;
|
|
|
|
ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, "Invalid script path: '" + path + "'.");
|
|
|
|
Ref<Script> script = ResourceLoader::load(path, "Script");
|
|
|
|
ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, "Can't load script at path: '" + path + "'.");
|
|
|
|
obj->set_script(script);
|
|
|
|
} else {
|
|
|
|
obj->set(str, value);
|
|
|
|
}
|
2017-08-18 15:59:31 +02:00
|
|
|
}
|
|
|
|
|
2024-04-15 12:23:52 +02:00
|
|
|
r_variant = variant;
|
2017-08-14 16:58:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2020-02-19 20:27:19 +01:00
|
|
|
case Variant::CALLABLE: {
|
|
|
|
r_variant = Callable();
|
|
|
|
} break;
|
|
|
|
case Variant::SIGNAL: {
|
2022-06-30 02:15:04 +02:00
|
|
|
String name;
|
|
|
|
Error err = _decode_string(buf, len, r_len, name);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2020-02-19 20:27:19 +01:00
|
|
|
|
2022-06-30 02:15:04 +02:00
|
|
|
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
|
|
|
|
ObjectID id = ObjectID(decode_uint64(buf));
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_variant = Signal(id, StringName(name));
|
|
|
|
} break;
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::DICTIONARY: {
|
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2017-01-11 12:53:31 +01:00
|
|
|
// bool shared = count&0x80000000;
|
2014-02-10 02:10:30 +01:00
|
|
|
count &= 0x7FFFFFFF;
|
|
|
|
|
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
|
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += 4; // Size of count number.
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-01-11 12:53:31 +01:00
|
|
|
Dictionary d;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
Variant key, value;
|
|
|
|
|
|
|
|
int used;
|
2022-02-14 21:04:05 +01:00
|
|
|
Error err = decode_variant(key, buf, len, &used, p_allow_objects, p_depth + 1);
|
2019-09-25 10:28:50 +02:00
|
|
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to decode Variant.");
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
buf += used;
|
|
|
|
len -= used;
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += used;
|
|
|
|
}
|
|
|
|
|
2022-02-14 21:04:05 +01:00
|
|
|
err = decode_variant(value, buf, len, &used, p_allow_objects, p_depth + 1);
|
2019-09-25 10:28:50 +02:00
|
|
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to decode Variant.");
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
buf += used;
|
|
|
|
len -= used;
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += used;
|
|
|
|
}
|
|
|
|
|
|
|
|
d[key] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_variant = d;
|
|
|
|
|
|
|
|
} break;
|
|
|
|
case Variant::ARRAY: {
|
2023-06-14 12:25:18 +02:00
|
|
|
Variant::Type builtin_type = Variant::VARIANT_MAX;
|
|
|
|
StringName class_name;
|
|
|
|
Ref<Script> script;
|
|
|
|
|
|
|
|
switch (header & HEADER_DATA_FIELD_TYPED_ARRAY_MASK) {
|
|
|
|
case HEADER_DATA_FIELD_TYPED_ARRAY_NONE:
|
|
|
|
break; // Untyped array.
|
|
|
|
case HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN: {
|
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
|
|
|
|
|
|
int32_t bt = decode_uint32(buf);
|
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR_FAIL_INDEX_V(bt, Variant::VARIANT_MAX, ERR_INVALID_DATA);
|
|
|
|
builtin_type = (Variant::Type)bt;
|
|
|
|
ERR_FAIL_COND_V(!p_allow_objects && builtin_type == Variant::OBJECT, ERR_UNAUTHORIZED);
|
|
|
|
} break;
|
|
|
|
case HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME: {
|
|
|
|
ERR_FAIL_COND_V(!p_allow_objects, ERR_UNAUTHORIZED);
|
|
|
|
|
|
|
|
String str;
|
|
|
|
Error err = _decode_string(buf, len, r_len, str);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
builtin_type = Variant::OBJECT;
|
|
|
|
class_name = str;
|
|
|
|
} break;
|
|
|
|
case HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT: {
|
|
|
|
ERR_FAIL_COND_V(!p_allow_objects, ERR_UNAUTHORIZED);
|
|
|
|
|
|
|
|
String path;
|
|
|
|
Error err = _decode_string(buf, len, r_len, path);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, "Invalid script path: '" + path + "'.");
|
|
|
|
script = ResourceLoader::load(path, "Script");
|
|
|
|
ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, "Can't load script at path: '" + path + "'.");
|
|
|
|
|
|
|
|
builtin_type = Variant::OBJECT;
|
|
|
|
class_name = script->get_instance_base_type();
|
|
|
|
} break;
|
|
|
|
default:
|
|
|
|
ERR_FAIL_V(ERR_INVALID_DATA); // Future proofing.
|
|
|
|
}
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2023-06-14 12:25:18 +02:00
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2017-01-11 12:53:31 +01:00
|
|
|
// bool shared = count&0x80000000;
|
2014-02-10 02:10:30 +01:00
|
|
|
count &= 0x7FFFFFFF;
|
|
|
|
|
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
|
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += 4; // Size of count number.
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2017-01-11 12:53:31 +01:00
|
|
|
Array varr;
|
2023-06-14 12:25:18 +02:00
|
|
|
if (builtin_type != Variant::VARIANT_MAX) {
|
|
|
|
varr.set_typed(builtin_type, class_name, script);
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
int used = 0;
|
|
|
|
Variant v;
|
2022-02-14 21:04:05 +01:00
|
|
|
Error err = decode_variant(v, buf, len, &used, p_allow_objects, p_depth + 1);
|
2019-09-25 10:28:50 +02:00
|
|
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to decode Variant.");
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += used;
|
|
|
|
len -= used;
|
|
|
|
varr.push_back(v);
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += used;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r_variant = varr;
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
// arrays
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_BYTE_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_COND_V(count < 0 || count > len, ERR_INVALID_DATA);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<uint8_t> data;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (count) {
|
|
|
|
data.resize(count);
|
2020-02-17 22:06:54 +01:00
|
|
|
uint8_t *w = data.ptrw();
|
2018-07-08 15:11:41 +02:00
|
|
|
for (int32_t i = 0; i < count; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
w[i] = buf[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r_variant = data;
|
|
|
|
|
|
|
|
if (r_len) {
|
2020-05-14 16:41:43 +02:00
|
|
|
if (count % 4) {
|
2014-02-10 02:10:30 +01:00
|
|
|
(*r_len) += 4 - count % 4;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
(*r_len) += 4 + count;
|
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::PACKED_INT32_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
Vector<int32_t> data;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (count) {
|
|
|
|
//const int*rbuf=(const int*)buf;
|
|
|
|
data.resize(count);
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
int32_t *w = data.ptrw();
|
2018-07-08 15:11:41 +02:00
|
|
|
for (int32_t i = 0; i < count; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
w[i] = decode_uint32(&buf[i * 4]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_variant = Variant(data);
|
|
|
|
if (r_len) {
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
(*r_len) += 4 + count * sizeof(int32_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::PACKED_INT64_ARRAY: {
|
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2021-08-02 13:34:06 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
ERR_FAIL_MUL_OF(count, 8, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * 8 > len, ERR_INVALID_DATA);
|
|
|
|
|
|
|
|
Vector<int64_t> data;
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
//const int*rbuf=(const int*)buf;
|
|
|
|
data.resize(count);
|
|
|
|
int64_t *w = data.ptrw();
|
|
|
|
for (int64_t i = 0; i < count; i++) {
|
|
|
|
w[i] = decode_uint64(&buf[i * 8]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_variant = Variant(data);
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 4 + count * sizeof(int64_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
|
|
|
case Variant::PACKED_FLOAT32_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<float> data;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (count) {
|
|
|
|
//const float*rbuf=(const float*)buf;
|
|
|
|
data.resize(count);
|
2020-02-17 22:06:54 +01:00
|
|
|
float *w = data.ptrw();
|
2018-07-08 15:11:41 +02:00
|
|
|
for (int32_t i = 0; i < count; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
w[i] = decode_float(&buf[i * 4]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_variant = data;
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 4 + count * sizeof(float);
|
|
|
|
}
|
|
|
|
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
} break;
|
|
|
|
case Variant::PACKED_FLOAT64_ARRAY: {
|
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2021-08-02 13:34:06 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
ERR_FAIL_MUL_OF(count, 8, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * 8 > len, ERR_INVALID_DATA);
|
|
|
|
|
|
|
|
Vector<double> data;
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
data.resize(count);
|
|
|
|
double *w = data.ptrw();
|
|
|
|
for (int64_t i = 0; i < count; i++) {
|
|
|
|
w[i] = decode_double(&buf[i * 8]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_variant = data;
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 4 + count * sizeof(double);
|
|
|
|
}
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_STRING_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<String> strings;
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += 4; // Size of count number.
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
for (int32_t i = 0; i < count; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
String str;
|
2018-07-08 15:11:41 +02:00
|
|
|
Error err = _decode_string(buf, len, r_len, str);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (err) {
|
2018-07-08 15:11:41 +02:00
|
|
|
return err;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
strings.push_back(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_variant = strings;
|
|
|
|
|
2013-04-10 10:37:04 +02:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_VECTOR2_ARRAY: {
|
2013-04-10 10:37:04 +02:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2013-04-10 10:37:04 +02:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<Vector2> varray;
|
2013-04-10 10:37:04 +02:00
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_MUL_OF(count, sizeof(double) * 2, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * sizeof(double) * 2 > (size_t)len, ERR_INVALID_DATA);
|
2013-04-10 10:37:04 +02:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 4; // Size of count number.
|
2013-04-10 10:37:04 +02:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (count) {
|
|
|
|
varray.resize(count);
|
|
|
|
Vector2 *w = varray.ptrw();
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < count; i++) {
|
|
|
|
w[i].x = decode_double(buf + i * sizeof(double) * 2 + sizeof(double) * 0);
|
|
|
|
w[i].y = decode_double(buf + i * sizeof(double) * 2 + sizeof(double) * 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int adv = sizeof(double) * 2 * count;
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += adv;
|
|
|
|
}
|
|
|
|
len -= adv;
|
|
|
|
buf += adv;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_MUL_OF(count, sizeof(float) * 2, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * sizeof(float) * 2 > (size_t)len, ERR_INVALID_DATA);
|
2013-04-10 10:37:04 +02:00
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += 4; // Size of count number.
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2013-04-10 10:37:04 +02:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (count) {
|
|
|
|
varray.resize(count);
|
|
|
|
Vector2 *w = varray.ptrw();
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < count; i++) {
|
|
|
|
w[i].x = decode_float(buf + i * sizeof(float) * 2 + sizeof(float) * 0);
|
|
|
|
w[i].y = decode_float(buf + i * sizeof(float) * 2 + sizeof(float) * 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int adv = sizeof(float) * 2 * count;
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += adv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-04-10 10:37:04 +02:00
|
|
|
r_variant = varray;
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_VECTOR3_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<Vector3> varray;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2020-03-17 04:11:41 +01:00
|
|
|
ERR_FAIL_MUL_OF(count, sizeof(double) * 3, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * sizeof(double) * 3 > (size_t)len, ERR_INVALID_DATA);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += 4; // Size of count number.
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (count) {
|
|
|
|
varray.resize(count);
|
|
|
|
Vector3 *w = varray.ptrw();
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < count; i++) {
|
|
|
|
w[i].x = decode_double(buf + i * sizeof(double) * 3 + sizeof(double) * 0);
|
|
|
|
w[i].y = decode_double(buf + i * sizeof(double) * 3 + sizeof(double) * 1);
|
|
|
|
w[i].z = decode_double(buf + i * sizeof(double) * 3 + sizeof(double) * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
int adv = sizeof(double) * 3 * count;
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += adv;
|
|
|
|
}
|
|
|
|
len -= adv;
|
|
|
|
buf += adv;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_MUL_OF(count, sizeof(float) * 3, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * sizeof(float) * 3 > (size_t)len, ERR_INVALID_DATA);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += 4; // Size of count number.
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
if (count) {
|
|
|
|
varray.resize(count);
|
|
|
|
Vector3 *w = varray.ptrw();
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < count; i++) {
|
|
|
|
w[i].x = decode_float(buf + i * sizeof(float) * 3 + sizeof(float) * 0);
|
|
|
|
w[i].y = decode_float(buf + i * sizeof(float) * 3 + sizeof(float) * 1);
|
|
|
|
w[i].z = decode_float(buf + i * sizeof(float) * 3 + sizeof(float) * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
int adv = sizeof(float) * 3 * count;
|
|
|
|
|
|
|
|
if (r_len) {
|
|
|
|
(*r_len) += adv;
|
|
|
|
}
|
|
|
|
len -= adv;
|
|
|
|
buf += adv;
|
|
|
|
}
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
r_variant = varray;
|
|
|
|
|
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_COLOR_ARRAY: {
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
2018-07-08 15:11:41 +02:00
|
|
|
int32_t count = decode_uint32(buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
len -= 4;
|
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
ERR_FAIL_MUL_OF(count, 4 * 4, ERR_INVALID_DATA);
|
|
|
|
ERR_FAIL_COND_V(count < 0 || count * 4 * 4 > len, ERR_INVALID_DATA);
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Vector<Color> carray;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (r_len) {
|
2020-03-17 04:11:41 +01:00
|
|
|
(*r_len) += 4; // Size of count number.
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
carray.resize(count);
|
2020-02-17 22:06:54 +01:00
|
|
|
Color *w = carray.ptrw();
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2018-07-08 15:11:41 +02:00
|
|
|
for (int32_t i = 0; i < count; i++) {
|
2020-03-17 04:11:41 +01:00
|
|
|
// Colors should always be in single-precision.
|
2014-02-10 02:10:30 +01:00
|
|
|
w[i].r = decode_float(buf + i * 4 * 4 + 4 * 0);
|
|
|
|
w[i].g = decode_float(buf + i * 4 * 4 + 4 * 1);
|
|
|
|
w[i].b = decode_float(buf + i * 4 * 4 + 4 * 2);
|
|
|
|
w[i].a = decode_float(buf + i * 4 * 4 + 4 * 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
int adv = 4 * 4 * count;
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (r_len) {
|
2014-02-10 02:10:30 +01:00
|
|
|
(*r_len) += adv;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r_variant = carray;
|
|
|
|
|
|
|
|
} break;
|
2019-04-09 17:08:36 +02:00
|
|
|
default: {
|
|
|
|
ERR_FAIL_V(ERR_BUG);
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2017-08-14 16:58:10 +02:00
|
|
|
static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) {
|
|
|
|
CharString utf8 = p_string.utf8();
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(utf8.length(), buf);
|
|
|
|
buf += 4;
|
2021-04-27 16:19:21 +02:00
|
|
|
memcpy(buf, utf8.get_data(), utf8.length());
|
2017-08-21 16:20:13 +02:00
|
|
|
buf += utf8.length();
|
2017-08-14 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 + utf8.length();
|
2017-08-21 16:20:13 +02:00
|
|
|
while (r_len % 4) {
|
2017-08-14 16:58:10 +02:00
|
|
|
r_len++; //pad
|
2017-08-21 16:20:13 +02:00
|
|
|
if (buf) {
|
2018-03-04 18:45:33 +01:00
|
|
|
*(buf++) = 0;
|
2017-08-21 16:20:13 +02:00
|
|
|
}
|
|
|
|
}
|
2017-08-14 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2021-07-30 15:43:01 +02:00
|
|
|
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects, int p_depth) {
|
2022-02-10 12:00:11 +01:00
|
|
|
ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Potential infinite recursion detected. Bailing.");
|
2014-02-10 02:10:30 +01:00
|
|
|
uint8_t *buf = r_buffer;
|
|
|
|
|
|
|
|
r_len = 0;
|
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
uint32_t header = p_variant.get_type();
|
2017-01-09 00:58:39 +01:00
|
|
|
|
|
|
|
switch (p_variant.get_type()) {
|
|
|
|
case Variant::INT: {
|
|
|
|
int64_t val = p_variant;
|
2018-09-18 18:31:37 +02:00
|
|
|
if (val > (int64_t)INT_MAX || val < (int64_t)INT_MIN) {
|
2023-06-14 12:25:18 +02:00
|
|
|
header |= HEADER_DATA_FLAG_64;
|
2017-01-09 00:58:39 +01:00
|
|
|
}
|
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::FLOAT: {
|
2017-01-09 00:58:39 +01:00
|
|
|
double d = p_variant;
|
|
|
|
float f = d;
|
|
|
|
if (double(f) != d) {
|
2023-06-14 12:25:18 +02:00
|
|
|
header |= HEADER_DATA_FLAG_64;
|
2017-01-09 00:58:39 +01:00
|
|
|
}
|
|
|
|
} break;
|
2017-08-18 15:59:31 +02:00
|
|
|
case Variant::OBJECT: {
|
2020-01-09 17:59:33 +01:00
|
|
|
// Test for potential wrong values sent by the debugger when it breaks.
|
2020-02-13 20:03:10 +01:00
|
|
|
Object *obj = p_variant.get_validated_object();
|
|
|
|
if (!obj) {
|
2021-06-07 10:17:32 +02:00
|
|
|
// Object is invalid, send a nullptr instead.
|
2020-01-09 17:59:33 +01:00
|
|
|
if (buf) {
|
|
|
|
encode_uint32(Variant::NIL, buf);
|
|
|
|
}
|
|
|
|
r_len += 4;
|
|
|
|
return OK;
|
|
|
|
}
|
2020-02-13 20:03:10 +01:00
|
|
|
|
2019-03-28 09:40:31 +01:00
|
|
|
if (!p_full_objects) {
|
2023-06-14 12:25:18 +02:00
|
|
|
header |= HEADER_DATA_FLAG_OBJECT_AS_ID;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case Variant::ARRAY: {
|
|
|
|
Array array = p_variant;
|
|
|
|
if (array.is_typed()) {
|
|
|
|
Ref<Script> script = array.get_typed_script();
|
|
|
|
if (script.is_valid()) {
|
|
|
|
ERR_FAIL_COND_V(!p_full_objects, ERR_UNAVAILABLE);
|
|
|
|
header |= HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT;
|
|
|
|
} else if (array.get_typed_class_name() != StringName()) {
|
|
|
|
ERR_FAIL_COND_V(!p_full_objects, ERR_UNAVAILABLE);
|
|
|
|
header |= HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME;
|
|
|
|
} else {
|
|
|
|
ERR_FAIL_COND_V(!p_full_objects && array.get_typed_builtin() == Variant::OBJECT, ERR_UNAVAILABLE);
|
|
|
|
header |= HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN;
|
|
|
|
}
|
2017-08-18 15:59:31 +02:00
|
|
|
}
|
|
|
|
} break;
|
2022-02-16 21:13:47 +01:00
|
|
|
#ifdef REAL_T_IS_DOUBLE
|
|
|
|
case Variant::VECTOR2:
|
|
|
|
case Variant::VECTOR3:
|
2023-10-12 18:18:45 +02:00
|
|
|
case Variant::VECTOR4:
|
2022-02-16 21:13:47 +01:00
|
|
|
case Variant::PACKED_VECTOR2_ARRAY:
|
|
|
|
case Variant::PACKED_VECTOR3_ARRAY:
|
|
|
|
case Variant::TRANSFORM2D:
|
|
|
|
case Variant::TRANSFORM3D:
|
2023-10-12 18:18:45 +02:00
|
|
|
case Variant::PROJECTION:
|
2022-02-16 21:13:47 +01:00
|
|
|
case Variant::QUATERNION:
|
|
|
|
case Variant::PLANE:
|
|
|
|
case Variant::BASIS:
|
|
|
|
case Variant::RECT2:
|
|
|
|
case Variant::AABB: {
|
2023-06-14 12:25:18 +02:00
|
|
|
header |= HEADER_DATA_FLAG_64;
|
2022-02-16 21:13:47 +01:00
|
|
|
} break;
|
|
|
|
#endif // REAL_T_IS_DOUBLE
|
2019-04-09 17:08:36 +02:00
|
|
|
default: {
|
|
|
|
} // nothing to do at this stage
|
2017-01-09 00:58:39 +01:00
|
|
|
}
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
if (buf) {
|
2023-06-14 12:25:18 +02:00
|
|
|
encode_uint32(header, buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
}
|
|
|
|
r_len += 4;
|
|
|
|
|
|
|
|
switch (p_variant.get_type()) {
|
|
|
|
case Variant::NIL: {
|
|
|
|
//nothing to do
|
|
|
|
} break;
|
|
|
|
case Variant::BOOL: {
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(p_variant.operator bool(), buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4;
|
|
|
|
|
|
|
|
} break;
|
|
|
|
case Variant::INT: {
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2017-01-09 00:58:39 +01:00
|
|
|
//64 bits
|
|
|
|
if (buf) {
|
2018-10-02 20:21:08 +02:00
|
|
|
encode_uint64(p_variant.operator int64_t(), buf);
|
2017-01-09 00:58:39 +01:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-01-09 00:58:39 +01:00
|
|
|
r_len += 8;
|
|
|
|
} else {
|
|
|
|
if (buf) {
|
2018-10-02 20:21:08 +02:00
|
|
|
encode_uint32(p_variant.operator int32_t(), buf);
|
2017-01-09 00:58:39 +01:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2017-01-09 00:58:39 +01:00
|
|
|
r_len += 4;
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::FLOAT: {
|
2023-06-14 12:25:18 +02:00
|
|
|
if (header & HEADER_DATA_FLAG_64) {
|
2017-01-09 00:58:39 +01:00
|
|
|
if (buf) {
|
|
|
|
encode_double(p_variant.operator double(), buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 8;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (buf) {
|
2017-04-11 19:17:56 +02:00
|
|
|
encode_float(p_variant.operator float(), buf);
|
2017-01-09 00:58:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4;
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
2014-03-14 02:57:24 +01:00
|
|
|
case Variant::NODE_PATH: {
|
|
|
|
NodePath np = p_variant;
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format
|
|
|
|
encode_uint32(np.get_subname_count(), buf + 4);
|
2019-02-12 21:10:08 +01:00
|
|
|
uint32_t np_flags = 0;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (np.is_absolute()) {
|
2019-02-12 21:10:08 +01:00
|
|
|
np_flags |= 1;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-03-14 02:57:24 +01:00
|
|
|
|
2019-02-12 21:10:08 +01:00
|
|
|
encode_uint32(np_flags, buf + 8);
|
2014-03-14 02:57:24 +01:00
|
|
|
|
|
|
|
buf += 12;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 12;
|
|
|
|
|
|
|
|
int total = np.get_name_count() + np.get_subname_count();
|
|
|
|
|
|
|
|
for (int i = 0; i < total; i++) {
|
|
|
|
String str;
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (i < np.get_name_count()) {
|
2014-03-14 02:57:24 +01:00
|
|
|
str = np.get_name(i);
|
2020-05-14 16:41:43 +02:00
|
|
|
} else {
|
2017-05-30 22:20:15 +02:00
|
|
|
str = np.get_subname(i - np.get_name_count());
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-03-14 02:57:24 +01:00
|
|
|
|
|
|
|
CharString utf8 = str.utf8();
|
|
|
|
|
|
|
|
int pad = 0;
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (utf8.length() % 4) {
|
2014-03-14 02:57:24 +01:00
|
|
|
pad = 4 - utf8.length() % 4;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-03-14 02:57:24 +01:00
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(utf8.length(), buf);
|
|
|
|
buf += 4;
|
2021-04-27 16:19:21 +02:00
|
|
|
memcpy(buf, utf8.get_data(), utf8.length());
|
2014-03-14 02:57:24 +01:00
|
|
|
buf += pad + utf8.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 + utf8.length() + pad;
|
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
2020-12-08 19:58:49 +01:00
|
|
|
case Variant::STRING:
|
2020-02-20 22:58:05 +01:00
|
|
|
case Variant::STRING_NAME: {
|
|
|
|
_encode_string(p_variant, buf, r_len);
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
|
2017-12-06 21:36:34 +01:00
|
|
|
// math types
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::VECTOR2: {
|
|
|
|
if (buf) {
|
|
|
|
Vector2 v2 = p_variant;
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(v2.x, &buf[0]);
|
|
|
|
encode_real(v2.y, &buf[sizeof(real_t)]);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 2 * sizeof(real_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-24 17:00:40 +01:00
|
|
|
} break;
|
2020-02-22 04:26:41 +01:00
|
|
|
case Variant::VECTOR2I: {
|
|
|
|
if (buf) {
|
|
|
|
Vector2i v2 = p_variant;
|
|
|
|
encode_uint32(v2.x, &buf[0]);
|
|
|
|
encode_uint32(v2.y, &buf[4]);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 2 * 4;
|
|
|
|
|
2020-02-24 17:00:40 +01:00
|
|
|
} break;
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::RECT2: {
|
|
|
|
if (buf) {
|
|
|
|
Rect2 r2 = p_variant;
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(r2.position.x, &buf[0]);
|
|
|
|
encode_real(r2.position.y, &buf[sizeof(real_t)]);
|
|
|
|
encode_real(r2.size.x, &buf[sizeof(real_t) * 2]);
|
|
|
|
encode_real(r2.size.y, &buf[sizeof(real_t) * 3]);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 4 * sizeof(real_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-22 04:26:41 +01:00
|
|
|
} break;
|
|
|
|
case Variant::RECT2I: {
|
|
|
|
if (buf) {
|
|
|
|
Rect2i r2 = p_variant;
|
|
|
|
encode_uint32(r2.position.x, &buf[0]);
|
|
|
|
encode_uint32(r2.position.y, &buf[4]);
|
|
|
|
encode_uint32(r2.size.x, &buf[8]);
|
|
|
|
encode_uint32(r2.size.y, &buf[12]);
|
|
|
|
}
|
|
|
|
r_len += 4 * 4;
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::VECTOR3: {
|
|
|
|
if (buf) {
|
|
|
|
Vector3 v3 = p_variant;
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(v3.x, &buf[0]);
|
|
|
|
encode_real(v3.y, &buf[sizeof(real_t)]);
|
|
|
|
encode_real(v3.z, &buf[sizeof(real_t) * 2]);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 3 * sizeof(real_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2020-02-22 04:26:41 +01:00
|
|
|
} break;
|
|
|
|
case Variant::VECTOR3I: {
|
|
|
|
if (buf) {
|
|
|
|
Vector3i v3 = p_variant;
|
|
|
|
encode_uint32(v3.x, &buf[0]);
|
|
|
|
encode_uint32(v3.y, &buf[4]);
|
|
|
|
encode_uint32(v3.z, &buf[8]);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 3 * 4;
|
|
|
|
|
2013-04-10 10:37:04 +02:00
|
|
|
} break;
|
2017-01-11 04:52:51 +01:00
|
|
|
case Variant::TRANSFORM2D: {
|
2013-04-10 10:37:04 +02:00
|
|
|
if (buf) {
|
2017-01-11 04:52:51 +01:00
|
|
|
Transform2D val = p_variant;
|
2013-04-10 10:37:04 +02:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 2; j++) {
|
2022-04-24 23:59:24 +02:00
|
|
|
memcpy(&buf[(i * 2 + j) * sizeof(real_t)], &val.columns[i][j], sizeof(real_t));
|
2013-04-10 10:37:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 6 * sizeof(real_t);
|
2013-04-10 10:37:04 +02:00
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
} break;
|
|
|
|
case Variant::VECTOR4: {
|
|
|
|
if (buf) {
|
|
|
|
Vector4 v4 = p_variant;
|
|
|
|
encode_real(v4.x, &buf[0]);
|
|
|
|
encode_real(v4.y, &buf[sizeof(real_t)]);
|
|
|
|
encode_real(v4.z, &buf[sizeof(real_t) * 2]);
|
|
|
|
encode_real(v4.w, &buf[sizeof(real_t) * 3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 * sizeof(real_t);
|
|
|
|
|
|
|
|
} break;
|
|
|
|
case Variant::VECTOR4I: {
|
|
|
|
if (buf) {
|
|
|
|
Vector4i v4 = p_variant;
|
|
|
|
encode_uint32(v4.x, &buf[0]);
|
|
|
|
encode_uint32(v4.y, &buf[4]);
|
|
|
|
encode_uint32(v4.z, &buf[8]);
|
|
|
|
encode_uint32(v4.w, &buf[12]);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 * 4;
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
case Variant::PLANE: {
|
|
|
|
if (buf) {
|
|
|
|
Plane p = p_variant;
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(p.normal.x, &buf[0]);
|
|
|
|
encode_real(p.normal.y, &buf[sizeof(real_t)]);
|
|
|
|
encode_real(p.normal.z, &buf[sizeof(real_t) * 2]);
|
|
|
|
encode_real(p.d, &buf[sizeof(real_t) * 3]);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 4 * sizeof(real_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2021-01-20 08:02:02 +01:00
|
|
|
case Variant::QUATERNION: {
|
2014-02-10 02:10:30 +01:00
|
|
|
if (buf) {
|
2021-01-20 08:02:02 +01:00
|
|
|
Quaternion q = p_variant;
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(q.x, &buf[0]);
|
|
|
|
encode_real(q.y, &buf[sizeof(real_t)]);
|
|
|
|
encode_real(q.z, &buf[sizeof(real_t) * 2]);
|
|
|
|
encode_real(q.w, &buf[sizeof(real_t) * 3]);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 4 * sizeof(real_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2017-11-17 03:09:00 +01:00
|
|
|
case Variant::AABB: {
|
2014-02-10 02:10:30 +01:00
|
|
|
if (buf) {
|
2017-11-17 03:09:00 +01:00
|
|
|
AABB aabb = p_variant;
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(aabb.position.x, &buf[0]);
|
|
|
|
encode_real(aabb.position.y, &buf[sizeof(real_t)]);
|
|
|
|
encode_real(aabb.position.z, &buf[sizeof(real_t) * 2]);
|
|
|
|
encode_real(aabb.size.x, &buf[sizeof(real_t) * 3]);
|
|
|
|
encode_real(aabb.size.y, &buf[sizeof(real_t) * 4]);
|
|
|
|
encode_real(aabb.size.z, &buf[sizeof(real_t) * 5]);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 6 * sizeof(real_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2017-01-11 04:52:51 +01:00
|
|
|
case Variant::BASIS: {
|
2014-02-10 02:10:30 +01:00
|
|
|
if (buf) {
|
2017-01-11 04:52:51 +01:00
|
|
|
Basis val = p_variant;
|
2014-02-10 02:10:30 +01:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 3; j++) {
|
2022-04-25 00:07:35 +02:00
|
|
|
memcpy(&buf[(i * 3 + j) * sizeof(real_t)], &val.rows[i][j], sizeof(real_t));
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 9 * sizeof(real_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2021-04-28 09:36:08 +02:00
|
|
|
case Variant::TRANSFORM3D: {
|
2014-02-10 02:10:30 +01:00
|
|
|
if (buf) {
|
2020-10-17 07:08:21 +02:00
|
|
|
Transform3D val = p_variant;
|
2014-02-10 02:10:30 +01:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 3; j++) {
|
2022-04-25 00:07:35 +02:00
|
|
|
memcpy(&buf[(i * 3 + j) * sizeof(real_t)], &val.basis.rows[i][j], sizeof(real_t));
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(val.origin.x, &buf[sizeof(real_t) * 9]);
|
|
|
|
encode_real(val.origin.y, &buf[sizeof(real_t) * 10]);
|
|
|
|
encode_real(val.origin.z, &buf[sizeof(real_t) * 11]);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 12 * sizeof(real_t);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
} break;
|
|
|
|
case Variant::PROJECTION: {
|
|
|
|
if (buf) {
|
|
|
|
Projection val = p_variant;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
for (int j = 0; j < 4; j++) {
|
2022-10-04 18:44:48 +02:00
|
|
|
memcpy(&buf[(i * 4 + j) * sizeof(real_t)], &val.columns[i][j], sizeof(real_t));
|
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 16 * sizeof(real_t);
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
|
|
|
|
|
|
|
// misc types
|
|
|
|
case Variant::COLOR: {
|
|
|
|
if (buf) {
|
|
|
|
Color c = p_variant;
|
|
|
|
encode_float(c.r, &buf[0]);
|
|
|
|
encode_float(c.g, &buf[4]);
|
|
|
|
encode_float(c.b, &buf[8]);
|
|
|
|
encode_float(c.a, &buf[12]);
|
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += 4 * 4; // Colors should always be in single-precision.
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2016-03-09 00:00:52 +01:00
|
|
|
} break;
|
2020-11-09 14:53:05 +01:00
|
|
|
case Variant::RID: {
|
2022-06-30 02:15:04 +02:00
|
|
|
RID rid = p_variant;
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint64(rid.get_id(), buf);
|
|
|
|
}
|
|
|
|
r_len += 8;
|
2017-08-14 16:58:10 +02:00
|
|
|
} break;
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::OBJECT: {
|
2019-03-28 09:40:31 +01:00
|
|
|
if (p_full_objects) {
|
2017-08-18 15:59:31 +02:00
|
|
|
Object *obj = p_variant;
|
|
|
|
if (!obj) {
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(0, buf);
|
|
|
|
}
|
2017-10-08 20:13:46 +02:00
|
|
|
r_len += 4;
|
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
} else {
|
2023-11-08 11:53:28 +01:00
|
|
|
ERR_FAIL_COND_V(!ClassDB::can_instantiate(obj->get_class()), ERR_INVALID_PARAMETER);
|
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
_encode_string(obj->get_class(), buf, r_len);
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
List<PropertyInfo> props;
|
|
|
|
obj->get_property_list(&props);
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
int pc = 0;
|
2021-07-24 15:46:25 +02:00
|
|
|
for (const PropertyInfo &E : props) {
|
2021-07-16 05:45:57 +02:00
|
|
|
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
|
2017-08-18 15:59:31 +02:00
|
|
|
continue;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-08-18 15:59:31 +02:00
|
|
|
pc++;
|
|
|
|
}
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
if (buf) {
|
|
|
|
encode_uint32(pc, buf);
|
|
|
|
buf += 4;
|
|
|
|
}
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
r_len += 4;
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2021-07-24 15:46:25 +02:00
|
|
|
for (const PropertyInfo &E : props) {
|
2021-07-16 05:45:57 +02:00
|
|
|
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
|
2017-08-18 15:59:31 +02:00
|
|
|
continue;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2021-07-16 05:45:57 +02:00
|
|
|
_encode_string(E.name, buf, r_len);
|
2017-08-14 16:58:10 +02:00
|
|
|
|
2023-06-14 12:25:18 +02:00
|
|
|
Variant value;
|
|
|
|
|
|
|
|
if (E.name == CoreStringNames::get_singleton()->_script) {
|
|
|
|
Ref<Script> script = obj->get_script();
|
|
|
|
if (script.is_valid()) {
|
|
|
|
String path = script->get_path();
|
|
|
|
ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://"), ERR_UNAVAILABLE, "Failed to encode a path to a custom script.");
|
|
|
|
value = path;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
value = obj->get(E.name);
|
|
|
|
}
|
|
|
|
|
2017-08-18 15:59:31 +02:00
|
|
|
int len;
|
2023-06-14 12:25:18 +02:00
|
|
|
Error err = encode_variant(value, buf, len, p_full_objects, p_depth + 1);
|
2021-07-30 15:43:01 +02:00
|
|
|
ERR_FAIL_COND_V(err, err);
|
2017-08-18 15:59:31 +02:00
|
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
|
|
r_len += len;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (buf) {
|
2017-08-18 15:59:31 +02:00
|
|
|
buf += len;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2017-08-18 15:59:31 +02:00
|
|
|
}
|
2017-08-14 16:58:10 +02:00
|
|
|
}
|
2019-03-28 09:40:31 +01:00
|
|
|
} else {
|
|
|
|
if (buf) {
|
2020-02-13 20:03:10 +01:00
|
|
|
Object *obj = p_variant.get_validated_object();
|
2020-02-12 18:24:06 +01:00
|
|
|
ObjectID id;
|
2020-02-13 20:03:10 +01:00
|
|
|
if (obj) {
|
2019-03-28 09:40:31 +01:00
|
|
|
id = obj->get_instance_id();
|
|
|
|
}
|
|
|
|
|
|
|
|
encode_uint64(id, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 8;
|
2017-08-14 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2022-06-30 02:15:04 +02:00
|
|
|
case Variant::CALLABLE: {
|
|
|
|
} break;
|
|
|
|
case Variant::SIGNAL: {
|
|
|
|
Signal signal = p_variant;
|
|
|
|
|
|
|
|
_encode_string(signal.get_name(), buf, r_len);
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint64(signal.get_object_id(), buf);
|
|
|
|
}
|
|
|
|
r_len += 8;
|
|
|
|
} break;
|
2014-02-10 02:10:30 +01:00
|
|
|
case Variant::DICTIONARY: {
|
|
|
|
Dictionary d = p_variant;
|
|
|
|
|
|
|
|
if (buf) {
|
2017-01-11 12:53:31 +01:00
|
|
|
encode_uint32(uint32_t(d.size()), buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
}
|
|
|
|
r_len += 4;
|
|
|
|
|
|
|
|
List<Variant> keys;
|
|
|
|
d.get_key_list(&keys);
|
|
|
|
|
2021-07-24 15:46:25 +02:00
|
|
|
for (const Variant &E : keys) {
|
2014-02-10 02:10:30 +01:00
|
|
|
int len;
|
2021-07-30 15:43:01 +02:00
|
|
|
Error err = encode_variant(E, buf, len, p_full_objects, p_depth + 1);
|
|
|
|
ERR_FAIL_COND_V(err, err);
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
|
|
r_len += len;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (buf) {
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += len;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2021-07-16 05:45:57 +02:00
|
|
|
Variant *v = d.getptr(E);
|
2023-09-09 16:11:33 +02:00
|
|
|
ERR_FAIL_NULL_V(v, ERR_BUG);
|
2021-07-30 15:43:01 +02:00
|
|
|
err = encode_variant(*v, buf, len, p_full_objects, p_depth + 1);
|
|
|
|
ERR_FAIL_COND_V(err, err);
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
|
|
r_len += len;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (buf) {
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += len;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
|
|
|
case Variant::ARRAY: {
|
2023-06-14 12:25:18 +02:00
|
|
|
Array array = p_variant;
|
|
|
|
|
|
|
|
if (array.is_typed()) {
|
|
|
|
Variant variant = array.get_typed_script();
|
|
|
|
Ref<Script> script = variant;
|
|
|
|
if (script.is_valid()) {
|
|
|
|
String path = script->get_path();
|
|
|
|
ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://"), ERR_UNAVAILABLE, "Failed to encode a path to a custom script for an array type.");
|
|
|
|
_encode_string(path, buf, r_len);
|
|
|
|
} else if (array.get_typed_class_name() != StringName()) {
|
|
|
|
_encode_string(array.get_typed_class_name(), buf, r_len);
|
|
|
|
} else {
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(array.get_typed_builtin(), buf);
|
|
|
|
buf += 4;
|
|
|
|
}
|
|
|
|
r_len += 4;
|
|
|
|
}
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (buf) {
|
2023-06-14 12:25:18 +02:00
|
|
|
encode_uint32(uint32_t(array.size()), buf);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += 4;
|
|
|
|
}
|
|
|
|
r_len += 4;
|
|
|
|
|
2023-12-24 13:44:21 +01:00
|
|
|
for (const Variant &var : array) {
|
2014-02-10 02:10:30 +01:00
|
|
|
int len;
|
2023-12-24 13:44:21 +01:00
|
|
|
Error err = encode_variant(var, buf, len, p_full_objects, p_depth + 1);
|
2021-07-30 15:43:01 +02:00
|
|
|
ERR_FAIL_COND_V(err, err);
|
2014-02-10 02:10:30 +01:00
|
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (buf) {
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += len;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2023-06-14 12:25:18 +02:00
|
|
|
r_len += len;
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
|
|
|
// arrays
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_BYTE_ARRAY: {
|
|
|
|
Vector<uint8_t> data = p_variant;
|
2014-02-10 02:10:30 +01:00
|
|
|
int datalen = data.size();
|
|
|
|
int datasize = sizeof(uint8_t);
|
2016-03-09 00:00:52 +01:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
if (buf) {
|
|
|
|
encode_uint32(datalen, buf);
|
|
|
|
buf += 4;
|
2020-02-17 22:06:54 +01:00
|
|
|
const uint8_t *r = data.ptr();
|
2023-10-29 17:59:44 +01:00
|
|
|
if (r) {
|
|
|
|
memcpy(buf, &r[0], datalen * datasize);
|
|
|
|
buf += datalen * datasize;
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 + datalen * datasize;
|
2019-05-19 19:09:16 +02:00
|
|
|
while (r_len % 4) {
|
2014-02-10 02:10:30 +01:00
|
|
|
r_len++;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (buf) {
|
2019-05-19 19:09:16 +02:00
|
|
|
*(buf++) = 0;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2019-05-19 19:09:16 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::PACKED_INT32_ARRAY: {
|
|
|
|
Vector<int32_t> data = p_variant;
|
2014-02-10 02:10:30 +01:00
|
|
|
int datalen = data.size();
|
|
|
|
int datasize = sizeof(int32_t);
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(datalen, buf);
|
|
|
|
buf += 4;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
const int32_t *r = data.ptr();
|
2020-05-14 16:41:43 +02:00
|
|
|
for (int32_t i = 0; i < datalen; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
encode_uint32(r[i], &buf[i * datasize]);
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 + datalen * datasize;
|
|
|
|
|
|
|
|
} break;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
case Variant::PACKED_INT64_ARRAY: {
|
|
|
|
Vector<int64_t> data = p_variant;
|
|
|
|
int datalen = data.size();
|
|
|
|
int datasize = sizeof(int64_t);
|
|
|
|
|
|
|
|
if (buf) {
|
2021-08-02 13:34:06 +02:00
|
|
|
encode_uint32(datalen, buf);
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
buf += 4;
|
|
|
|
const int64_t *r = data.ptr();
|
2020-05-14 16:41:43 +02:00
|
|
|
for (int64_t i = 0; i < datalen; i++) {
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
encode_uint64(r[i], &buf[i * datasize]);
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 + datalen * datasize;
|
|
|
|
|
|
|
|
} break;
|
|
|
|
case Variant::PACKED_FLOAT32_ARRAY: {
|
|
|
|
Vector<float> data = p_variant;
|
2014-02-10 02:10:30 +01:00
|
|
|
int datalen = data.size();
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
int datasize = sizeof(float);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(datalen, buf);
|
|
|
|
buf += 4;
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
const float *r = data.ptr();
|
2020-05-14 16:41:43 +02:00
|
|
|
for (int i = 0; i < datalen; i++) {
|
2014-02-10 02:10:30 +01:00
|
|
|
encode_float(r[i], &buf[i * datasize]);
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 + datalen * datasize;
|
|
|
|
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
} break;
|
|
|
|
case Variant::PACKED_FLOAT64_ARRAY: {
|
|
|
|
Vector<double> data = p_variant;
|
|
|
|
int datalen = data.size();
|
|
|
|
int datasize = sizeof(double);
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(datalen, buf);
|
|
|
|
buf += 4;
|
|
|
|
const double *r = data.ptr();
|
2020-05-14 16:41:43 +02:00
|
|
|
for (int i = 0; i < datalen; i++) {
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
encode_double(r[i], &buf[i * datasize]);
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 + datalen * datasize;
|
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_STRING_ARRAY: {
|
|
|
|
Vector<String> data = p_variant;
|
2014-02-10 02:10:30 +01:00
|
|
|
int len = data.size();
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(len, buf);
|
|
|
|
buf += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4;
|
|
|
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
CharString utf8 = data.get(i).utf8();
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(utf8.length() + 1, buf);
|
|
|
|
buf += 4;
|
2021-04-27 16:19:21 +02:00
|
|
|
memcpy(buf, utf8.get_data(), utf8.length() + 1);
|
2014-02-10 02:10:30 +01:00
|
|
|
buf += utf8.length() + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 + utf8.length() + 1;
|
|
|
|
while (r_len % 4) {
|
|
|
|
r_len++; //pad
|
2020-05-14 16:41:43 +02:00
|
|
|
if (buf) {
|
2018-07-08 15:11:41 +02:00
|
|
|
*(buf++) = 0;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-10 10:37:04 +02:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_VECTOR2_ARRAY: {
|
|
|
|
Vector<Vector2> data = p_variant;
|
2013-04-10 10:37:04 +02:00
|
|
|
int len = data.size();
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(len, buf);
|
|
|
|
buf += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4;
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
Vector2 v = data.get(i);
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(v.x, &buf[0]);
|
|
|
|
encode_real(v.y, &buf[sizeof(real_t)]);
|
|
|
|
buf += sizeof(real_t) * 2;
|
2013-04-10 10:37:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += sizeof(real_t) * 2 * len;
|
2013-04-10 10:37:04 +02:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_VECTOR3_ARRAY: {
|
|
|
|
Vector<Vector3> data = p_variant;
|
2014-02-10 02:10:30 +01:00
|
|
|
int len = data.size();
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(len, buf);
|
|
|
|
buf += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4;
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
Vector3 v = data.get(i);
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
encode_real(v.x, &buf[0]);
|
|
|
|
encode_real(v.y, &buf[sizeof(real_t)]);
|
|
|
|
encode_real(v.z, &buf[sizeof(real_t) * 2]);
|
|
|
|
buf += sizeof(real_t) * 3;
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 04:11:41 +01:00
|
|
|
r_len += sizeof(real_t) * 3 * len;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
} break;
|
2020-02-17 22:06:54 +01:00
|
|
|
case Variant::PACKED_COLOR_ARRAY: {
|
|
|
|
Vector<Color> data = p_variant;
|
2014-02-10 02:10:30 +01:00
|
|
|
int len = data.size();
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
encode_uint32(len, buf);
|
|
|
|
buf += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4;
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
Color c = data.get(i);
|
|
|
|
|
|
|
|
encode_float(c.r, &buf[0]);
|
|
|
|
encode_float(c.g, &buf[4]);
|
|
|
|
encode_float(c.b, &buf[8]);
|
|
|
|
encode_float(c.a, &buf[12]);
|
2020-03-17 04:11:41 +01:00
|
|
|
buf += 4 * 4; // Colors should always be in single-precision.
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r_len += 4 * 4 * len;
|
|
|
|
|
|
|
|
} break;
|
2019-04-09 17:08:36 +02:00
|
|
|
default: {
|
|
|
|
ERR_FAIL_V(ERR_BUG);
|
|
|
|
}
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
2022-10-24 22:40:34 +02:00
|
|
|
|
|
|
|
Vector<float> vector3_to_float32_array(const Vector3 *vecs, size_t count) {
|
|
|
|
// We always allocate a new array, and we don't memcpy.
|
|
|
|
// We also don't consider returning a pointer to the passed vectors when sizeof(real_t) == 4.
|
|
|
|
// One reason is that we could decide to put a 4th component in Vector3 for SIMD/mobile performance,
|
|
|
|
// which would cause trouble with these optimizations.
|
|
|
|
Vector<float> floats;
|
|
|
|
if (count == 0) {
|
|
|
|
return floats;
|
|
|
|
}
|
|
|
|
floats.resize(count * 3);
|
|
|
|
float *floats_w = floats.ptrw();
|
|
|
|
for (size_t i = 0; i < count; ++i) {
|
|
|
|
const Vector3 v = vecs[i];
|
|
|
|
floats_w[0] = v.x;
|
|
|
|
floats_w[1] = v.y;
|
|
|
|
floats_w[2] = v.z;
|
|
|
|
floats_w += 3;
|
|
|
|
}
|
|
|
|
return floats;
|
|
|
|
}
|