|
@@ -30,7 +30,10 @@
|
|
|
|
|
|
#include "marshalls.h"
|
|
#include "marshalls.h"
|
|
|
|
|
|
|
|
+#include "core/core_string_names.h"
|
|
|
|
+#include "core/io/resource_loader.h"
|
|
#include "core/object/ref_counted.h"
|
|
#include "core/object/ref_counted.h"
|
|
|
|
+#include "core/object/script_language.h"
|
|
#include "core/os/keyboard.h"
|
|
#include "core/os/keyboard.h"
|
|
#include "core/string/print_string.h"
|
|
#include "core/string/print_string.h"
|
|
|
|
|
|
@@ -55,9 +58,22 @@ ObjectID EncodedObjectAsID::get_object_id() const {
|
|
#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_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)
|
|
#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)
|
|
|
|
|
|
-#define ENCODE_MASK 0xFF
|
|
|
|
-#define ENCODE_FLAG_64 1 << 16
|
|
|
|
-#define ENCODE_FLAG_OBJECT_AS_ID 1 << 16
|
|
|
|
|
|
+// 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)
|
|
|
|
|
|
static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r_string) {
|
|
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);
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
@@ -101,9 +117,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
|
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
|
|
|
|
- uint32_t type = decode_uint32(buf);
|
|
|
|
|
|
+ uint32_t header = decode_uint32(buf);
|
|
|
|
|
|
- ERR_FAIL_COND_V((type & ENCODE_MASK) >= Variant::VARIANT_MAX, ERR_INVALID_DATA);
|
|
|
|
|
|
+ ERR_FAIL_COND_V((header & HEADER_TYPE_MASK) >= Variant::VARIANT_MAX, ERR_INVALID_DATA);
|
|
|
|
|
|
buf += 4;
|
|
buf += 4;
|
|
len -= 4;
|
|
len -= 4;
|
|
@@ -114,7 +130,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
// Note: We cannot use sizeof(real_t) for decoding, in case a different size is encoded.
|
|
// 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.
|
|
// 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.
|
|
// This does lead to some code duplication for decoding, but compatibility is the priority.
|
|
- switch (type & ENCODE_MASK) {
|
|
|
|
|
|
+ switch (header & HEADER_TYPE_MASK) {
|
|
case Variant::NIL: {
|
|
case Variant::NIL: {
|
|
r_variant = Variant();
|
|
r_variant = Variant();
|
|
} break;
|
|
} break;
|
|
@@ -127,7 +143,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
}
|
|
}
|
|
} break;
|
|
} break;
|
|
case Variant::INT: {
|
|
case Variant::INT: {
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
|
|
int64_t val = decode_uint64(buf);
|
|
int64_t val = decode_uint64(buf);
|
|
r_variant = val;
|
|
r_variant = val;
|
|
@@ -146,7 +162,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
|
|
|
|
} break;
|
|
} break;
|
|
case Variant::FLOAT: {
|
|
case Variant::FLOAT: {
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double), ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double), ERR_INVALID_DATA);
|
|
double val = decode_double(buf);
|
|
double val = decode_double(buf);
|
|
r_variant = val;
|
|
r_variant = val;
|
|
@@ -176,7 +192,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
// math types
|
|
// math types
|
|
case Variant::VECTOR2: {
|
|
case Variant::VECTOR2: {
|
|
Vector2 val;
|
|
Vector2 val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 2, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 2, ERR_INVALID_DATA);
|
|
val.x = decode_double(&buf[0]);
|
|
val.x = decode_double(&buf[0]);
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
@@ -210,7 +226,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::RECT2: {
|
|
case Variant::RECT2: {
|
|
Rect2 val;
|
|
Rect2 val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
val.position.x = decode_double(&buf[0]);
|
|
val.position.x = decode_double(&buf[0]);
|
|
val.position.y = decode_double(&buf[sizeof(double)]);
|
|
val.position.y = decode_double(&buf[sizeof(double)]);
|
|
@@ -250,7 +266,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::VECTOR3: {
|
|
case Variant::VECTOR3: {
|
|
Vector3 val;
|
|
Vector3 val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 3, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 3, ERR_INVALID_DATA);
|
|
val.x = decode_double(&buf[0]);
|
|
val.x = decode_double(&buf[0]);
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
@@ -287,7 +303,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::VECTOR4: {
|
|
case Variant::VECTOR4: {
|
|
Vector4 val;
|
|
Vector4 val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
val.x = decode_double(&buf[0]);
|
|
val.x = decode_double(&buf[0]);
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
@@ -327,7 +343,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::TRANSFORM2D: {
|
|
case Variant::TRANSFORM2D: {
|
|
Transform2D val;
|
|
Transform2D val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA);
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int j = 0; j < 2; j++) {
|
|
for (int j = 0; j < 2; j++) {
|
|
@@ -355,7 +371,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::PLANE: {
|
|
case Variant::PLANE: {
|
|
Plane val;
|
|
Plane val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
val.normal.x = decode_double(&buf[0]);
|
|
val.normal.x = decode_double(&buf[0]);
|
|
val.normal.y = decode_double(&buf[sizeof(double)]);
|
|
val.normal.y = decode_double(&buf[sizeof(double)]);
|
|
@@ -381,7 +397,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::QUATERNION: {
|
|
case Variant::QUATERNION: {
|
|
Quaternion val;
|
|
Quaternion val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
|
|
val.x = decode_double(&buf[0]);
|
|
val.x = decode_double(&buf[0]);
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
val.y = decode_double(&buf[sizeof(double)]);
|
|
@@ -407,7 +423,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::AABB: {
|
|
case Variant::AABB: {
|
|
AABB val;
|
|
AABB val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA);
|
|
val.position.x = decode_double(&buf[0]);
|
|
val.position.x = decode_double(&buf[0]);
|
|
val.position.y = decode_double(&buf[sizeof(double)]);
|
|
val.position.y = decode_double(&buf[sizeof(double)]);
|
|
@@ -437,7 +453,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::BASIS: {
|
|
case Variant::BASIS: {
|
|
Basis val;
|
|
Basis val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 9, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 9, ERR_INVALID_DATA);
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
@@ -465,7 +481,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::TRANSFORM3D: {
|
|
case Variant::TRANSFORM3D: {
|
|
Transform3D val;
|
|
Transform3D val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 12, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 12, ERR_INVALID_DATA);
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
@@ -499,7 +515,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
} break;
|
|
} break;
|
|
case Variant::PROJECTION: {
|
|
case Variant::PROJECTION: {
|
|
Projection val;
|
|
Projection val;
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 16, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 16, ERR_INVALID_DATA);
|
|
for (int i = 0; i < 4; i++) {
|
|
for (int i = 0; i < 4; i++) {
|
|
for (int j = 0; j < 4; j++) {
|
|
for (int j = 0; j < 4; j++) {
|
|
@@ -560,12 +576,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
|
|
|
|
uint32_t namecount = strlen &= 0x7FFFFFFF;
|
|
uint32_t namecount = strlen &= 0x7FFFFFFF;
|
|
uint32_t subnamecount = decode_uint32(buf + 4);
|
|
uint32_t subnamecount = decode_uint32(buf + 4);
|
|
- uint32_t flags = decode_uint32(buf + 8);
|
|
|
|
|
|
+ uint32_t np_flags = decode_uint32(buf + 8);
|
|
|
|
|
|
len -= 12;
|
|
len -= 12;
|
|
buf += 12;
|
|
buf += 12;
|
|
|
|
|
|
- if (flags & 2) { // Obsolete format with property separate from subpath
|
|
|
|
|
|
+ if (np_flags & 2) { // Obsolete format with property separate from subpath.
|
|
subnamecount++;
|
|
subnamecount++;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -589,7 +605,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- r_variant = NodePath(names, subnames, flags & 1);
|
|
|
|
|
|
+ r_variant = NodePath(names, subnames, np_flags & 1);
|
|
|
|
|
|
} else {
|
|
} else {
|
|
//old format, just a string
|
|
//old format, just a string
|
|
@@ -608,8 +624,8 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
r_variant = RID::from_uint64(id);
|
|
r_variant = RID::from_uint64(id);
|
|
} break;
|
|
} break;
|
|
case Variant::OBJECT: {
|
|
case Variant::OBJECT: {
|
|
- if (type & ENCODE_FLAG_OBJECT_AS_ID) {
|
|
|
|
- //this _is_ allowed
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_OBJECT_AS_ID) {
|
|
|
|
+ // This _is_ allowed.
|
|
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
|
|
ObjectID val = ObjectID(decode_uint64(buf));
|
|
ObjectID val = ObjectID(decode_uint64(buf));
|
|
if (r_len) {
|
|
if (r_len) {
|
|
@@ -625,7 +641,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
|
|
|
|
r_variant = obj_as_id;
|
|
r_variant = obj_as_id;
|
|
}
|
|
}
|
|
-
|
|
|
|
} else {
|
|
} else {
|
|
ERR_FAIL_COND_V(!p_allow_objects, ERR_UNAUTHORIZED);
|
|
ERR_FAIL_COND_V(!p_allow_objects, ERR_UNAUTHORIZED);
|
|
|
|
|
|
@@ -672,7 +687,16 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
(*r_len) += used;
|
|
(*r_len) += used;
|
|
}
|
|
}
|
|
|
|
|
|
- obj->set(str, value);
|
|
|
|
|
|
+ if (str == "script") {
|
|
|
|
+ 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);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (Object::cast_to<RefCounted>(obj)) {
|
|
if (Object::cast_to<RefCounted>(obj)) {
|
|
@@ -747,7 +771,60 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
|
|
|
|
} break;
|
|
} break;
|
|
case Variant::ARRAY: {
|
|
case Variant::ARRAY: {
|
|
|
|
+ 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.
|
|
|
|
+ }
|
|
|
|
+
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
|
|
+
|
|
int32_t count = decode_uint32(buf);
|
|
int32_t count = decode_uint32(buf);
|
|
// bool shared = count&0x80000000;
|
|
// bool shared = count&0x80000000;
|
|
count &= 0x7FFFFFFF;
|
|
count &= 0x7FFFFFFF;
|
|
@@ -760,6 +837,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
}
|
|
}
|
|
|
|
|
|
Array varr;
|
|
Array varr;
|
|
|
|
+ if (builtin_type != Variant::VARIANT_MAX) {
|
|
|
|
+ varr.set_typed(builtin_type, class_name, script);
|
|
|
|
+ }
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
for (int i = 0; i < count; i++) {
|
|
int used = 0;
|
|
int used = 0;
|
|
@@ -936,7 +1016,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
|
|
|
|
Vector<Vector2> varray;
|
|
Vector<Vector2> varray;
|
|
|
|
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_MUL_OF(count, sizeof(double) * 2, ERR_INVALID_DATA);
|
|
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);
|
|
ERR_FAIL_COND_V(count < 0 || count * sizeof(double) * 2 > (size_t)len, ERR_INVALID_DATA);
|
|
|
|
|
|
@@ -996,7 +1076,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
|
|
|
|
Vector<Vector3> varray;
|
|
Vector<Vector3> varray;
|
|
|
|
|
|
- if (type & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
ERR_FAIL_MUL_OF(count, sizeof(double) * 3, ERR_INVALID_DATA);
|
|
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);
|
|
ERR_FAIL_COND_V(count < 0 || count * sizeof(double) * 3 > (size_t)len, ERR_INVALID_DATA);
|
|
|
|
|
|
@@ -1122,20 +1202,20 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|
|
|
|
|
r_len = 0;
|
|
r_len = 0;
|
|
|
|
|
|
- uint32_t flags = 0;
|
|
|
|
|
|
+ uint32_t header = p_variant.get_type();
|
|
|
|
|
|
switch (p_variant.get_type()) {
|
|
switch (p_variant.get_type()) {
|
|
case Variant::INT: {
|
|
case Variant::INT: {
|
|
int64_t val = p_variant;
|
|
int64_t val = p_variant;
|
|
if (val > (int64_t)INT_MAX || val < (int64_t)INT_MIN) {
|
|
if (val > (int64_t)INT_MAX || val < (int64_t)INT_MIN) {
|
|
- flags |= ENCODE_FLAG_64;
|
|
|
|
|
|
+ header |= HEADER_DATA_FLAG_64;
|
|
}
|
|
}
|
|
} break;
|
|
} break;
|
|
case Variant::FLOAT: {
|
|
case Variant::FLOAT: {
|
|
double d = p_variant;
|
|
double d = p_variant;
|
|
float f = d;
|
|
float f = d;
|
|
if (double(f) != d) {
|
|
if (double(f) != d) {
|
|
- flags |= ENCODE_FLAG_64;
|
|
|
|
|
|
+ header |= HEADER_DATA_FLAG_64;
|
|
}
|
|
}
|
|
} break;
|
|
} break;
|
|
case Variant::OBJECT: {
|
|
case Variant::OBJECT: {
|
|
@@ -1151,7 +1231,23 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|
}
|
|
}
|
|
|
|
|
|
if (!p_full_objects) {
|
|
if (!p_full_objects) {
|
|
- flags |= ENCODE_FLAG_OBJECT_AS_ID;
|
|
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
} break;
|
|
} break;
|
|
#ifdef REAL_T_IS_DOUBLE
|
|
#ifdef REAL_T_IS_DOUBLE
|
|
@@ -1168,7 +1264,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|
case Variant::BASIS:
|
|
case Variant::BASIS:
|
|
case Variant::RECT2:
|
|
case Variant::RECT2:
|
|
case Variant::AABB: {
|
|
case Variant::AABB: {
|
|
- flags |= ENCODE_FLAG_64;
|
|
|
|
|
|
+ header |= HEADER_DATA_FLAG_64;
|
|
} break;
|
|
} break;
|
|
#endif // REAL_T_IS_DOUBLE
|
|
#endif // REAL_T_IS_DOUBLE
|
|
default: {
|
|
default: {
|
|
@@ -1176,7 +1272,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|
}
|
|
}
|
|
|
|
|
|
if (buf) {
|
|
if (buf) {
|
|
- encode_uint32(p_variant.get_type() | flags, buf);
|
|
|
|
|
|
+ encode_uint32(header, buf);
|
|
buf += 4;
|
|
buf += 4;
|
|
}
|
|
}
|
|
r_len += 4;
|
|
r_len += 4;
|
|
@@ -1194,7 +1290,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|
|
|
|
|
} break;
|
|
} break;
|
|
case Variant::INT: {
|
|
case Variant::INT: {
|
|
- if (flags & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
//64 bits
|
|
//64 bits
|
|
if (buf) {
|
|
if (buf) {
|
|
encode_uint64(p_variant.operator int64_t(), buf);
|
|
encode_uint64(p_variant.operator int64_t(), buf);
|
|
@@ -1210,7 +1306,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|
}
|
|
}
|
|
} break;
|
|
} break;
|
|
case Variant::FLOAT: {
|
|
case Variant::FLOAT: {
|
|
- if (flags & ENCODE_FLAG_64) {
|
|
|
|
|
|
+ if (header & HEADER_DATA_FLAG_64) {
|
|
if (buf) {
|
|
if (buf) {
|
|
encode_double(p_variant.operator double(), buf);
|
|
encode_double(p_variant.operator double(), buf);
|
|
}
|
|
}
|
|
@@ -1523,8 +1619,21 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|
|
|
|
|
_encode_string(E.name, buf, r_len);
|
|
_encode_string(E.name, buf, r_len);
|
|
|
|
|
|
|
|
+ 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);
|
|
|
|
+ }
|
|
|
|
+
|
|
int len;
|
|
int len;
|
|
- Error err = encode_variant(obj->get(E.name), buf, len, p_full_objects, p_depth + 1);
|
|
|
|
|
|
+ Error err = encode_variant(value, buf, len, p_full_objects, p_depth + 1);
|
|
ERR_FAIL_COND_V(err, err);
|
|
ERR_FAIL_COND_V(err, err);
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
r_len += len;
|
|
r_len += len;
|
|
@@ -1594,24 +1703,41 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|
|
|
|
|
} break;
|
|
} break;
|
|
case Variant::ARRAY: {
|
|
case Variant::ARRAY: {
|
|
- Array v = p_variant;
|
|
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
if (buf) {
|
|
if (buf) {
|
|
- encode_uint32(uint32_t(v.size()), buf);
|
|
|
|
|
|
+ encode_uint32(uint32_t(array.size()), buf);
|
|
buf += 4;
|
|
buf += 4;
|
|
}
|
|
}
|
|
-
|
|
|
|
r_len += 4;
|
|
r_len += 4;
|
|
|
|
|
|
- for (int i = 0; i < v.size(); i++) {
|
|
|
|
|
|
+ for (int i = 0; i < array.size(); i++) {
|
|
int len;
|
|
int len;
|
|
- Error err = encode_variant(v.get(i), buf, len, p_full_objects, p_depth + 1);
|
|
|
|
|
|
+ Error err = encode_variant(array.get(i), buf, len, p_full_objects, p_depth + 1);
|
|
ERR_FAIL_COND_V(err, err);
|
|
ERR_FAIL_COND_V(err, err);
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
- r_len += len;
|
|
|
|
if (buf) {
|
|
if (buf) {
|
|
buf += len;
|
|
buf += len;
|
|
}
|
|
}
|
|
|
|
+ r_len += len;
|
|
}
|
|
}
|
|
|
|
|
|
} break;
|
|
} break;
|