|
@@ -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
|
|
|
|
|
|
////////////
|
|
|
|