diff options
Diffstat (limited to 'core/io/json.cpp')
-rw-r--r-- | core/io/json.cpp | 748 |
1 files changed, 747 insertions, 1 deletions
diff --git a/core/io/json.cpp b/core/io/json.cpp index 61051727c1..664ff7857b 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -588,10 +588,756 @@ void JSON::_bind_methods() { ClassDB::bind_method(D_METHOD("get_error_line"), &JSON::get_error_line); ClassDB::bind_method(D_METHOD("get_error_message"), &JSON::get_error_message); + ClassDB::bind_static_method("JSON", D_METHOD("to_native", "json", "allow_classes", "allow_scripts"), &JSON::to_native, DEFVAL(false), DEFVAL(false)); + ClassDB::bind_static_method("JSON", D_METHOD("from_native", "variant", "allow_classes", "allow_scripts"), &JSON::from_native, DEFVAL(false), DEFVAL(false)); + ADD_PROPERTY(PropertyInfo(Variant::NIL, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), "set_data", "get_data"); // Ensures that it can be serialized as binary. } -//// +#define GDTYPE "__gdtype" +#define VALUES "values" +#define PASS_ARG p_allow_classes, p_allow_scripts + +Variant JSON::from_native(const Variant &p_variant, bool p_allow_classes, bool p_allow_scripts) { + switch (p_variant.get_type()) { + case Variant::NIL: { + Dictionary nil; + nil[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return nil; + } break; + case Variant::BOOL: { + return p_variant; + } break; + case Variant::INT: { + return p_variant; + } break; + case Variant::FLOAT: { + return p_variant; + } break; + case Variant::STRING: { + return p_variant; + } break; + case Variant::VECTOR2: { + Dictionary d; + Vector2 v = p_variant; + Array values; + values.push_back(v.x); + values.push_back(v.y); + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::VECTOR2I: { + Dictionary d; + Vector2i v = p_variant; + Array values; + values.push_back(v.x); + values.push_back(v.y); + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::RECT2: { + Dictionary d; + Rect2 r = p_variant; + d["position"] = from_native(r.position); + d["size"] = from_native(r.size); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::RECT2I: { + Dictionary d; + Rect2i r = p_variant; + d["position"] = from_native(r.position); + d["size"] = from_native(r.size); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::VECTOR3: { + Dictionary d; + Vector3 v = p_variant; + Array values; + values.push_back(v.x); + values.push_back(v.y); + values.push_back(v.z); + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::VECTOR3I: { + Dictionary d; + Vector3i v = p_variant; + Array values; + values.push_back(v.x); + values.push_back(v.y); + values.push_back(v.z); + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::TRANSFORM2D: { + Dictionary d; + Transform2D t = p_variant; + d["x"] = from_native(t[0]); + d["y"] = from_native(t[1]); + d["origin"] = from_native(t[2]); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::VECTOR4: { + Dictionary d; + Vector4 v = p_variant; + Array values; + values.push_back(v.x); + values.push_back(v.y); + values.push_back(v.z); + values.push_back(v.w); + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::VECTOR4I: { + Dictionary d; + Vector4i v = p_variant; + Array values; + values.push_back(v.x); + values.push_back(v.y); + values.push_back(v.z); + values.push_back(v.w); + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PLANE: { + Dictionary d; + Plane p = p_variant; + d["normal"] = from_native(p.normal); + d["d"] = p.d; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::QUATERNION: { + Dictionary d; + Quaternion q = p_variant; + Array values; + values.push_back(q.x); + values.push_back(q.y); + values.push_back(q.z); + values.push_back(q.w); + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::AABB: { + Dictionary d; + AABB aabb = p_variant; + d["position"] = from_native(aabb.position); + d["size"] = from_native(aabb.size); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::BASIS: { + Dictionary d; + Basis t = p_variant; + d["x"] = from_native(t.get_column(0)); + d["y"] = from_native(t.get_column(1)); + d["z"] = from_native(t.get_column(2)); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::TRANSFORM3D: { + Dictionary d; + Transform3D t = p_variant; + d["basis"] = from_native(t.basis); + d["origin"] = from_native(t.origin); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PROJECTION: { + Dictionary d; + Projection t = p_variant; + d["x"] = from_native(t[0]); + d["y"] = from_native(t[1]); + d["z"] = from_native(t[2]); + d["w"] = from_native(t[3]); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::COLOR: { + Dictionary d; + Color c = p_variant; + Array values; + values.push_back(c.r); + values.push_back(c.g); + values.push_back(c.b); + values.push_back(c.a); + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::STRING_NAME: { + Dictionary d; + d["name"] = String(p_variant); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::NODE_PATH: { + Dictionary d; + d["path"] = String(p_variant); + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::RID: { + Dictionary d; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::OBJECT: { + Object *obj = p_variant.get_validated_object(); + + if (p_allow_classes && obj) { + Dictionary d; + List<PropertyInfo> property_list; + obj->get_property_list(&property_list); + + d["type"] = obj->get_class(); + Dictionary p; + for (const PropertyInfo &P : property_list) { + if (P.usage & PROPERTY_USAGE_STORAGE) { + if (P.name == "script" && !p_allow_scripts) { + continue; + } + p[P.name] = from_native(obj->get(P.name), PASS_ARG); + } + } + d["properties"] = p; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } else { + Dictionary nil; + nil[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return nil; + } + } break; + case Variant::CALLABLE: + case Variant::SIGNAL: { + Dictionary nil; + nil[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return nil; + } break; + case Variant::DICTIONARY: { + Dictionary d = p_variant; + List<Variant> keys; + d.get_key_list(&keys); + bool all_strings = true; + for (const Variant &K : keys) { + if (K.get_type() != Variant::STRING) { + all_strings = false; + break; + } + } + + if (all_strings) { + Dictionary ret_dict; + for (const Variant &K : keys) { + ret_dict[K] = from_native(d[K], PASS_ARG); + } + return ret_dict; + } else { + Dictionary ret; + Array pairs; + for (const Variant &K : keys) { + Dictionary pair; + pair["key"] = from_native(K, PASS_ARG); + pair["value"] = from_native(d[K], PASS_ARG); + pairs.push_back(pair); + } + ret["pairs"] = pairs; + ret[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return ret; + } + } break; + case Variant::ARRAY: { + Array arr = p_variant; + Array ret; + for (int i = 0; i < arr.size(); i++) { + ret.push_back(from_native(arr[i], PASS_ARG)); + } + return ret; + } break; + case Variant::PACKED_BYTE_ARRAY: { + Dictionary d; + PackedByteArray arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + values.push_back(arr[i]); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PACKED_INT32_ARRAY: { + Dictionary d; + PackedInt32Array arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + values.push_back(arr[i]); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + + } break; + case Variant::PACKED_INT64_ARRAY: { + Dictionary d; + PackedInt64Array arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + values.push_back(arr[i]); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PACKED_FLOAT32_ARRAY: { + Dictionary d; + PackedFloat32Array arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + values.push_back(arr[i]); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PACKED_FLOAT64_ARRAY: { + Dictionary d; + PackedFloat64Array arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + values.push_back(arr[i]); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PACKED_STRING_ARRAY: { + Dictionary d; + PackedStringArray arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + values.push_back(arr[i]); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PACKED_VECTOR2_ARRAY: { + Dictionary d; + PackedVector2Array arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + Vector2 v = arr[i]; + values.push_back(v.x); + values.push_back(v.y); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PACKED_VECTOR3_ARRAY: { + Dictionary d; + PackedVector3Array arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + Vector3 v = arr[i]; + values.push_back(v.x); + values.push_back(v.y); + values.push_back(v.z); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PACKED_COLOR_ARRAY: { + Dictionary d; + PackedColorArray arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + Color v = arr[i]; + values.push_back(v.r); + values.push_back(v.g); + values.push_back(v.b); + values.push_back(v.a); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + case Variant::PACKED_VECTOR4_ARRAY: { + Dictionary d; + PackedVector4Array arr = p_variant; + Array values; + for (int i = 0; i < arr.size(); i++) { + Vector4 v = arr[i]; + values.push_back(v.x); + values.push_back(v.y); + values.push_back(v.z); + values.push_back(v.w); + } + d[VALUES] = values; + d[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return d; + } break; + default: { + ERR_PRINT(vformat("Unhandled conversion from native Variant type '%s' to JSON.", Variant::get_type_name(p_variant.get_type()))); + } break; + } + + Dictionary nil; + nil[GDTYPE] = Variant::get_type_name(p_variant.get_type()); + return nil; +} + +Variant JSON::to_native(const Variant &p_json, bool p_allow_classes, bool p_allow_scripts) { + switch (p_json.get_type()) { + case Variant::BOOL: { + return p_json; + } break; + case Variant::INT: { + return p_json; + } break; + case Variant::FLOAT: { + return p_json; + } break; + case Variant::STRING: { + return p_json; + } break; + case Variant::STRING_NAME: { + return p_json; + } break; + case Variant::CALLABLE: { + return p_json; + } break; + case Variant::DICTIONARY: { + Dictionary d = p_json; + if (d.has(GDTYPE)) { + // Specific Godot Variant types serialized to JSON. + String type = d[GDTYPE]; + if (type == Variant::get_type_name(Variant::VECTOR2)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() != 2, Variant()); + Vector2 v; + v.x = values[0]; + v.y = values[1]; + return v; + } else if (type == Variant::get_type_name(Variant::VECTOR2I)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() != 2, Variant()); + Vector2i v; + v.x = values[0]; + v.y = values[1]; + return v; + } else if (type == Variant::get_type_name(Variant::RECT2)) { + ERR_FAIL_COND_V(!d.has("position"), Variant()); + ERR_FAIL_COND_V(!d.has("size"), Variant()); + Rect2 r; + r.position = to_native(d["position"]); + r.size = to_native(d["size"]); + return r; + } else if (type == Variant::get_type_name(Variant::RECT2I)) { + ERR_FAIL_COND_V(!d.has("position"), Variant()); + ERR_FAIL_COND_V(!d.has("size"), Variant()); + Rect2i r; + r.position = to_native(d["position"]); + r.size = to_native(d["size"]); + return r; + } else if (type == Variant::get_type_name(Variant::VECTOR3)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() != 3, Variant()); + Vector3 v; + v.x = values[0]; + v.y = values[1]; + v.z = values[2]; + return v; + } else if (type == Variant::get_type_name(Variant::VECTOR3I)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() != 3, Variant()); + Vector3i v; + v.x = values[0]; + v.y = values[1]; + v.z = values[2]; + return v; + } else if (type == Variant::get_type_name(Variant::TRANSFORM2D)) { + ERR_FAIL_COND_V(!d.has("x"), Variant()); + ERR_FAIL_COND_V(!d.has("y"), Variant()); + ERR_FAIL_COND_V(!d.has("origin"), Variant()); + Transform2D t; + t[0] = to_native(d["x"]); + t[1] = to_native(d["y"]); + t[2] = to_native(d["origin"]); + return t; + } else if (type == Variant::get_type_name(Variant::VECTOR4)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() != 4, Variant()); + Vector4 v; + v.x = values[0]; + v.y = values[1]; + v.z = values[2]; + v.w = values[3]; + return v; + } else if (type == Variant::get_type_name(Variant::VECTOR4I)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() != 4, Variant()); + Vector4i v; + v.x = values[0]; + v.y = values[1]; + v.z = values[2]; + v.w = values[3]; + return v; + } else if (type == Variant::get_type_name(Variant::PLANE)) { + ERR_FAIL_COND_V(!d.has("normal"), Variant()); + ERR_FAIL_COND_V(!d.has("d"), Variant()); + Plane p; + p.normal = to_native(d["normal"]); + p.d = d["d"]; + return p; + } else if (type == Variant::get_type_name(Variant::QUATERNION)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() != 4, Variant()); + Quaternion v; + v.x = values[0]; + v.y = values[1]; + v.z = values[2]; + v.w = values[3]; + return v; + } else if (type == Variant::get_type_name(Variant::AABB)) { + ERR_FAIL_COND_V(!d.has("position"), Variant()); + ERR_FAIL_COND_V(!d.has("size"), Variant()); + AABB r; + r.position = to_native(d["position"]); + r.size = to_native(d["size"]); + return r; + } else if (type == Variant::get_type_name(Variant::BASIS)) { + ERR_FAIL_COND_V(!d.has("x"), Variant()); + ERR_FAIL_COND_V(!d.has("y"), Variant()); + ERR_FAIL_COND_V(!d.has("z"), Variant()); + Basis b; + b.set_column(0, to_native(d["x"])); + b.set_column(1, to_native(d["y"])); + b.set_column(2, to_native(d["z"])); + return b; + } else if (type == Variant::get_type_name(Variant::TRANSFORM3D)) { + ERR_FAIL_COND_V(!d.has("basis"), Variant()); + ERR_FAIL_COND_V(!d.has("origin"), Variant()); + Transform3D t; + t.basis = to_native(d["basis"]); + t.origin = to_native(d["origin"]); + return t; + } else if (type == Variant::get_type_name(Variant::PROJECTION)) { + ERR_FAIL_COND_V(!d.has("x"), Variant()); + ERR_FAIL_COND_V(!d.has("y"), Variant()); + ERR_FAIL_COND_V(!d.has("z"), Variant()); + ERR_FAIL_COND_V(!d.has("w"), Variant()); + Projection p; + p[0] = to_native(d["x"]); + p[1] = to_native(d["y"]); + p[2] = to_native(d["z"]); + p[3] = to_native(d["w"]); + return p; + } else if (type == Variant::get_type_name(Variant::COLOR)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() != 4, Variant()); + Color c; + c.r = values[0]; + c.g = values[1]; + c.b = values[2]; + c.a = values[3]; + return c; + } else if (type == Variant::get_type_name(Variant::NODE_PATH)) { + ERR_FAIL_COND_V(!d.has("path"), Variant()); + NodePath np = d["path"]; + return np; + } else if (type == Variant::get_type_name(Variant::STRING_NAME)) { + ERR_FAIL_COND_V(!d.has("name"), Variant()); + StringName s = d["name"]; + return s; + } else if (type == Variant::get_type_name(Variant::OBJECT)) { + ERR_FAIL_COND_V(!d.has("type"), Variant()); + ERR_FAIL_COND_V(!d.has("properties"), Variant()); + + ERR_FAIL_COND_V(!p_allow_classes, Variant()); + + String obj_type = d["type"]; + bool is_script = obj_type == "Script" || ClassDB::is_parent_class(obj_type, "Script"); + ERR_FAIL_COND_V(!p_allow_scripts && is_script, Variant()); + Object *obj = ClassDB::instantiate(obj_type); + ERR_FAIL_NULL_V(obj, Variant()); + + Dictionary p = d["properties"]; + + List<Variant> keys; + p.get_key_list(&keys); + + for (const Variant &K : keys) { + String property = K; + Variant value = to_native(p[K], PASS_ARG); + obj->set(property, value); + } + + Variant v(obj); + + return v; + } else if (type == Variant::get_type_name(Variant::DICTIONARY)) { + ERR_FAIL_COND_V(!d.has("pairs"), Variant()); + Array pairs = d["pairs"]; + Dictionary r; + for (int i = 0; i < pairs.size(); i++) { + Dictionary p = pairs[i]; + ERR_CONTINUE(!p.has("key")); + ERR_CONTINUE(!p.has("value")); + r[to_native(p["key"], PASS_ARG)] = to_native(p["value"]); + } + return r; + } else if (type == Variant::get_type_name(Variant::ARRAY)) { + ERR_PRINT(vformat("Unexpected Array with '%s' key. Arrays are supported natively.", GDTYPE)); + } else if (type == Variant::get_type_name(Variant::PACKED_BYTE_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + PackedByteArray pbarr; + pbarr.resize(values.size()); + for (int i = 0; i < pbarr.size(); i++) { + pbarr.write[i] = values[i]; + } + return pbarr; + } else if (type == Variant::get_type_name(Variant::PACKED_INT32_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + PackedInt32Array arr; + arr.resize(values.size()); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = values[i]; + } + return arr; + } else if (type == Variant::get_type_name(Variant::PACKED_INT64_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + PackedInt64Array arr; + arr.resize(values.size()); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = values[i]; + } + return arr; + } else if (type == Variant::get_type_name(Variant::PACKED_FLOAT32_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + PackedFloat32Array arr; + arr.resize(values.size()); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = values[i]; + } + return arr; + } else if (type == Variant::get_type_name(Variant::PACKED_FLOAT64_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + PackedFloat64Array arr; + arr.resize(values.size()); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = values[i]; + } + return arr; + } else if (type == Variant::get_type_name(Variant::PACKED_STRING_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + PackedStringArray arr; + arr.resize(values.size()); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = values[i]; + } + return arr; + } else if (type == Variant::get_type_name(Variant::PACKED_VECTOR2_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() % 2 != 0, Variant()); + PackedVector2Array arr; + arr.resize(values.size() / 2); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = Vector2(values[i * 2 + 0], values[i * 2 + 1]); + } + return arr; + } else if (type == Variant::get_type_name(Variant::PACKED_VECTOR3_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() % 3 != 0, Variant()); + PackedVector3Array arr; + arr.resize(values.size() / 3); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = Vector3(values[i * 3 + 0], values[i * 3 + 1], values[i * 3 + 2]); + } + return arr; + } else if (type == Variant::get_type_name(Variant::PACKED_COLOR_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() % 4 != 0, Variant()); + PackedColorArray arr; + arr.resize(values.size() / 4); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = Color(values[i * 4 + 0], values[i * 4 + 1], values[i * 4 + 2], values[i * 4 + 3]); + } + return arr; + } else if (type == Variant::get_type_name(Variant::PACKED_VECTOR4_ARRAY)) { + ERR_FAIL_COND_V(!d.has(VALUES), Variant()); + Array values = d[VALUES]; + ERR_FAIL_COND_V(values.size() % 4 != 0, Variant()); + PackedVector4Array arr; + arr.resize(values.size() / 4); + for (int i = 0; i < arr.size(); i++) { + arr.write[i] = Vector4(values[i * 4 + 0], values[i * 4 + 1], values[i * 4 + 2], values[i * 4 + 3]); + } + return arr; + } else { + return Variant(); + } + } else { + // Regular dictionary with string keys. + List<Variant> keys; + d.get_key_list(&keys); + Dictionary r; + for (const Variant &K : keys) { + r[K] = to_native(d[K], PASS_ARG); + } + return r; + } + } break; + case Variant::ARRAY: { + Array arr = p_json; + Array ret; + ret.resize(arr.size()); + for (int i = 0; i < arr.size(); i++) { + ret[i] = to_native(arr[i], PASS_ARG); + } + return ret; + } break; + default: { + ERR_PRINT(vformat("Unhandled conversion from JSON type '%s' to native Variant type.", Variant::get_type_name(p_json.get_type()))); + return Variant(); + } + } + + return Variant(); +} + +#undef GDTYPE +#undef VALUES +#undef PASS_ARG //////////// |