瀏覽代碼

Refactored variant constructor logic

reduz 4 年之前
父節點
當前提交
221a2a1742
共有 33 個文件被更改,包括 1369 次插入571 次删除
  1. 2 2
      core/math/expression.cpp
  2. 6 0
      core/math/transform_2d.h
  3. 2 1
      core/object/object.cpp
  4. 4 12
      core/register_core_types.cpp
  5. 1 1
      core/variant/array.cpp
  6. 14 3
      core/variant/variant.cpp
  7. 77 6
      core/variant/variant.h
  8. 26 474
      core/variant/variant_call.cpp
  9. 781 0
      core/variant/variant_construct.cpp
  10. 297 0
      core/variant/variant_internal.h
  11. 64 9
      core/variant/variant_op.cpp
  12. 2 2
      core/variant/variant_setget.cpp
  13. 6 5
      editor/animation_track_editor.cpp
  14. 4 3
      editor/array_property_edit.cpp
  15. 2 1
      editor/doc_data.cpp
  16. 1 1
      editor/editor_inspector.cpp
  17. 12 8
      editor/editor_properties_array_dict.cpp
  18. 2 1
      editor/project_settings_editor.cpp
  19. 2 2
      editor/property_selector.cpp
  20. 2 1
      modules/gdscript/gdscript.cpp
  21. 8 5
      modules/gdscript/gdscript_analyzer.cpp
  22. 17 8
      modules/gdscript/gdscript_editor.cpp
  23. 5 4
      modules/gdscript/gdscript_function.cpp
  24. 1 1
      modules/gdscript/gdscript_functions.cpp
  25. 6 2
      modules/gdscript/gdscript_parser.cpp
  26. 2 2
      modules/visual_script/visual_script.cpp
  27. 1 1
      modules/visual_script/visual_script_builtin_funcs.cpp
  28. 7 4
      modules/visual_script/visual_script_editor.cpp
  29. 1 1
      modules/visual_script/visual_script_expression.cpp
  30. 9 6
      modules/visual_script/visual_script_func_nodes.cpp
  31. 3 3
      modules/visual_script/visual_script_nodes.cpp
  32. 1 1
      modules/visual_script/visual_script_property_selector.cpp
  33. 1 1
      scene/main/shader_globals_override.cpp

+ 2 - 2
core/math/expression.cpp

@@ -564,7 +564,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant
 				return;
 
 			} else {
-				*r_return = Variant::construct(Variant::Type(type), p_inputs, 1, r_error);
+				Variant::construct(Variant::Type(type), *r_return, p_inputs, 1, r_error);
 			}
 		} break;
 		case TYPE_OF: {
@@ -2021,7 +2021,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
 			}
 
 			Callable::CallError ce;
-			r_ret = Variant::construct(constructor->data_type, (const Variant **)argp.ptr(), argp.size(), ce);
+			Variant::construct(constructor->data_type, r_ret, (const Variant **)argp.ptr(), argp.size(), ce);
 
 			if (ce.error != Callable::CallError::CALL_OK) {
 				r_error_str = vformat(RTR("Invalid arguments to construct '%s'"), Variant::get_type_name(constructor->data_type));

+ 6 - 0
core/math/transform_2d.h

@@ -128,6 +128,12 @@ struct Transform2D {
 		elements[2][1] = oy;
 	}
 
+	Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) {
+		elements[0] = p_x;
+		elements[1] = p_y;
+		elements[2] = p_origin;
+	}
+
 	Transform2D(real_t p_rot, const Vector2 &p_pos);
 	Transform2D() {
 		elements[0][0] = 1.0;

+ 2 - 1
core/object/object.cpp

@@ -1690,7 +1690,8 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName>
 	}
 
 	Callable::CallError ce;
-	Variant check = Variant::construct(t, nullptr, 0, ce);
+	Variant check;
+	Variant::construct(t, check, nullptr, 0, ce);
 
 	for (int i = 1; i < p_path.size(); i++) {
 		if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) {

+ 4 - 12
core/register_core_types.cpp

@@ -96,12 +96,6 @@ extern Mutex _global_mutex;
 
 extern void register_global_constants();
 extern void unregister_global_constants();
-extern void register_variant_methods();
-extern void unregister_variant_methods();
-extern void register_variant_operators();
-extern void unregister_variant_operators();
-extern void register_variant_setters_getters();
-extern void unregister_variant_setters_getters();
 
 void register_core_types() {
 	//consistency check
@@ -114,9 +108,8 @@ void register_core_types() {
 	ResourceLoader::initialize();
 
 	register_global_constants();
-	register_variant_methods();
-	register_variant_operators();
-	register_variant_setters_getters();
+
+	Variant::register_types();
 
 	CoreStringNames::create();
 
@@ -323,9 +316,8 @@ void unregister_core_types() {
 	ClassDB::cleanup_defaults();
 	ObjectDB::cleanup();
 
-	unregister_variant_setters_getters();
-	unregister_variant_operators();
-	unregister_variant_methods();
+	Variant::unregister_types();
+
 	unregister_global_constants();
 
 	ClassDB::cleanup();

+ 1 - 1
core/variant/array.cpp

@@ -165,7 +165,7 @@ void Array::_assign(const Array &p_array) {
 				} else if (Variant::can_convert_strict(src_val.get_type(), _p->typed.type)) {
 					Variant *ptr = &src_val;
 					Callable::CallError ce;
-					new_array.write[i] = Variant::construct(_p->typed.type, (const Variant **)&ptr, 1, ce, true);
+					Variant::construct(_p->typed.type, new_array.write[i], (const Variant **)&ptr, 1, ce);
 					if (ce.error != Callable::CallError::CALL_OK) {
 						ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'.");
 					}

+ 14 - 3
core/variant/variant.cpp

@@ -1266,7 +1266,7 @@ void Variant::zero() {
 	}
 }
 
-void Variant::clear() {
+void Variant::_clear_internal() {
 	switch (type) {
 		case STRING: {
 			reinterpret_cast<String *>(_data._mem)->~String();
@@ -1358,8 +1358,6 @@ void Variant::clear() {
 		default: {
 		} /* not needed */
 	}
-
-	type = NIL;
 }
 
 Variant::operator signed int() const {
@@ -3519,3 +3517,16 @@ String vformat(const String &p_text, const Variant &p1, const Variant &p2, const
 
 	return fmt;
 }
+
+void Variant::register_types() {
+	_register_variant_operators();
+	_register_variant_methods();
+	_register_variant_setters_getters();
+	_register_variant_constructors();
+}
+void Variant::unregister_types() {
+	_unregister_variant_operators();
+	_unregister_variant_methods();
+	_unregister_variant_setters_getters();
+	_unregister_variant_constructors();
+}

+ 77 - 6
core/variant/variant.h

@@ -207,7 +207,66 @@ private:
 	} _data alignas(8);
 
 	void reference(const Variant &p_variant);
-	void clear();
+
+	void _clear_internal();
+
+	_FORCE_INLINE_ void clear() {
+		static const bool needs_deinit[Variant::VARIANT_MAX] = {
+			false, //NIL,
+			false, //BOOL,
+			false, //INT,
+			false, //FLOAT,
+			true, //STRING,
+			false, //VECTOR2,
+			false, //VECTOR2I,
+			false, //RECT2,
+			false, //RECT2I,
+			false, //VECTOR3,
+			false, //VECTOR3I,
+			true, //TRANSFORM2D,
+			false, //PLANE,
+			false, //QUAT,
+			true, //AABB,
+			true, //BASIS,
+			true, //TRANSFORM,
+
+			// misc types
+			false, //COLOR,
+			true, //STRING_NAME,
+			true, //NODE_PATH,
+			false, //_RID,
+			true, //OBJECT,
+			true, //CALLABLE,
+			true, //SIGNAL,
+			true, //DICTIONARY,
+			true, //ARRAY,
+
+			// typed arrays
+			true, //PACKED_BYTE_ARRAY,
+			true, //PACKED_INT32_ARRAY,
+			true, //PACKED_INT64_ARRAY,
+			true, //PACKED_FLOAT32_ARRAY,
+			true, //PACKED_FLOAT64_ARRAY,
+			true, //PACKED_STRING_ARRAY,
+			true, //PACKED_VECTOR2_ARRAY,
+			true, //PACKED_VECTOR3_ARRAY,
+			true, //PACKED_COLOR_ARRAY,
+		};
+
+		if (unlikely(needs_deinit[type])) { //make it fast for types that dont need deinit
+			_clear_internal();
+		}
+		type = NIL;
+	}
+
+	static void _register_variant_operators();
+	static void _unregister_variant_operators();
+	static void _register_variant_methods();
+	static void _unregister_variant_methods();
+	static void _register_variant_setters_getters();
+	static void _unregister_variant_setters_getters();
+	static void _register_variant_constructors();
+	static void _unregister_variant_constructors();
 
 public:
 	_FORCE_INLINE_ Type get_type() const {
@@ -467,7 +526,19 @@ public:
 	static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
 	static String get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
 
-	static Variant construct(const Variant::Type, const Variant **p_args, int p_argcount, Callable::CallError &r_error, bool p_strict = true);
+	// constructor
+	typedef void (*ValidatedConstructor)(Variant &r_base, const Variant **p_args);
+	typedef void (*PTRConstructor)(void *base, const void **p_args);
+
+	static int get_constructor_count(Variant::Type p_type);
+	static ValidatedConstructor get_validated_constructor(Variant::Type p_type, int p_constructor);
+	static PTRConstructor get_ptr_constructor(Variant::Type p_type, int p_constructor);
+	static int get_constructor_argument_count(Variant::Type p_type, int p_constructor);
+	static Variant::Type get_constructor_argument_type(Variant::Type p_type, int p_constructor, int p_argument);
+	static String get_constructor_argument_name(Variant::Type p_type, int p_constructor, int p_argument);
+	static void construct(Variant::Type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+
+	static void get_constructor_list(Type p_type, List<MethodInfo> *r_list); //convenience
 
 	void get_method_list(List<MethodInfo> *p_list) const;
 	bool has_method(const StringName &p_method) const;
@@ -560,7 +631,6 @@ public:
 	String stringify(List<const void *> &stack) const;
 
 	void static_assign(const Variant &p_variant);
-	static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
 	static void get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants);
 	static bool has_constant(Variant::Type p_type, const StringName &p_value);
 	static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr);
@@ -573,12 +643,13 @@ public:
 
 	void operator=(const Variant &p_variant); // only this is enough for all the other types
 
+	static void register_types();
+	static void unregister_types();
+
 	Variant(const Variant &p_variant);
 	_FORCE_INLINE_ Variant() {}
 	_FORCE_INLINE_ ~Variant() {
-		if (type != Variant::NIL) {
-			clear();
-		}
+		clear();
 	}
 };
 

+ 26 - 474
core/variant/variant_call.cpp

@@ -61,6 +61,27 @@ _FORCE_INLINE_ Vector<String> sarray(P... p_args) {
 typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
 typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
 
+template <class T>
+struct TypeAdjust {
+	_FORCE_INLINE_ static void adjust(Variant *r_ret) {
+		VariantTypeChanger<typename GetSimpleTypeT<T>::type_t>::change(r_ret);
+	}
+};
+
+template <> //do nothing for variant
+struct TypeAdjust<Variant> {
+	_FORCE_INLINE_ static void adjust(Variant *r_ret) {
+	}
+};
+
+template <> //do nothing for variant
+struct TypeAdjust<Object *> {
+	_FORCE_INLINE_ static void adjust(Variant *r_ret) {
+		VariantInternal::clear(r_ret);
+		*r_ret = (Object *)nullptr;
+	}
+};
+
 struct _VariantCall {
 	template <class T, class... P>
 	class InternalMethod : public Variant::InternalMethod {
@@ -166,6 +187,7 @@ struct _VariantCall {
 		}
 
 		virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) {
+			TypeAdjust<R>::adjust(r_ret);
 			call_with_validated_variant_args_ret(base, method, p_args, r_ret);
 		}
 #ifdef PTRCALL_ENABLED
@@ -231,6 +253,7 @@ struct _VariantCall {
 		}
 
 		virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) {
+			TypeAdjust<R>::adjust(r_ret);
 			call_with_validated_variant_args_retc(base, method, p_args, r_ret);
 		}
 #ifdef PTRCALL_ENABLED
@@ -333,6 +356,7 @@ struct _VariantCall {
 		}
 
 		virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) {
+			TypeAdjust<R>::adjust(r_ret);
 			call_with_validated_variant_args_static_retc(base, method, p_args, r_ret);
 		}
 #ifdef PTRCALL_ENABLED
@@ -670,190 +694,6 @@ struct _VariantCall {
 		signal->emit(p_args, p_argcount);
 	}
 
-	struct ConstructData {
-		int arg_count;
-		Vector<Variant::Type> arg_types;
-		Vector<String> arg_names;
-		VariantConstructFunc func;
-	};
-
-	struct ConstructFunc {
-		List<ConstructData> constructors;
-	};
-
-	static ConstructFunc *construct_funcs;
-
-	static void Vector2_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Vector2(*p_args[0], *p_args[1]);
-	}
-
-	static void Vector2i_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Vector2i(*p_args[0], *p_args[1]);
-	}
-
-	static void Rect2_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Rect2(*p_args[0], *p_args[1]);
-	}
-
-	static void Rect2_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Rect2(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
-	}
-
-	static void Rect2i_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Rect2i(*p_args[0], *p_args[1]);
-	}
-
-	static void Rect2i_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Rect2i(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
-	}
-
-	static void Transform2D_init2(Variant &r_ret, const Variant **p_args) {
-		Transform2D m(*p_args[0], *p_args[1]);
-		r_ret = m;
-	}
-
-	static void Transform2D_init3(Variant &r_ret, const Variant **p_args) {
-		Transform2D m;
-		m[0] = *p_args[0];
-		m[1] = *p_args[1];
-		m[2] = *p_args[2];
-		r_ret = m;
-	}
-
-	static void Vector3_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Vector3(*p_args[0], *p_args[1], *p_args[2]);
-	}
-
-	static void Vector3i_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Vector3i(*p_args[0], *p_args[1], *p_args[2]);
-	}
-
-	static void Plane_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Plane(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
-	}
-
-	static void Plane_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Plane(*p_args[0], *p_args[1], *p_args[2]);
-	}
-
-	static void Plane_init3(Variant &r_ret, const Variant **p_args) {
-		r_ret = Plane(p_args[0]->operator Vector3(), p_args[1]->operator real_t());
-	}
-	static void Plane_init4(Variant &r_ret, const Variant **p_args) {
-		r_ret = Plane(p_args[0]->operator Vector3(), p_args[1]->operator Vector3());
-	}
-
-	static void Quat_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Quat(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
-	}
-
-	static void Quat_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Quat(((Vector3)(*p_args[0])), ((real_t)(*p_args[1])));
-	}
-
-	static void Quat_init3(Variant &r_ret, const Variant **p_args) {
-		r_ret = Quat(((Vector3)(*p_args[0])));
-	}
-
-	static void Color_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = Color(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
-	}
-
-	static void Color_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Color(*p_args[0], *p_args[1], *p_args[2]);
-	}
-
-	static void Color_init3(Variant &r_ret, const Variant **p_args) {
-		r_ret = Color::html(*p_args[0]);
-	}
-
-	static void Color_init4(Variant &r_ret, const Variant **p_args) {
-		r_ret = Color::hex(*p_args[0]);
-	}
-
-	static void Color_init5(Variant &r_ret, const Variant **p_args) {
-		r_ret = Color(((Color)(*p_args[0])), *p_args[1]);
-	}
-
-	static void AABB_init1(Variant &r_ret, const Variant **p_args) {
-		r_ret = ::AABB(*p_args[0], *p_args[1]);
-	}
-
-	static void Basis_init1(Variant &r_ret, const Variant **p_args) {
-		Basis m;
-		m.set_axis(0, *p_args[0]);
-		m.set_axis(1, *p_args[1]);
-		m.set_axis(2, *p_args[2]);
-		r_ret = m;
-	}
-
-	static void Basis_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Basis(p_args[0]->operator Vector3(), p_args[1]->operator real_t());
-	}
-
-	static void Transform_init1(Variant &r_ret, const Variant **p_args) {
-		Transform t;
-		t.basis.set_axis(0, *p_args[0]);
-		t.basis.set_axis(1, *p_args[1]);
-		t.basis.set_axis(2, *p_args[2]);
-		t.origin = *p_args[3];
-		r_ret = t;
-	}
-
-	static void Transform_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Transform(p_args[0]->operator Basis(), p_args[1]->operator Vector3());
-	}
-
-	static void Callable_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Callable(p_args[0]->operator ObjectID(), p_args[1]->operator String());
-	}
-
-	static void Signal_init2(Variant &r_ret, const Variant **p_args) {
-		r_ret = Signal(p_args[0]->operator ObjectID(), p_args[1]->operator String());
-	}
-
-	static void add_constructor(VariantConstructFunc p_func, const Variant::Type p_type,
-			const String &p_name1 = "", const Variant::Type p_type1 = Variant::NIL,
-			const String &p_name2 = "", const Variant::Type p_type2 = Variant::NIL,
-			const String &p_name3 = "", const Variant::Type p_type3 = Variant::NIL,
-			const String &p_name4 = "", const Variant::Type p_type4 = Variant::NIL) {
-		ConstructData cd;
-		cd.func = p_func;
-		cd.arg_count = 0;
-
-		if (p_name1 == "") {
-			goto end;
-		}
-		cd.arg_count++;
-		cd.arg_names.push_back(p_name1);
-		cd.arg_types.push_back(p_type1);
-
-		if (p_name2 == "") {
-			goto end;
-		}
-		cd.arg_count++;
-		cd.arg_names.push_back(p_name2);
-		cd.arg_types.push_back(p_type2);
-
-		if (p_name3 == "") {
-			goto end;
-		}
-		cd.arg_count++;
-		cd.arg_names.push_back(p_name3);
-		cd.arg_types.push_back(p_type3);
-
-		if (p_name4 == "") {
-			goto end;
-		}
-		cd.arg_count++;
-		cd.arg_names.push_back(p_name4);
-		cd.arg_types.push_back(p_type4);
-
-	end:
-
-		construct_funcs[p_type].constructors.push_back(cd);
-	}
-
 	struct ConstantData {
 		Map<StringName, int> value;
 #ifdef DEBUG_ENABLED
@@ -882,7 +722,6 @@ struct _VariantCall {
 	}
 };
 
-_VariantCall::ConstructFunc *_VariantCall::construct_funcs = nullptr;
 _VariantCall::ConstantData *_VariantCall::constant_data = nullptr;
 _VariantCall::MethodMap *_VariantCall::type_internal_methods = nullptr;
 List<StringName> *_VariantCall::type_internal_method_names = nullptr;
@@ -935,213 +774,6 @@ void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p
 
 #define VCALL(m_type, m_method) _VariantCall::_call_##m_type##_##m_method
 
-Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, int p_argcount, Callable::CallError &r_error, bool p_strict) {
-	r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
-	ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, Variant());
-
-	r_error.error = Callable::CallError::CALL_OK;
-	if (p_argcount == 0) { //generic construct
-
-		switch (p_type) {
-			case NIL:
-				return Variant();
-
-			// atomic types
-			case BOOL:
-				return Variant(false);
-			case INT:
-				return 0;
-			case FLOAT:
-				return 0.0f;
-			case STRING:
-				return String();
-
-			// math types
-			case VECTOR2:
-				return Vector2();
-			case VECTOR2I:
-				return Vector2i();
-			case RECT2:
-				return Rect2();
-			case RECT2I:
-				return Rect2i();
-			case VECTOR3:
-				return Vector3();
-			case VECTOR3I:
-				return Vector3i();
-			case TRANSFORM2D:
-				return Transform2D();
-			case PLANE:
-				return Plane();
-			case QUAT:
-				return Quat();
-			case AABB:
-				return ::AABB();
-			case BASIS:
-				return Basis();
-			case TRANSFORM:
-				return Transform();
-
-			// misc types
-			case COLOR:
-				return Color();
-			case STRING_NAME:
-				return StringName();
-			case NODE_PATH:
-				return NodePath();
-			case _RID:
-				return RID();
-			case OBJECT:
-				return (Object *)nullptr;
-			case CALLABLE:
-				return Callable();
-			case SIGNAL:
-				return Signal();
-			case DICTIONARY:
-				return Dictionary();
-			case ARRAY:
-				return Array();
-			case PACKED_BYTE_ARRAY:
-				return PackedByteArray();
-			case PACKED_INT32_ARRAY:
-				return PackedInt32Array();
-			case PACKED_INT64_ARRAY:
-				return PackedInt64Array();
-			case PACKED_FLOAT32_ARRAY:
-				return PackedFloat32Array();
-			case PACKED_FLOAT64_ARRAY:
-				return PackedFloat64Array();
-			case PACKED_STRING_ARRAY:
-				return PackedStringArray();
-			case PACKED_VECTOR2_ARRAY:
-				return PackedVector2Array();
-			case PACKED_VECTOR3_ARRAY:
-				return PackedVector3Array();
-			case PACKED_COLOR_ARRAY:
-				return PackedColorArray();
-			default:
-				return Variant();
-		}
-
-	} else if (p_argcount == 1 && p_args[0]->type == p_type) {
-		return *p_args[0]; //copy construct
-	} else if (p_argcount == 1 && (!p_strict || Variant::can_convert(p_args[0]->type, p_type))) {
-		//near match construct
-
-		switch (p_type) {
-			case NIL: {
-				return Variant();
-			} break;
-			case BOOL: {
-				return Variant(bool(*p_args[0]));
-			}
-			case INT: {
-				return (int64_t(*p_args[0]));
-			}
-			case FLOAT: {
-				return double(*p_args[0]);
-			}
-			case STRING: {
-				return String(*p_args[0]);
-			}
-			case VECTOR2: {
-				return Vector2(*p_args[0]);
-			}
-			case VECTOR2I: {
-				return Vector2i(*p_args[0]);
-			}
-			case RECT2:
-				return (Rect2(*p_args[0]));
-			case RECT2I:
-				return (Rect2i(*p_args[0]));
-			case VECTOR3:
-				return (Vector3(*p_args[0]));
-			case VECTOR3I:
-				return (Vector3i(*p_args[0]));
-			case TRANSFORM2D:
-				return (Transform2D(p_args[0]->operator Transform2D()));
-			case PLANE:
-				return (Plane(*p_args[0]));
-			case QUAT:
-				return (p_args[0]->operator Quat());
-			case AABB:
-				return (::AABB(*p_args[0]));
-			case BASIS:
-				return (Basis(p_args[0]->operator Basis()));
-			case TRANSFORM:
-				return (Transform(p_args[0]->operator Transform()));
-
-			// misc types
-			case COLOR:
-				return p_args[0]->type == Variant::STRING ? Color::html(*p_args[0]) : Color::hex(*p_args[0]);
-			case STRING_NAME:
-				return (StringName(p_args[0]->operator StringName()));
-			case NODE_PATH:
-				return (NodePath(p_args[0]->operator NodePath()));
-			case _RID:
-				return (RID(*p_args[0]));
-			case OBJECT:
-				return ((Object *)(p_args[0]->operator Object *()));
-			case CALLABLE:
-				return ((Callable)(p_args[0]->operator Callable()));
-			case SIGNAL:
-				return ((Signal)(p_args[0]->operator Signal()));
-			case DICTIONARY:
-				return p_args[0]->operator Dictionary();
-			case ARRAY:
-				return p_args[0]->operator Array();
-
-			// arrays
-			case PACKED_BYTE_ARRAY:
-				return (PackedByteArray(*p_args[0]));
-			case PACKED_INT32_ARRAY:
-				return (PackedInt32Array(*p_args[0]));
-			case PACKED_INT64_ARRAY:
-				return (PackedInt64Array(*p_args[0]));
-			case PACKED_FLOAT32_ARRAY:
-				return (PackedFloat32Array(*p_args[0]));
-			case PACKED_FLOAT64_ARRAY:
-				return (PackedFloat64Array(*p_args[0]));
-			case PACKED_STRING_ARRAY:
-				return (PackedStringArray(*p_args[0]));
-			case PACKED_VECTOR2_ARRAY:
-				return (PackedVector2Array(*p_args[0]));
-			case PACKED_VECTOR3_ARRAY:
-				return (PackedVector3Array(*p_args[0]));
-			case PACKED_COLOR_ARRAY:
-				return (PackedColorArray(*p_args[0]));
-			default:
-				return Variant();
-		}
-	} else if (p_argcount >= 1) {
-		_VariantCall::ConstructFunc &c = _VariantCall::construct_funcs[p_type];
-
-		for (List<_VariantCall::ConstructData>::Element *E = c.constructors.front(); E; E = E->next()) {
-			const _VariantCall::ConstructData &cd = E->get();
-
-			if (cd.arg_count != p_argcount) {
-				continue;
-			}
-
-			//validate parameters
-			for (int i = 0; i < cd.arg_count; i++) {
-				if (!Variant::can_convert(p_args[i]->type, cd.arg_types[i])) {
-					r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; //no such constructor
-					r_error.argument = i;
-					r_error.expected = cd.arg_types[i];
-					return Variant();
-				}
-			}
-
-			Variant v;
-			cd.func(v, p_args);
-			return v;
-		}
-	}
-	r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; //no such constructor
-	return Variant();
-}
-
 bool Variant::has_method(const StringName &p_method) const {
 	if (type == OBJECT) {
 		Object *obj = get_validated_object();
@@ -1246,43 +878,6 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
 	}
 }
 
-void Variant::get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list) {
-	ERR_FAIL_INDEX(p_type, VARIANT_MAX);
-
-	//custom constructors
-	for (const List<_VariantCall::ConstructData>::Element *E = _VariantCall::construct_funcs[p_type].constructors.front(); E; E = E->next()) {
-		const _VariantCall::ConstructData &cd = E->get();
-		MethodInfo mi;
-		mi.name = Variant::get_type_name(p_type);
-		mi.return_val.type = p_type;
-		for (int i = 0; i < cd.arg_count; i++) {
-			PropertyInfo pi;
-			pi.name = cd.arg_names[i];
-			pi.type = cd.arg_types[i];
-			mi.arguments.push_back(pi);
-		}
-		p_list->push_back(mi);
-	}
-	//default constructors
-	for (int i = 0; i < VARIANT_MAX; i++) {
-		if (i == p_type) {
-			continue;
-		}
-		if (!Variant::can_convert(Variant::Type(i), p_type)) {
-			continue;
-		}
-
-		MethodInfo mi;
-		mi.name = Variant::get_type_name(p_type);
-		PropertyInfo pi;
-		pi.name = "from";
-		pi.type = Variant::Type(i);
-		mi.arguments.push_back(pi);
-		mi.return_val.type = p_type;
-		p_list->push_back(mi);
-	}
-}
-
 void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants) {
 	ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
 
@@ -1350,10 +945,9 @@ Variant::InternalMethod *Variant::get_internal_method(Type p_type, const StringN
 	return nullptr;
 }
 
-void register_variant_methods() {
+void Variant::_register_variant_methods() {
 	_VariantCall::type_internal_methods = memnew_arr(_VariantCall::MethodMap, Variant::VARIANT_MAX);
 	_VariantCall::type_internal_method_names = memnew_arr(List<StringName>, Variant::VARIANT_MAX);
-	_VariantCall::construct_funcs = memnew_arr(_VariantCall::ConstructFunc, Variant::VARIANT_MAX);
 	_VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX);
 
 	/* String */
@@ -1946,47 +1540,6 @@ void register_variant_methods() {
 	bind_method(PackedColorArray, to_byte_array, sarray(), varray());
 	bind_method(PackedColorArray, sort, sarray(), varray());
 
-	/* Register constructors */
-
-	_VariantCall::add_constructor(_VariantCall::Vector2_init1, Variant::VECTOR2, "x", Variant::FLOAT, "y", Variant::FLOAT);
-	_VariantCall::add_constructor(_VariantCall::Vector2i_init1, Variant::VECTOR2I, "x", Variant::INT, "y", Variant::INT);
-
-	_VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "position", Variant::VECTOR2, "size", Variant::VECTOR2);
-	_VariantCall::add_constructor(_VariantCall::Rect2_init2, Variant::RECT2, "x", Variant::FLOAT, "y", Variant::FLOAT, "width", Variant::FLOAT, "height", Variant::FLOAT);
-
-	_VariantCall::add_constructor(_VariantCall::Rect2i_init1, Variant::RECT2I, "position", Variant::VECTOR2I, "size", Variant::VECTOR2I);
-	_VariantCall::add_constructor(_VariantCall::Rect2i_init2, Variant::RECT2I, "x", Variant::INT, "y", Variant::INT, "width", Variant::INT, "height", Variant::INT);
-
-	_VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rotation", Variant::FLOAT, "position", Variant::VECTOR2);
-	_VariantCall::add_constructor(_VariantCall::Transform2D_init3, Variant::TRANSFORM2D, "x_axis", Variant::VECTOR2, "y_axis", Variant::VECTOR2, "origin", Variant::VECTOR2);
-
-	_VariantCall::add_constructor(_VariantCall::Vector3_init1, Variant::VECTOR3, "x", Variant::FLOAT, "y", Variant::FLOAT, "z", Variant::FLOAT);
-	_VariantCall::add_constructor(_VariantCall::Vector3i_init1, Variant::VECTOR3I, "x", Variant::INT, "y", Variant::INT, "z", Variant::INT);
-
-	_VariantCall::add_constructor(_VariantCall::Plane_init1, Variant::PLANE, "a", Variant::FLOAT, "b", Variant::FLOAT, "c", Variant::FLOAT, "d", Variant::FLOAT);
-	_VariantCall::add_constructor(_VariantCall::Plane_init2, Variant::PLANE, "v1", Variant::VECTOR3, "v2", Variant::VECTOR3, "v3", Variant::VECTOR3);
-	_VariantCall::add_constructor(_VariantCall::Plane_init3, Variant::PLANE, "normal", Variant::VECTOR3, "d", Variant::FLOAT);
-
-	_VariantCall::add_constructor(_VariantCall::Quat_init1, Variant::QUAT, "x", Variant::FLOAT, "y", Variant::FLOAT, "z", Variant::FLOAT, "w", Variant::FLOAT);
-	_VariantCall::add_constructor(_VariantCall::Quat_init2, Variant::QUAT, "axis", Variant::VECTOR3, "angle", Variant::FLOAT);
-	_VariantCall::add_constructor(_VariantCall::Quat_init3, Variant::QUAT, "euler", Variant::VECTOR3);
-
-	_VariantCall::add_constructor(_VariantCall::Color_init1, Variant::COLOR, "r", Variant::FLOAT, "g", Variant::FLOAT, "b", Variant::FLOAT, "a", Variant::FLOAT);
-	_VariantCall::add_constructor(_VariantCall::Color_init2, Variant::COLOR, "r", Variant::FLOAT, "g", Variant::FLOAT, "b", Variant::FLOAT);
-	// init3 and init4 are the constructors for HTML hex strings and integers respectively which don't need binding here, so we skip to init5.
-	_VariantCall::add_constructor(_VariantCall::Color_init5, Variant::COLOR, "c", Variant::COLOR, "a", Variant::FLOAT);
-
-	_VariantCall::add_constructor(_VariantCall::AABB_init1, Variant::AABB, "position", Variant::VECTOR3, "size", Variant::VECTOR3);
-
-	_VariantCall::add_constructor(_VariantCall::Basis_init1, Variant::BASIS, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3);
-	_VariantCall::add_constructor(_VariantCall::Basis_init2, Variant::BASIS, "axis", Variant::VECTOR3, "phi", Variant::FLOAT);
-
-	_VariantCall::add_constructor(_VariantCall::Transform_init1, Variant::TRANSFORM, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3, "origin", Variant::VECTOR3);
-	_VariantCall::add_constructor(_VariantCall::Transform_init2, Variant::TRANSFORM, "basis", Variant::BASIS, "origin", Variant::VECTOR3);
-
-	_VariantCall::add_constructor(_VariantCall::Callable_init2, Variant::CALLABLE, "object", Variant::OBJECT, "method_name", Variant::STRING_NAME);
-	_VariantCall::add_constructor(_VariantCall::Signal_init2, Variant::SIGNAL, "object", Variant::OBJECT, "signal_name", Variant::STRING_NAME);
-
 	/* Register constants */
 
 	int ncc = Color::get_named_color_count();
@@ -2071,7 +1624,7 @@ void register_variant_methods() {
 	_VariantCall::add_variant_constant(Variant::QUAT, "IDENTITY", Quat(0, 0, 0, 1));
 }
 
-void unregister_variant_methods() {
+void Variant::_unregister_variant_methods() {
 	//clear methods
 	for (int i = 0; i < Variant::VARIANT_MAX; i++) {
 		for (List<StringName>::Element *E = _VariantCall::type_internal_method_names[i].front(); E; E = E->next()) {
@@ -2084,6 +1637,5 @@ void unregister_variant_methods() {
 
 	memdelete_arr(_VariantCall::type_internal_methods);
 	memdelete_arr(_VariantCall::type_internal_method_names);
-	memdelete_arr(_VariantCall::construct_funcs);
 	memdelete_arr(_VariantCall::constant_data);
 }

+ 781 - 0
core/variant/variant_construct.cpp

@@ -0,0 +1,781 @@
+/*************************************************************************/
+/*  variant_construct.cpp                                                */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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.                */
+/*************************************************************************/
+
+#include "variant.h"
+
+#include "core/core_string_names.h"
+#include "core/crypto/crypto_core.h"
+#include "core/debugger/engine_debugger.h"
+#include "core/io/compression.h"
+#include "core/object/class_db.h"
+#include "core/os/os.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/oa_hash_map.h"
+
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) {
+}
+
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) {
+	arr.push_back(p_str);
+}
+
+template <class... P>
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) {
+	arr.push_back(p_str);
+	sarray_add_str(arr, p_args...);
+}
+
+template <class... P>
+_FORCE_INLINE_ Vector<String> sarray(P... p_args) {
+	Vector<String> arr;
+	sarray_add_str(arr, p_args...);
+	return arr;
+}
+
+template <class T, class... P>
+class VariantConstructor {
+	template <size_t... Is>
+	static _FORCE_INLINE_ void construct_helper(T &base, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+		r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+		base = T(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+		base = T(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+	}
+
+	template <size_t... Is>
+	static _FORCE_INLINE_ void validated_construct_helper(T &base, const Variant **p_args, IndexSequence<Is...>) {
+		base = T((*VariantGetInternalPtr<P>::get_ptr(p_args[Is]))...);
+	}
+
+	template <size_t... Is>
+	static _FORCE_INLINE_ void ptr_construct_helper(void *base, const void **p_args, IndexSequence<Is...>) {
+		PtrToArg<T>::encode(T(PtrToArg<P>::convert(p_args[Is])...), base);
+	}
+
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		r_error.error = Callable::CallError::CALL_OK;
+		VariantTypeChanger<T>::change(&r_ret);
+		construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+	}
+
+	static void validated_construct(Variant &r_ret, const Variant **p_args) {
+		VariantTypeChanger<T>::change(&r_ret);
+		validated_construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, BuildIndexSequence<sizeof...(P)>{});
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		ptr_construct_helper(base, p_args, BuildIndexSequence<sizeof...(P)>{});
+	}
+
+	static int get_argument_count() {
+		return sizeof...(P);
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return call_get_argument_type<P...>(p_arg);
+	}
+
+	static Variant::Type get_base_type() {
+		return GetTypeInfo<T>::VARIANT_TYPE;
+	}
+};
+
+class VariantConstructorObject {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		VariantInternal::clear(&r_ret);
+		if (p_args[0]->get_type() == Variant::NIL) {
+			VariantInternal::object_assign_null(&r_ret);
+			r_error.error = Callable::CallError::CALL_OK;
+		} else if (p_args[0]->get_type() == Variant::OBJECT) {
+			VariantInternal::object_assign(&r_ret, p_args[0]);
+			r_error.error = Callable::CallError::CALL_OK;
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::OBJECT;
+		}
+	}
+
+	static void validated_construct(Variant &r_ret, const Variant **p_args) {
+		VariantInternal::clear(&r_ret);
+		VariantInternal::object_assign(&r_ret, p_args[0]);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrToArg<Object *>::encode(PtrToArg<Object *>::convert(p_args[0]), base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::OBJECT;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::OBJECT;
+	}
+};
+
+class VariantConstructorNilObject {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		if (p_args[0]->get_type() != Variant::NIL) {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::NIL;
+		}
+
+		VariantInternal::clear(&r_ret);
+		VariantInternal::object_assign_null(&r_ret);
+	}
+
+	static void validated_construct(Variant &r_ret, const Variant **p_args) {
+		VariantInternal::clear(&r_ret);
+		VariantInternal::object_assign_null(&r_ret);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrToArg<Object *>::encode(nullptr, base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::NIL;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::OBJECT;
+	}
+};
+
+class VariantConstructorCallableArgs {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		ObjectID object_id;
+		StringName method;
+
+		if (p_args[0]->get_type() == Variant::NIL) {
+			// leave as is
+		} else if (p_args[0]->get_type() == Variant::OBJECT) {
+			object_id = VariantInternal::get_object_id(p_args[0]);
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::OBJECT;
+			return;
+		}
+
+		if (p_args[1]->get_type() == Variant::STRING_NAME) {
+			method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
+		} else if (p_args[1]->get_type() == Variant::STRING) {
+			method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 1;
+			r_error.expected = Variant::STRING_NAME;
+			return;
+		}
+
+		VariantTypeChanger<Callable>::change(&r_ret);
+		*VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(object_id, method);
+	}
+
+	static void validated_construct(Variant &r_ret, const Variant **p_args) {
+		VariantTypeChanger<Callable>::change(&r_ret);
+		*VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrToArg<Callable>::encode(Callable(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
+	}
+
+	static int get_argument_count() {
+		return 2;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		if (p_arg == 0) {
+			return Variant::OBJECT;
+		} else {
+			return Variant::STRING_NAME;
+		}
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::CALLABLE;
+	}
+};
+
+class VariantConstructorSignalArgs {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		ObjectID object_id;
+		StringName method;
+
+		if (p_args[0]->get_type() == Variant::NIL) {
+			// leave as is
+		} else if (p_args[0]->get_type() == Variant::OBJECT) {
+			object_id = VariantInternal::get_object_id(p_args[0]);
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::OBJECT;
+			return;
+		}
+
+		if (p_args[1]->get_type() == Variant::STRING_NAME) {
+			method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
+		} else if (p_args[1]->get_type() == Variant::STRING) {
+			method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 1;
+			r_error.expected = Variant::STRING_NAME;
+			return;
+		}
+
+		VariantTypeChanger<Signal>::change(&r_ret);
+		*VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(object_id, method);
+	}
+
+	static void validated_construct(Variant &r_ret, const Variant **p_args) {
+		VariantTypeChanger<Signal>::change(&r_ret);
+		*VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrToArg<Signal>::encode(Signal(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
+	}
+
+	static int get_argument_count() {
+		return 2;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		if (p_arg == 0) {
+			return Variant::OBJECT;
+		} else {
+			return Variant::STRING_NAME;
+		}
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::CALLABLE;
+	}
+};
+
+template <class T>
+class VariantConstructorToArray {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		if (p_args[0]->get_type() != GetTypeInfo<T>::VARIANT_TYPE) {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = GetTypeInfo<T>::VARIANT_TYPE;
+			return;
+		}
+
+		VariantTypeChanger<Array>::change(&r_ret);
+		Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
+		const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr[i] = src_arr[i];
+		}
+	}
+
+	static void validated_construct(Variant &r_ret, const Variant **p_args) {
+		VariantTypeChanger<Array>::change(&r_ret);
+		Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
+		const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr[i] = src_arr[i];
+		}
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		Array dst_arr;
+		T src_arr = PtrToArg<T>::convert(p_args[0]);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr[i] = src_arr[i];
+		}
+
+		PtrToArg<Array>::encode(dst_arr, base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return GetTypeInfo<T>::VARIANT_TYPE;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::ARRAY;
+	}
+};
+
+template <class T>
+class VariantConstructorFromArray {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		if (p_args[0]->get_type() != Variant::ARRAY) {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::ARRAY;
+			return;
+		}
+
+		VariantTypeChanger<T>::change(&r_ret);
+		const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
+		T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr.write[i] = src_arr[i];
+		}
+	}
+
+	static void validated_construct(Variant &r_ret, const Variant **p_args) {
+		VariantTypeChanger<T>::change(&r_ret);
+		const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
+		T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr.write[i] = src_arr[i];
+		}
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		Array src_arr = PtrToArg<Array>::convert(p_args[0]);
+		T dst_arr;
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr.write[i] = src_arr[i];
+		}
+
+		PtrToArg<T>::encode(dst_arr, base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::ARRAY;
+	}
+
+	static Variant::Type get_base_type() {
+		return GetTypeInfo<T>::VARIANT_TYPE;
+	}
+};
+
+class VariantConstructorNil {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		if (p_args[0]->get_type() != Variant::NIL) {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::NIL;
+			return;
+		}
+
+		r_error.error = Callable::CallError::CALL_OK;
+		VariantInternal::clear(&r_ret);
+	}
+
+	static void validated_construct(Variant &r_ret, const Variant **p_args) {
+		VariantInternal::clear(&r_ret);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrToArg<Variant>::encode(Variant(), base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::NIL;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::NIL;
+	}
+};
+
+struct VariantConstructData {
+	void (*construct)(Variant &r_base, const Variant **p_args, Callable::CallError &r_error);
+	Variant::ValidatedConstructor validated_construct;
+	Variant::PTRConstructor ptr_construct;
+	Variant::Type (*get_argument_type)(int);
+	int argument_count;
+	Vector<String> arg_names;
+};
+
+static LocalVector<VariantConstructData> construct_data[Variant::VARIANT_MAX];
+
+static void variant_initialize_nil(Variant *v) {
+	VariantInternal::clear(v);
+}
+
+template <class T>
+static void variant_initialize(Variant *v) {
+	VariantTypeChanger<T>::change(v);
+}
+
+template <class T>
+static void variant_initialize_zero(Variant *v) {
+	VariantTypeChanger<T>::change(v);
+	*VariantGetInternalPtr<T>::get_ptr(v) = 0;
+}
+
+static void variant_initialize_false(Variant *v) {
+	VariantTypeChanger<bool>::change(v);
+	*VariantGetInternalPtr<bool>::get_ptr(v) = false;
+}
+
+static void variant_initialize_obj(Variant *v) {
+	VariantInternal::clear(v);
+	VariantInternal::object_assign_null(v);
+}
+
+typedef void (*VariantInitializeFunc)(Variant *v);
+
+static VariantInitializeFunc initialize_funcs[Variant::VARIANT_MAX];
+
+template <class T>
+static void add_constructor(const Vector<String> &arg_names) {
+	ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), "Argument names size mismatch for " + Variant::get_type_name(T::get_base_type()) + ".");
+
+	VariantConstructData cd;
+	cd.construct = T::construct;
+	cd.validated_construct = T::validated_construct;
+	cd.ptr_construct = T::ptr_construct;
+	cd.get_argument_type = T::get_argument_type;
+	cd.argument_count = T::get_argument_count();
+	cd.arg_names = arg_names;
+	construct_data[T::get_base_type()].push_back(cd);
+}
+
+void Variant::_register_variant_constructors() {
+	add_constructor<VariantConstructorNil>(sarray("from"));
+
+	add_constructor<VariantConstructor<bool, bool>>(sarray("from"));
+	add_constructor<VariantConstructor<bool, int64_t>>(sarray("from"));
+	add_constructor<VariantConstructor<bool, double>>(sarray("from"));
+
+	add_constructor<VariantConstructor<int64_t, int64_t>>(sarray("from"));
+	add_constructor<VariantConstructor<int64_t, double>>(sarray("from"));
+
+	add_constructor<VariantConstructor<double, double>>(sarray("from"));
+	add_constructor<VariantConstructor<double, int64_t>>(sarray("from"));
+
+	add_constructor<VariantConstructor<String, String>>(sarray("from"));
+	add_constructor<VariantConstructor<String, StringName>>(sarray("from"));
+	add_constructor<VariantConstructor<String, NodePath>>(sarray("from"));
+
+	add_constructor<VariantConstructor<Vector2, Vector2>>(sarray("from"));
+	add_constructor<VariantConstructor<Vector2, Vector2i>>(sarray("from"));
+	add_constructor<VariantConstructor<Vector2, double, double>>(sarray("x", "y"));
+
+	add_constructor<VariantConstructor<Vector2i, Vector2i>>(sarray("from"));
+	add_constructor<VariantConstructor<Vector2i, Vector2>>(sarray("from"));
+	add_constructor<VariantConstructor<Vector2i, int64_t, int64_t>>(sarray("x", "y"));
+
+	add_constructor<VariantConstructor<Rect2, Rect2>>(sarray("from"));
+	add_constructor<VariantConstructor<Rect2, Rect2i>>(sarray("from"));
+	add_constructor<VariantConstructor<Rect2, Vector2, Vector2>>(sarray("position", "size"));
+	add_constructor<VariantConstructor<Rect2, double, double, double, double>>(sarray("x", "y", "width", "height"));
+
+	add_constructor<VariantConstructor<Rect2i, Rect2i>>(sarray("from"));
+	add_constructor<VariantConstructor<Rect2i, Rect2>>(sarray("from"));
+	add_constructor<VariantConstructor<Rect2i, Vector2i, Vector2i>>(sarray("position", "size"));
+	add_constructor<VariantConstructor<Rect2i, int64_t, int64_t, int64_t, int64_t>>(sarray("x", "y", "width", "height"));
+
+	add_constructor<VariantConstructor<Vector3, Vector3>>(sarray("from"));
+	add_constructor<VariantConstructor<Vector3, Vector3i>>(sarray("from"));
+	add_constructor<VariantConstructor<Vector3, double, double, double>>(sarray("x", "y", "z"));
+
+	add_constructor<VariantConstructor<Vector3i, Vector3i>>(sarray("from"));
+	add_constructor<VariantConstructor<Vector3i, Vector3>>(sarray("from"));
+	add_constructor<VariantConstructor<Vector3i, int64_t, int64_t, int64_t>>(sarray("x", "y", "z"));
+
+	add_constructor<VariantConstructor<Transform2D, Transform2D>>(sarray("from"));
+	add_constructor<VariantConstructor<Transform2D, Vector2, Vector2, Vector2>>(sarray("x", "y", "origin"));
+
+	add_constructor<VariantConstructor<Plane, Plane>>(sarray("from"));
+	add_constructor<VariantConstructor<Plane, Vector3, double>>(sarray("normal", "d"));
+	add_constructor<VariantConstructor<Plane, Vector3, Vector3>>(sarray("point", "normal"));
+	add_constructor<VariantConstructor<Plane, Vector3, Vector3, Vector3>>(sarray("point1", "point2", "point3"));
+
+	add_constructor<VariantConstructor<Quat, Quat>>(sarray("from"));
+	add_constructor<VariantConstructor<Quat, Basis>>(sarray("from"));
+	add_constructor<VariantConstructor<Quat, Vector3>>(sarray("euler"));
+	add_constructor<VariantConstructor<Quat, Vector3, double>>(sarray("axis", "angle"));
+	add_constructor<VariantConstructor<Quat, Vector3, Vector3>>(sarray("arc_from", "arc_to"));
+
+	add_constructor<VariantConstructor<::AABB, ::AABB>>(sarray("from"));
+	add_constructor<VariantConstructor<::AABB, Vector3, Vector3>>(sarray("position", "size"));
+
+	add_constructor<VariantConstructor<Basis, Basis>>(sarray("from"));
+	add_constructor<VariantConstructor<Basis, Quat>>(sarray("from"));
+	add_constructor<VariantConstructor<Basis, Vector3, Vector3, Vector3>>(sarray("x", "y", "z"));
+
+	add_constructor<VariantConstructor<Transform, Transform>>(sarray("from"));
+	add_constructor<VariantConstructor<Transform, Basis, Vector3>>(sarray("basis", "origin"));
+
+	add_constructor<VariantConstructor<Color, Color>>(sarray("from"));
+
+	add_constructor<VariantConstructor<StringName, StringName>>(sarray("from"));
+	add_constructor<VariantConstructor<StringName, String>>(sarray("from"));
+
+	add_constructor<VariantConstructor<NodePath, NodePath>>(sarray("from"));
+	add_constructor<VariantConstructor<NodePath, String>>(sarray("from"));
+
+	add_constructor<VariantConstructor<RID, RID>>(sarray("from"));
+
+	add_constructor<VariantConstructorObject>(sarray("from"));
+	add_constructor<VariantConstructorNilObject>(sarray("from"));
+
+	add_constructor<VariantConstructor<Callable, Callable>>(sarray("from"));
+	add_constructor<VariantConstructorCallableArgs>(sarray("object", "method"));
+
+	add_constructor<VariantConstructor<Signal, Signal>>(sarray("from"));
+	add_constructor<VariantConstructorSignalArgs>(sarray("object", "signal"));
+
+	add_constructor<VariantConstructor<Dictionary, Dictionary>>(sarray("from"));
+
+	add_constructor<VariantConstructor<Array, Array>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedByteArray>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedInt32Array>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedInt64Array>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedFloat64Array>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedFloat64Array>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedStringArray>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedVector2Array>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedVector3Array>>(sarray("from"));
+	add_constructor<VariantConstructorToArray<PackedColorArray>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedByteArray, PackedByteArray>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedByteArray>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedInt32Array, PackedInt32Array>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedInt32Array>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedInt64Array, PackedInt64Array>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedInt64Array>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedFloat32Array, PackedFloat32Array>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedFloat32Array>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedFloat64Array, PackedFloat64Array>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedFloat64Array>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedStringArray, PackedStringArray>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedStringArray>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedVector2Array, PackedVector2Array>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedVector2Array>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedVector3Array, PackedVector3Array>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedVector3Array>>(sarray("from"));
+
+	add_constructor<VariantConstructor<PackedColorArray, PackedColorArray>>(sarray("from"));
+	add_constructor<VariantConstructorFromArray<PackedColorArray>>(sarray("from"));
+
+	initialize_funcs[NIL] = variant_initialize_nil;
+
+	// atomic types
+	initialize_funcs[BOOL] = variant_initialize_false;
+	initialize_funcs[INT] = variant_initialize_zero<int64_t>;
+	initialize_funcs[FLOAT] = variant_initialize_zero<double>;
+	initialize_funcs[STRING] = variant_initialize<String>;
+
+	// math types
+	initialize_funcs[VECTOR2] = variant_initialize<Vector2>;
+	initialize_funcs[VECTOR2I] = variant_initialize<Vector2i>;
+	initialize_funcs[RECT2] = variant_initialize<Rect2>;
+	initialize_funcs[RECT2I] = variant_initialize<Rect2i>;
+	initialize_funcs[VECTOR3] = variant_initialize<Vector3>;
+	initialize_funcs[VECTOR3I] = variant_initialize<Vector3i>;
+	initialize_funcs[TRANSFORM2D] = variant_initialize<Transform2D>;
+	initialize_funcs[PLANE] = variant_initialize<Plane>;
+	initialize_funcs[QUAT] = variant_initialize<Quat>;
+	initialize_funcs[AABB] = variant_initialize<::AABB>;
+	initialize_funcs[BASIS] = variant_initialize<Basis>;
+	initialize_funcs[TRANSFORM] = variant_initialize<Transform>;
+
+	// misc types
+	initialize_funcs[COLOR] = variant_initialize<Color>;
+	initialize_funcs[STRING_NAME] = variant_initialize<StringName>;
+	initialize_funcs[NODE_PATH] = variant_initialize<NodePath>;
+	initialize_funcs[_RID] = variant_initialize<RID>;
+	initialize_funcs[OBJECT] = variant_initialize_obj;
+	initialize_funcs[CALLABLE] = variant_initialize<Callable>;
+	initialize_funcs[SIGNAL] = variant_initialize<Signal>;
+	initialize_funcs[DICTIONARY] = variant_initialize<Dictionary>;
+	initialize_funcs[ARRAY] = variant_initialize<Array>;
+
+	// typed arrays
+	initialize_funcs[PACKED_BYTE_ARRAY] = variant_initialize<PackedByteArray>;
+	initialize_funcs[PACKED_INT32_ARRAY] = variant_initialize<PackedInt32Array>;
+	initialize_funcs[PACKED_INT64_ARRAY] = variant_initialize<PackedInt64Array>;
+	initialize_funcs[PACKED_FLOAT32_ARRAY] = variant_initialize<PackedFloat32Array>;
+	initialize_funcs[PACKED_FLOAT64_ARRAY] = variant_initialize<PackedFloat64Array>;
+	initialize_funcs[PACKED_STRING_ARRAY] = variant_initialize<PackedStringArray>;
+	initialize_funcs[PACKED_VECTOR2_ARRAY] = variant_initialize<PackedVector2Array>;
+	initialize_funcs[PACKED_VECTOR3_ARRAY] = variant_initialize<PackedVector3Array>;
+	initialize_funcs[PACKED_COLOR_ARRAY] = variant_initialize<PackedColorArray>;
+}
+
+void Variant::_unregister_variant_constructors() {
+	for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+		construct_data[i].clear();
+	}
+}
+
+void Variant::construct(Variant::Type p_type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+	if (p_argcount == 0) {
+		initialize_funcs[p_type](&base);
+		r_error.error = Callable::CallError::CALL_OK;
+
+	} else {
+		uint32_t s = construct_data[p_type].size();
+		for (uint32_t i = 0; i < s; i++) {
+			int argc = construct_data[p_type][i].argument_count;
+			if (argc != p_argcount) {
+				continue;
+			}
+			bool args_match = true;
+			for (int j = 0; j < argc; j++) {
+				if (!Variant::can_convert_strict(p_args[j]->get_type(), construct_data[p_type][i].get_argument_type(j))) {
+					args_match = false;
+					break;
+				}
+			}
+
+			if (!args_match) {
+				continue;
+			}
+
+			construct_data[p_type][i].construct(base, p_args, r_error);
+			return;
+		}
+
+		r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+	}
+}
+
+int Variant::get_constructor_count(Variant::Type p_type) {
+	ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
+	return construct_data[p_type].size();
+}
+
+Variant::ValidatedConstructor Variant::get_validated_constructor(Variant::Type p_type, int p_constructor) {
+	ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
+	ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), nullptr);
+	return construct_data[p_type][p_constructor].validated_construct;
+}
+
+Variant::PTRConstructor Variant::get_ptr_constructor(Variant::Type p_type, int p_constructor) {
+	ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
+	ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), nullptr);
+	return construct_data[p_type][p_constructor].ptr_construct;
+}
+
+int Variant::get_constructor_argument_count(Variant::Type p_type, int p_constructor) {
+	ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
+	ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), -1);
+	return construct_data[p_type][p_constructor].argument_count;
+}
+
+Variant::Type Variant::get_constructor_argument_type(Variant::Type p_type, int p_constructor, int p_argument) {
+	ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX);
+	ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), Variant::VARIANT_MAX);
+	return construct_data[p_type][p_constructor].get_argument_type(p_argument);
+}
+
+String Variant::get_constructor_argument_name(Variant::Type p_type, int p_constructor, int p_argument) {
+	ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String());
+	ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), String());
+	return construct_data[p_type][p_constructor].arg_names[p_argument];
+}
+
+void VariantInternal::object_assign(Variant *v, const Variant *o) {
+	if (o->_get_obj().obj && o->_get_obj().id.is_reference()) {
+		Reference *reference = static_cast<Reference *>(o->_get_obj().obj);
+		if (!reference->reference()) {
+			v->_get_obj().obj = nullptr;
+			v->_get_obj().id = ObjectID();
+			return;
+		}
+	}
+
+	v->_get_obj().obj = const_cast<Object *>(o->_get_obj().obj);
+	v->_get_obj().id = o->_get_obj().id;
+}
+
+void Variant::get_constructor_list(Type p_type, List<MethodInfo> *r_list) {
+	ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
+
+	MethodInfo mi;
+	mi.return_val.type = p_type;
+	mi.name = get_type_name(p_type);
+
+	for (int i = 0; i < get_constructor_count(p_type); i++) {
+		int ac = get_constructor_argument_count(p_type, i);
+		mi.arguments.clear();
+		for (int j = 0; j < ac; j++) {
+			PropertyInfo arg;
+			arg.name = get_constructor_argument_name(p_type, i, j);
+			arg.type = get_constructor_argument_type(p_type, i, j);
+			mi.arguments.push_back(arg);
+		}
+		r_list->push_back(mi);
+	}
+}

+ 297 - 0
core/variant/variant_internal.h

@@ -116,6 +116,106 @@ public:
 
 	_FORCE_INLINE_ static Object **get_object(Variant *v) { return (Object **)&v->_get_obj().obj; }
 	_FORCE_INLINE_ static const Object **get_object(const Variant *v) { return (const Object **)&v->_get_obj().obj; }
+
+	_FORCE_INLINE_ static const ObjectID get_object_id(const Variant *v) { return v->_get_obj().id; }
+
+	template <class T>
+	_FORCE_INLINE_ static void init_generic(Variant *v) {
+		v->type = GetTypeInfo<T>::VARIANT_TYPE;
+	}
+
+	_FORCE_INLINE_ static void init_string(Variant *v) {
+		memnew_placement(v->_data._mem, String);
+		v->type = Variant::STRING;
+	}
+
+	_FORCE_INLINE_ static void init_transform2d(Variant *v) {
+		v->_data._transform2d = memnew(Transform2D);
+		v->type = Variant::TRANSFORM2D;
+	}
+	_FORCE_INLINE_ static void init_aabb(Variant *v) {
+		v->_data._aabb = memnew(AABB);
+		v->type = Variant::AABB;
+	}
+	_FORCE_INLINE_ static void init_basis(Variant *v) {
+		v->_data._basis = memnew(Basis);
+		v->type = Variant::BASIS;
+	}
+	_FORCE_INLINE_ static void init_transform(Variant *v) {
+		v->_data._transform = memnew(Transform);
+		v->type = Variant::TRANSFORM;
+	}
+	_FORCE_INLINE_ static void init_string_name(Variant *v) {
+		memnew_placement(v->_data._mem, StringName);
+		v->type = Variant::STRING_NAME;
+	}
+	_FORCE_INLINE_ static void init_node_path(Variant *v) {
+		memnew_placement(v->_data._mem, NodePath);
+		v->type = Variant::NODE_PATH;
+	}
+	_FORCE_INLINE_ static void init_callable(Variant *v) {
+		memnew_placement(v->_data._mem, Callable);
+		v->type = Variant::CALLABLE;
+	}
+	_FORCE_INLINE_ static void init_signal(Variant *v) {
+		memnew_placement(v->_data._mem, Signal);
+		v->type = Variant::SIGNAL;
+	}
+	_FORCE_INLINE_ static void init_dictionary(Variant *v) {
+		memnew_placement(v->_data._mem, Dictionary);
+		v->type = Variant::DICTIONARY;
+	}
+	_FORCE_INLINE_ static void init_array(Variant *v) {
+		memnew_placement(v->_data._mem, Array);
+		v->type = Variant::ARRAY;
+	}
+	_FORCE_INLINE_ static void init_byte_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<uint8_t>::create(Vector<uint8_t>());
+		v->type = Variant::PACKED_BYTE_ARRAY;
+	}
+	_FORCE_INLINE_ static void init_int32_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<int32_t>::create(Vector<int32_t>());
+		v->type = Variant::PACKED_INT32_ARRAY;
+	}
+	_FORCE_INLINE_ static void init_int64_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<int64_t>::create(Vector<int64_t>());
+		v->type = Variant::PACKED_INT64_ARRAY;
+	}
+	_FORCE_INLINE_ static void init_float32_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<float>::create(Vector<float>());
+		v->type = Variant::PACKED_FLOAT32_ARRAY;
+	}
+	_FORCE_INLINE_ static void init_float64_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<double>::create(Vector<double>());
+		v->type = Variant::PACKED_FLOAT64_ARRAY;
+	}
+	_FORCE_INLINE_ static void init_string_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<String>::create(Vector<String>());
+		v->type = Variant::PACKED_STRING_ARRAY;
+	}
+	_FORCE_INLINE_ static void init_vector2_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<Vector2>::create(Vector<Vector2>());
+		v->type = Variant::PACKED_VECTOR2_ARRAY;
+	}
+	_FORCE_INLINE_ static void init_vector3_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<Vector3>::create(Vector<Vector3>());
+		v->type = Variant::PACKED_VECTOR3_ARRAY;
+	}
+	_FORCE_INLINE_ static void init_color_array(Variant *v) {
+		v->_data.packed_array = Variant::PackedArrayRef<Color>::create(Vector<Color>());
+		v->type = Variant::PACKED_COLOR_ARRAY;
+	}
+
+	_FORCE_INLINE_ static void clear(Variant *v) {
+		v->clear();
+	}
+
+	static void object_assign(Variant *v, const Variant *o); //needs to use reference, do away
+
+	_FORCE_INLINE_ static void object_assign_null(Variant *v) {
+		v->_get_obj().obj = nullptr;
+		v->_get_obj().id = ObjectID();
+	}
 };
 
 template <class T>
@@ -649,4 +749,201 @@ struct VariantInternalAccessor<Vector<Variant>> {
 	}
 };
 
+template <class T>
+struct VariantInitializer {
+};
+
+template <>
+struct VariantInitializer<bool> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<bool>(v); }
+};
+
+#define INITIALIZER_INT(m_type)                                                                    \
+	template <>                                                                                    \
+	struct VariantInitializer<m_type> {                                                            \
+		static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<int64_t>(v); } \
+	};
+
+INITIALIZER_INT(uint8_t)
+INITIALIZER_INT(int8_t)
+INITIALIZER_INT(uint16_t)
+INITIALIZER_INT(int16_t)
+INITIALIZER_INT(uint32_t)
+INITIALIZER_INT(int32_t)
+INITIALIZER_INT(uint64_t)
+INITIALIZER_INT(int64_t)
+INITIALIZER_INT(char32_t)
+INITIALIZER_INT(Error)
+INITIALIZER_INT(ObjectID)
+
+template <>
+struct VariantInitializer<double> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<double>(v); }
+};
+
+template <>
+struct VariantInitializer<float> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<double>(v); }
+};
+
+template <>
+struct VariantInitializer<String> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string(v); }
+};
+
+template <>
+struct VariantInitializer<Vector2> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector2>(v); }
+};
+
+template <>
+struct VariantInitializer<Vector2i> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector2i>(v); }
+};
+
+template <>
+struct VariantInitializer<Rect2> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Rect2>(v); }
+};
+
+template <>
+struct VariantInitializer<Rect2i> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Rect2i>(v); }
+};
+
+template <>
+struct VariantInitializer<Vector3> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector3>(v); }
+};
+
+template <>
+struct VariantInitializer<Vector3i> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector3i>(v); }
+};
+
+template <>
+struct VariantInitializer<Transform2D> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform2d(v); }
+};
+
+template <>
+struct VariantInitializer<Plane> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Plane>(v); }
+};
+
+template <>
+struct VariantInitializer<Quat> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Quat>(v); }
+};
+
+template <>
+struct VariantInitializer<AABB> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_aabb(v); }
+};
+
+template <>
+struct VariantInitializer<Basis> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_basis(v); }
+};
+
+template <>
+struct VariantInitializer<Transform> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform(v); }
+};
+
+template <>
+struct VariantInitializer<Color> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Color>(v); }
+};
+
+template <>
+struct VariantInitializer<StringName> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string_name(v); }
+};
+
+template <>
+struct VariantInitializer<NodePath> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_node_path(v); }
+};
+
+template <>
+struct VariantInitializer<RID> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<RID>(v); }
+};
+
+template <>
+struct VariantInitializer<Callable> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_callable(v); }
+};
+
+template <>
+struct VariantInitializer<Signal> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_signal(v); }
+};
+
+template <>
+struct VariantInitializer<Dictionary> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_dictionary(v); }
+};
+
+template <>
+struct VariantInitializer<Array> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedByteArray> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_byte_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedInt32Array> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_int32_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedInt64Array> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_int64_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedFloat32Array> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_float32_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedFloat64Array> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_float64_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedStringArray> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedVector2Array> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_vector2_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedVector3Array> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_vector3_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedColorArray> {
+	static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_color_array(v); }
+};
+
+template <class T>
+struct VariantTypeChanger {
+	static _FORCE_INLINE_ void change(Variant *v) {
+		if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer
+			VariantInternal::clear(v);
+			VariantInitializer<T>::init(v);
+		}
+	}
+};
+
 #endif // VARIANT_INTERNAL_H

+ 64 - 9
core/variant/variant_op.cpp

@@ -44,6 +44,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) + *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -64,6 +65,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) - *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -84,6 +86,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) * *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -104,6 +107,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<A>::get_ptr(left)->xform(*VariantGetInternalPtr<B>::get_ptr(right));
 	}
 #ifdef PTRCALL_ENABLED
@@ -124,6 +128,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<B>::get_ptr(right)->xform_inv(*VariantGetInternalPtr<A>::get_ptr(left));
 	}
 #ifdef PTRCALL_ENABLED
@@ -144,6 +149,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -169,6 +175,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -189,6 +196,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -214,6 +222,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -233,6 +242,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = -*VariantGetInternalPtr<A>::get_ptr(left);
 	}
 #ifdef PTRCALL_ENABLED
@@ -252,6 +262,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left);
 	}
 #ifdef PTRCALL_ENABLED
@@ -272,6 +283,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) << *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -292,6 +304,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >> *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -312,6 +325,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) | *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -352,6 +366,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) ^ *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -371,6 +386,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<R>::change(r_ret);
 		*VariantGetInternalPtr<R>::get_ptr(r_ret) = ~*VariantGetInternalPtr<A>::get_ptr(left);
 	}
 #ifdef PTRCALL_ENABLED
@@ -391,6 +407,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) == *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -412,6 +429,7 @@ public:
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const Object *a = left->get_validated_object();
 		const Object *b = right->get_validated_object();
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == b;
 	}
 #ifdef PTRCALL_ENABLED
@@ -431,6 +449,7 @@ public:
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const Object *a = left->get_validated_object();
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == nullptr;
 	}
 #ifdef PTRCALL_ENABLED
@@ -450,6 +469,7 @@ public:
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const Object *b = right->get_validated_object();
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr == b;
 	}
 #ifdef PTRCALL_ENABLED
@@ -470,6 +490,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) != *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -491,6 +512,7 @@ public:
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		Object *a = left->get_validated_object();
 		Object *b = right->get_validated_object();
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != b;
 	}
 #ifdef PTRCALL_ENABLED
@@ -510,6 +532,7 @@ public:
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		Object *a = left->get_validated_object();
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != nullptr;
 	}
 #ifdef PTRCALL_ENABLED
@@ -529,6 +552,7 @@ public:
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		Object *b = right->get_validated_object();
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr != b;
 	}
 #ifdef PTRCALL_ENABLED
@@ -549,6 +573,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) < *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -569,6 +594,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) <= *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -589,6 +615,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) > *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -609,6 +636,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >= *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -629,6 +657,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) && *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -650,6 +679,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) || *VariantGetInternalPtr<B>::get_ptr(right);
 	}
 #ifdef PTRCALL_ENABLED
@@ -675,6 +705,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = xor_op(*VariantGetInternalPtr<A>::get_ptr(left), *VariantGetInternalPtr<B>::get_ptr(right));
 	}
 #ifdef PTRCALL_ENABLED
@@ -695,6 +726,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<A>::get_ptr(left);
 	}
 #ifdef PTRCALL_ENABLED
@@ -729,6 +761,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<Array>::change(r_ret);
 		_add_arrays(*VariantGetInternalPtr<Array>::get_ptr(r_ret), *VariantGetInternalPtr<Array>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right));
 	}
 #ifdef PTRCALL_ENABLED
@@ -754,6 +787,7 @@ public:
 		r_valid = true;
 	}
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<Vector<T>>::change(r_ret);
 		*VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector<T>>::get_ptr(left);
 		VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret)->append_array(*VariantGetInternalPtr<Vector<T>>::get_ptr(right));
 	}
@@ -787,6 +821,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<String>::change(r_ret);
 		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), nullptr);
 	}
 #ifdef PTRCALL_ENABLED
@@ -813,6 +848,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<String>::change(r_ret);
 		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), nullptr);
 	}
 #ifdef PTRCALL_ENABLED
@@ -842,6 +878,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<String>::change(r_ret);
 		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), right->get_validated_object(), nullptr);
 	}
 #ifdef PTRCALL_ENABLED
@@ -871,6 +908,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<String>::change(r_ret);
 		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), nullptr);
 	}
 #ifdef PTRCALL_ENABLED
@@ -890,6 +928,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = true;
 	}
 #ifdef PTRCALL_ENABLED
@@ -909,6 +948,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = false;
 	}
 #ifdef PTRCALL_ENABLED
@@ -962,6 +1002,7 @@ _FORCE_INLINE_ static bool _operate_get_object(const Variant *p_ptr) {
 		}                                                                                                                    \
                                                                                                                              \
 		static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {                          \
+			VariantTypeChanger<bool>::change(r_ret);                                                                         \
 			*VariantGetInternalPtr<bool>::get_ptr(r_ret) = m_op(_operate_get_##m_left(left), _operate_get_##m_right(right)); \
 		}                                                                                                                    \
                                                                                                                              \
@@ -1002,6 +1043,7 @@ _FORCE_INLINE_ static bool _operate_get_ptr_object(const void *p_ptr) {
 		}                                                                                                                    \
                                                                                                                              \
 		static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {                          \
+			VariantTypeChanger<bool>::change(r_ret);                                                                         \
 			*VariantGetInternalPtr<bool>::get_ptr(r_ret) = m_op(_operate_get_##m_left(left), _operate_get_##m_right(right)); \
 		}                                                                                                                    \
                                                                                                                              \
@@ -1168,6 +1210,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<bool>::get_ptr(left);
 	}
 #ifdef PTRCALL_ENABLED
@@ -1187,6 +1230,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<int64_t>::get_ptr(left);
 	}
 #ifdef PTRCALL_ENABLED
@@ -1206,6 +1250,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<double>::get_ptr(left);
 	}
 #ifdef PTRCALL_ENABLED
@@ -1225,6 +1270,7 @@ public:
 	}
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = left->get_validated_object() == nullptr;
 	}
 #ifdef PTRCALL_ENABLED
@@ -1251,6 +1297,7 @@ public:
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left);
 		const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1;
 	}
 #ifdef PTRCALL_ENABLED
@@ -1275,6 +1322,7 @@ public:
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const A &a = *VariantGetInternalPtr<A>::get_ptr(left);
 		const B &b = *VariantGetInternalPtr<B>::get_ptr(right);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(a) != -1;
 	}
 #ifdef PTRCALL_ENABLED
@@ -1295,6 +1343,7 @@ public:
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(Variant()) != -1;
 	}
 #ifdef PTRCALL_ENABLED
@@ -1315,6 +1364,7 @@ public:
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(*left) != -1;
 	}
 #ifdef PTRCALL_ENABLED
@@ -1339,6 +1389,7 @@ public:
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
 		const A &a = *VariantGetInternalPtr<A>::get_ptr(left);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(a);
 	}
 #ifdef PTRCALL_ENABLED
@@ -1360,6 +1411,7 @@ public:
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(Variant());
 	}
 #ifdef PTRCALL_ENABLED
@@ -1381,6 +1433,7 @@ public:
 
 	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
 		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(*left);
 	}
 #ifdef PTRCALL_ENABLED
@@ -1414,6 +1467,7 @@ public:
 
 		bool valid;
 		l->get(a, &valid);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid;
 	}
 #ifdef PTRCALL_ENABLED
@@ -1449,6 +1503,7 @@ public:
 
 		bool valid;
 		l->get(a, &valid);
+		VariantTypeChanger<bool>::change(r_ret);
 		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid;
 	}
 #ifdef PTRCALL_ENABLED
@@ -1480,7 +1535,7 @@ void register_op(Variant::Operator p_op, Variant::Type p_type_a, Variant::Type p
 #endif
 }
 
-void register_variant_operators() {
+void Variant::_register_variant_operators() {
 	zeromem(operator_return_type_table, sizeof(operator_return_type_table));
 	zeromem(operator_evaluator_table, sizeof(operator_evaluator_table));
 	zeromem(validated_operator_evaluator_table, sizeof(validated_operator_evaluator_table));
@@ -1568,8 +1623,8 @@ void register_variant_operators() {
 	register_op<OperatorEvaluatorMul<Transform, Transform, Transform>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::TRANSFORM);
 	register_op<OperatorEvaluatorXForm<Vector3, Transform, Vector3>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::VECTOR3);
 	register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Transform>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::TRANSFORM);
-	register_op<OperatorEvaluatorXForm<AABB, Transform, AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::AABB);
-	register_op<OperatorEvaluatorXFormInv<AABB, AABB, Transform>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM);
+	register_op<OperatorEvaluatorXForm<::AABB, Transform, ::AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::AABB);
+	register_op<OperatorEvaluatorXFormInv<::AABB, ::AABB, Transform>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM);
 	register_op<OperatorEvaluatorXForm<Vector<Vector3>, Transform, Vector<Vector3>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::PACKED_VECTOR3_ARRAY);
 	register_op<OperatorEvaluatorXFormInv<Vector<Vector3>, Vector<Vector3>, Transform>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR3_ARRAY, Variant::TRANSFORM);
 
@@ -1645,7 +1700,7 @@ void register_variant_operators() {
 	register_op<OperatorEvaluatorStringModT<Transform2D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM2D);
 	register_op<OperatorEvaluatorStringModT<Plane>>(Variant::OP_MODULE, Variant::STRING, Variant::PLANE);
 	register_op<OperatorEvaluatorStringModT<Quat>>(Variant::OP_MODULE, Variant::STRING, Variant::QUAT);
-	register_op<OperatorEvaluatorStringModT<AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB);
+	register_op<OperatorEvaluatorStringModT<::AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB);
 	register_op<OperatorEvaluatorStringModT<Basis>>(Variant::OP_MODULE, Variant::STRING, Variant::BASIS);
 	register_op<OperatorEvaluatorStringModT<Transform>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM);
 
@@ -1713,7 +1768,7 @@ void register_variant_operators() {
 	register_op<OperatorEvaluatorEqual<Transform2D, Transform2D>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D);
 	register_op<OperatorEvaluatorEqual<Plane, Plane>>(Variant::OP_EQUAL, Variant::PLANE, Variant::PLANE);
 	register_op<OperatorEvaluatorEqual<Quat, Quat>>(Variant::OP_EQUAL, Variant::QUAT, Variant::QUAT);
-	register_op<OperatorEvaluatorEqual<AABB, AABB>>(Variant::OP_EQUAL, Variant::AABB, Variant::AABB);
+	register_op<OperatorEvaluatorEqual<::AABB, ::AABB>>(Variant::OP_EQUAL, Variant::AABB, Variant::AABB);
 	register_op<OperatorEvaluatorEqual<Basis, Basis>>(Variant::OP_EQUAL, Variant::BASIS, Variant::BASIS);
 	register_op<OperatorEvaluatorEqual<Transform, Transform>>(Variant::OP_EQUAL, Variant::TRANSFORM, Variant::TRANSFORM);
 	register_op<OperatorEvaluatorEqual<Color, Color>>(Variant::OP_EQUAL, Variant::COLOR, Variant::COLOR);
@@ -1759,7 +1814,7 @@ void register_variant_operators() {
 	register_op<OperatorEvaluatorNotEqual<Transform2D, Transform2D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D);
 	register_op<OperatorEvaluatorNotEqual<Plane, Plane>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::PLANE);
 	register_op<OperatorEvaluatorNotEqual<Quat, Quat>>(Variant::OP_NOT_EQUAL, Variant::QUAT, Variant::QUAT);
-	register_op<OperatorEvaluatorNotEqual<AABB, AABB>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::AABB);
+	register_op<OperatorEvaluatorNotEqual<::AABB, ::AABB>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::AABB);
 	register_op<OperatorEvaluatorNotEqual<Basis, Basis>>(Variant::OP_NOT_EQUAL, Variant::BASIS, Variant::BASIS);
 	register_op<OperatorEvaluatorNotEqual<Transform, Transform>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM, Variant::TRANSFORM);
 	register_op<OperatorEvaluatorNotEqual<Color, Color>>(Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::COLOR);
@@ -1948,7 +2003,7 @@ void register_variant_operators() {
 	register_op<OperatorEvaluatorInDictionaryHas<Transform2D>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::DICTIONARY);
 	register_op<OperatorEvaluatorInDictionaryHas<Plane>>(Variant::OP_IN, Variant::PLANE, Variant::DICTIONARY);
 	register_op<OperatorEvaluatorInDictionaryHas<Quat>>(Variant::OP_IN, Variant::QUAT, Variant::DICTIONARY);
-	register_op<OperatorEvaluatorInDictionaryHas<AABB>>(Variant::OP_IN, Variant::AABB, Variant::DICTIONARY);
+	register_op<OperatorEvaluatorInDictionaryHas<::AABB>>(Variant::OP_IN, Variant::AABB, Variant::DICTIONARY);
 	register_op<OperatorEvaluatorInDictionaryHas<Basis>>(Variant::OP_IN, Variant::BASIS, Variant::DICTIONARY);
 	register_op<OperatorEvaluatorInDictionaryHas<Transform>>(Variant::OP_IN, Variant::TRANSFORM, Variant::DICTIONARY);
 
@@ -1985,7 +2040,7 @@ void register_variant_operators() {
 	register_op<OperatorEvaluatorInArrayFind<Transform2D, Array>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::ARRAY);
 	register_op<OperatorEvaluatorInArrayFind<Plane, Array>>(Variant::OP_IN, Variant::PLANE, Variant::ARRAY);
 	register_op<OperatorEvaluatorInArrayFind<Quat, Array>>(Variant::OP_IN, Variant::QUAT, Variant::ARRAY);
-	register_op<OperatorEvaluatorInArrayFind<AABB, Array>>(Variant::OP_IN, Variant::AABB, Variant::ARRAY);
+	register_op<OperatorEvaluatorInArrayFind<::AABB, Array>>(Variant::OP_IN, Variant::AABB, Variant::ARRAY);
 	register_op<OperatorEvaluatorInArrayFind<Basis, Array>>(Variant::OP_IN, Variant::BASIS, Variant::ARRAY);
 	register_op<OperatorEvaluatorInArrayFind<Transform, Array>>(Variant::OP_IN, Variant::TRANSFORM, Variant::ARRAY);
 
@@ -2034,7 +2089,7 @@ void register_variant_operators() {
 	register_op<OperatorEvaluatorObjectHasPropertyStringName>(Variant::OP_IN, Variant::STRING_NAME, Variant::OBJECT);
 }
 
-void unregister_variant_operators() {
+void Variant::_unregister_variant_operators() {
 }
 
 void Variant::evaluate(const Operator &p_op, const Variant &p_a,

+ 2 - 2
core/variant/variant_setget.cpp

@@ -2576,12 +2576,12 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
 	}
 }
 
-void register_variant_setters_getters() {
+void Variant::_register_variant_setters_getters() {
 	register_named_setters_getters();
 	register_indexed_setters_getters();
 	register_keyed_setters_getters();
 }
-void unregister_variant_setters_getters() {
+void Variant::_unregister_variant_setters_getters() {
 	unregister_named_setters_getters();
 	unregister_indexed_setters_getters();
 }

+ 6 - 5
editor/animation_track_editor.cpp

@@ -228,9 +228,9 @@ public:
 							if (Variant::can_convert(args[idx].get_type(), t)) {
 								Variant old = args[idx];
 								Variant *ptrs[1] = { &old };
-								args.write[idx] = Variant::construct(t, (const Variant **)ptrs, 1, err);
+								Variant::construct(t, args.write[idx], (const Variant **)ptrs, 1, err);
 							} else {
-								args.write[idx] = Variant::construct(t, nullptr, 0, err);
+								Variant::construct(t, args.write[idx], nullptr, 0, err);
 							}
 							change_notify_deserved = true;
 							d_new["args"] = args;
@@ -846,9 +846,9 @@ public:
 									if (Variant::can_convert(args[idx].get_type(), t)) {
 										Variant old = args[idx];
 										Variant *ptrs[1] = { &old };
-										args.write[idx] = Variant::construct(t, (const Variant **)ptrs, 1, err);
+										Variant::construct(t, args.write[idx], (const Variant **)ptrs, 1, err);
 									} else {
-										args.write[idx] = Variant::construct(t, nullptr, 0, err);
+										Variant::construct(t, args.write[idx], nullptr, 0, err);
 									}
 									change_notify_deserved = true;
 									d_new["args"] = args;
@@ -4587,7 +4587,8 @@ void AnimationTrackEditor::_add_method_key(const String &p_method) {
 					params.push_back(arg);
 				} else {
 					Callable::CallError ce;
-					Variant arg = Variant::construct(E->get().arguments[i].type, nullptr, 0, ce);
+					Variant arg;
+					Variant::construct(E->get().arguments[i].type, arg, nullptr, 0, ce);
 					params.push_back(arg);
 				}
 			}

+ 4 - 3
editor/array_property_edit.cpp

@@ -43,7 +43,7 @@ Variant ArrayPropertyEdit::get_array() const {
 	Variant arr = o->get(property);
 	if (!arr.is_array()) {
 		Callable::CallError ce;
-		arr = Variant::construct(default_type, nullptr, 0, ce);
+		Variant::construct(default_type, arr, nullptr, 0, ce);
 	}
 	return arr;
 }
@@ -107,7 +107,7 @@ bool ArrayPropertyEdit::_set(const StringName &p_name, const Variant &p_value) {
 					new_type = arr.get(size - 1).get_type();
 				}
 				if (new_type != Variant::NIL) {
-					init = Variant::construct(new_type, nullptr, 0, ce);
+					Variant::construct(new_type, init, nullptr, 0, ce);
 					for (int i = size; i < newsize; i++) {
 						ur->add_do_method(this, "_set_value", i, init);
 					}
@@ -136,7 +136,8 @@ bool ArrayPropertyEdit::_set(const StringName &p_name, const Variant &p_value) {
 			Variant value = arr.get(idx);
 			if (value.get_type() != type && type >= 0 && type < Variant::VARIANT_MAX) {
 				Callable::CallError ce;
-				Variant new_value = Variant::construct(Variant::Type(type), nullptr, 0, ce);
+				Variant new_value;
+				Variant::construct(Variant::Type(type), new_value, nullptr, 0, ce);
 				UndoRedo *ur = EditorNode::get_undo_redo();
 
 				ur->create_action(TTR("Change Array Value Type"));

+ 2 - 1
editor/doc_data.cpp

@@ -561,7 +561,8 @@ void DocData::generate(bool p_basic_types) {
 		c.name = cname;
 
 		Callable::CallError cerror;
-		Variant v = Variant::construct(Variant::Type(i), nullptr, 0, cerror);
+		Variant v;
+		Variant::construct(Variant::Type(i), v, nullptr, 0, cerror);
 
 		List<MethodInfo> method_list;
 		v.get_method_list(&method_list);

+ 1 - 1
editor/editor_inspector.cpp

@@ -2278,7 +2278,7 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
 			for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
 				if (E->get().name == p_path) {
 					Callable::CallError ce;
-					to_create = Variant::construct(E->get().type, nullptr, 0, ce);
+					Variant::construct(E->get().type, to_create, nullptr, 0, ce);
 					break;
 				}
 			}

+ 12 - 8
editor/editor_properties_array_dict.cpp

@@ -186,7 +186,7 @@ void EditorPropertyArray::_change_type_menu(int p_index) {
 
 	Variant value;
 	Callable::CallError ce;
-	value = Variant::construct(Variant::Type(p_index), nullptr, 0, ce);
+	Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
 	Variant array = object->get_array();
 	array.set(changing_type_idx, value);
 
@@ -445,7 +445,7 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d
 		// Handle the case where array is not initialised yet
 		if (!array.is_array()) {
 			Callable::CallError ce;
-			array = Variant::construct(array_type, nullptr, 0, ce);
+			Variant::construct(array_type, array, nullptr, 0, ce);
 		}
 
 		// Loop the file array and add to existing array
@@ -491,7 +491,7 @@ void EditorPropertyArray::_edit_pressed() {
 	Variant array = get_edited_object()->get(get_edited_property());
 	if (!array.is_array()) {
 		Callable::CallError ce;
-		array = Variant::construct(array_type, nullptr, 0, ce);
+		Variant::construct(array_type, array, nullptr, 0, ce);
 
 		get_edited_object()->set(get_edited_property(), array);
 	}
@@ -524,7 +524,9 @@ void EditorPropertyArray::_length_changed(double p_page) {
 			for (int i = previous_size; i < size; i++) {
 				if (array.get(i).get_type() == Variant::NIL) {
 					Callable::CallError ce;
-					array.set(i, Variant::construct(subtype, nullptr, 0, ce));
+					Variant r;
+					Variant::construct(subtype, r, nullptr, 0, ce);
+					array.set(i, r);
 				}
 			}
 		}
@@ -534,7 +536,9 @@ void EditorPropertyArray::_length_changed(double p_page) {
 		// Pool*Array don't initialize their elements, have to do it manually
 		for (int i = previous_size; i < size; i++) {
 			Callable::CallError ce;
-			array.set(i, Variant::construct(array.get(i).get_type(), nullptr, 0, ce));
+			Variant r;
+			Variant::construct(array.get(i).get_type(), r, nullptr, 0, ce);
+			array.set(i, r);
 		}
 	}
 
@@ -657,7 +661,7 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
 	if (changing_type_idx < 0) {
 		Variant value;
 		Callable::CallError ce;
-		value = Variant::construct(Variant::Type(p_index), nullptr, 0, ce);
+		Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
 		if (changing_type_idx == -1) {
 			object->set_new_item_key(value);
 		} else {
@@ -672,7 +676,7 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
 	if (p_index < Variant::VARIANT_MAX) {
 		Variant value;
 		Callable::CallError ce;
-		value = Variant::construct(Variant::Type(p_index), nullptr, 0, ce);
+		Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce);
 		Variant key = dict.get_key_at_index(changing_type_idx);
 		dict[key] = value;
 	} else {
@@ -1044,7 +1048,7 @@ void EditorPropertyDictionary::_edit_pressed() {
 	Variant prop_val = get_edited_object()->get(get_edited_property());
 	if (prop_val.get_type() == Variant::NIL) {
 		Callable::CallError ce;
-		prop_val = Variant::construct(Variant::DICTIONARY, nullptr, 0, ce);
+		Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
 		get_edited_object()->set(get_edited_property(), prop_val);
 	}
 

+ 2 - 1
editor/project_settings_editor.cpp

@@ -98,7 +98,8 @@ void ProjectSettingsEditor::_add_setting() {
 	// Initialize the property with the default value for the given type.
 	// The type list starts at 1 (as we exclude Nil), so add 1 to the selected value.
 	Callable::CallError ce;
-	const Variant value = Variant::construct(Variant::Type(type->get_selected() + 1), nullptr, 0, ce);
+	Variant value;
+	Variant::construct(Variant::Type(type->get_selected() + 1), value, nullptr, 0, ce);
 
 	undo_redo->create_action(TTR("Add Project Setting"));
 	undo_redo->add_do_property(ps, setting, value);

+ 2 - 2
editor/property_selector.cpp

@@ -95,7 +95,7 @@ void PropertySelector::_update_search() {
 		} else if (type != Variant::NIL) {
 			Variant v;
 			Callable::CallError ce;
-			v = Variant::construct(type, nullptr, 0, ce);
+			Variant::construct(type, v, nullptr, 0, ce);
 
 			v.get_property_list(&props);
 		} else {
@@ -200,7 +200,7 @@ void PropertySelector::_update_search() {
 		if (type != Variant::NIL) {
 			Variant v;
 			Callable::CallError ce;
-			v = Variant::construct(type, nullptr, 0, ce);
+			Variant::construct(type, v, nullptr, 0, ce);
 			v.get_method_list(&methods);
 		} else {
 			Object *obj = ObjectDB::get_instance(script);

+ 2 - 1
modules/gdscript/gdscript.cpp

@@ -1092,7 +1092,8 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
 					// Try conversion
 					Callable::CallError ce;
 					const Variant *value = &p_value;
-					Variant converted = Variant::construct(member->data_type.builtin_type, &value, 1, ce);
+					Variant converted;
+					Variant::construct(member->data_type.builtin_type, converted, &value, 1, ce);
 					if (ce.error == Callable::CallError::CALL_OK) {
 						members.write[member->index] = converted;
 						return true;

+ 8 - 5
modules/gdscript/gdscript_analyzer.cpp

@@ -1711,7 +1711,8 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
 				}
 
 				Callable::CallError err;
-				Variant value = Variant::construct(builtin_type, (const Variant **)args.ptr(), args.size(), err);
+				Variant value;
+				Variant::construct(builtin_type, value, (const Variant **)args.ptr(), args.size(), err);
 
 				switch (err.error) {
 					case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
@@ -2075,7 +2076,8 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
 				}
 				default: {
 					Callable::CallError temp;
-					Variant dummy = Variant::construct(base.builtin_type, nullptr, 0, temp);
+					Variant dummy;
+					Variant::construct(base.builtin_type, dummy, nullptr, 0, temp);
 					List<PropertyInfo> properties;
 					dummy.get_property_list(&properties);
 					for (const List<PropertyInfo>::Element *E = properties.front(); E != nullptr; E = E->next()) {
@@ -2869,7 +2871,8 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, GD
 	if (p_base_type.kind == GDScriptParser::DataType::BUILTIN) {
 		// Construct a base type to get methods.
 		Callable::CallError err;
-		Variant dummy = Variant::construct(p_base_type.builtin_type, nullptr, 0, err);
+		Variant dummy;
+		Variant::construct(p_base_type.builtin_type, dummy, nullptr, 0, err);
 		if (err.error != Callable::CallError::CALL_OK) {
 			ERR_FAIL_V_MSG(false, "Could not construct base Variant type.");
 		}
@@ -3095,7 +3098,7 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator
 		a = a_ref;
 	} else {
 		Callable::CallError err;
-		a = Variant::construct(a_type, nullptr, 0, err);
+		Variant::construct(a_type, a, nullptr, 0, err);
 		if (err.error != Callable::CallError::CALL_OK) {
 			r_valid = false;
 			ERR_FAIL_V_MSG(result, vformat("Could not construct value of type %s", Variant::get_type_name(a_type)));
@@ -3108,7 +3111,7 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator
 		b = b_ref;
 	} else {
 		Callable::CallError err;
-		b = Variant::construct(b_type, nullptr, 0, err);
+		Variant::construct(b_type, b, nullptr, 0, err);
 		if (err.error != Callable::CallError::CALL_OK) {
 			r_valid = false;
 			ERR_FAIL_V_MSG(result, vformat("Could not construct value of type %s", Variant::get_type_name(b_type)));

+ 17 - 8
modules/gdscript/gdscript_editor.cpp

@@ -973,7 +973,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
 			} break;
 			case GDScriptParser::DataType::BUILTIN: {
 				Callable::CallError err;
-				Variant tmp = Variant::construct(base_type.builtin_type, nullptr, 0, err);
+				Variant tmp;
+				Variant::construct(base_type.builtin_type, tmp, nullptr, 0, err);
 				if (err.error != Callable::CallError::CALL_OK) {
 					return;
 				}
@@ -1523,7 +1524,8 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
 						found = _guess_identifier_type_from_base(c, base, id, r_type);
 					} else if (!found && index.type.kind == GDScriptParser::DataType::BUILTIN) {
 						Callable::CallError err;
-						Variant base_val = Variant::construct(base.type.builtin_type, nullptr, 0, err);
+						Variant base_val;
+						Variant::construct(base.type.builtin_type, base_val, nullptr, 0, err);
 						bool valid = false;
 						Variant res = base_val.get(index.value, &valid);
 						if (valid) {
@@ -1560,9 +1562,14 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
 
 				Callable::CallError ce;
 				bool v1_use_value = p1.value.get_type() != Variant::NIL && p1.value.get_type() != Variant::OBJECT;
-				Variant v1 = (v1_use_value) ? p1.value : Variant::construct(p1.type.builtin_type, nullptr, 0, ce);
+				Variant d1;
+				Variant::construct(p1.type.builtin_type, d1, nullptr, 0, ce);
+				Variant d2;
+				Variant::construct(p2.type.builtin_type, d2, nullptr, 0, ce);
+
+				Variant v1 = (v1_use_value) ? p1.value : d1;
 				bool v2_use_value = p2.value.get_type() != Variant::NIL && p2.value.get_type() != Variant::OBJECT;
-				Variant v2 = (v2_use_value) ? p2.value : Variant::construct(p2.type.builtin_type, nullptr, 0, ce);
+				Variant v2 = (v2_use_value) ? p2.value : d2;
 				// avoid potential invalid ops
 				if ((op->variant_op == Variant::OP_DIVIDE || op->variant_op == Variant::OP_MODULE) && v2.get_type() == Variant::INT) {
 					v2 = 1;
@@ -1952,7 +1959,8 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
 			} break;
 			case GDScriptParser::DataType::BUILTIN: {
 				Callable::CallError err;
-				Variant tmp = Variant::construct(base_type.builtin_type, nullptr, 0, err);
+				Variant tmp;
+				Variant::construct(base_type.builtin_type, tmp, nullptr, 0, err);
 
 				if (err.error != Callable::CallError::CALL_OK) {
 					return false;
@@ -2102,7 +2110,8 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex
 			} break;
 			case GDScriptParser::DataType::BUILTIN: {
 				Callable::CallError err;
-				Variant tmp = Variant::construct(base_type.builtin_type, nullptr, 0, err);
+				Variant tmp;
+				Variant::construct(base_type.builtin_type, tmp, nullptr, 0, err);
 				if (err.error != Callable::CallError::CALL_OK) {
 					return false;
 				}
@@ -2257,7 +2266,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 			case GDScriptParser::DataType::BUILTIN: {
 				if (base.get_type() == Variant::NIL) {
 					Callable::CallError err;
-					base = Variant::construct(base_type.builtin_type, nullptr, 0, err);
+					Variant::construct(base_type.builtin_type, base, nullptr, 0, err);
 					if (err.error != Callable::CallError::CALL_OK) {
 						return;
 					}
@@ -2883,7 +2892,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
 					v = v_ref;
 				} else {
 					Callable::CallError err;
-					v = Variant::construct(base_type.builtin_type, NULL, 0, err);
+					Variant::construct(base_type.builtin_type, v, NULL, 0, err);
 					if (err.error != Callable::CallError::CALL_OK) {
 						break;
 					}

+ 5 - 4
modules/gdscript/gdscript_function.cpp

@@ -331,7 +331,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 						return Variant();
 					}
 					if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
-						Variant arg = Variant::construct(argument_types[i].builtin_type, &p_args[i], 1, r_err);
+						Variant arg;
+						Variant::construct(argument_types[i].builtin_type, arg, &p_args[i], 1, r_err);
 						memnew_placement(&stack[i], Variant(arg));
 					} else {
 						memnew_placement(&stack[i], Variant(*p_args[i]));
@@ -755,7 +756,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 					if (Variant::can_convert_strict(src->get_type(), var_type)) {
 #endif // DEBUG_ENABLED
 						Callable::CallError ce;
-						*dst = Variant::construct(var_type, const_cast<const Variant **>(&src), 1, ce);
+						Variant::construct(var_type, *dst, const_cast<const Variant **>(&src), 1, ce);
 					} else {
 #ifdef DEBUG_ENABLED
 						err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) +
@@ -857,7 +858,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				GD_ERR_BREAK(to_type < 0 || to_type >= Variant::VARIANT_MAX);
 
 				Callable::CallError err;
-				*dst = Variant::construct(to_type, (const Variant **)&src, 1, err);
+				Variant::construct(to_type, *dst, (const Variant **)&src, 1, err);
 
 #ifdef DEBUG_ENABLED
 				if (err.error != Callable::CallError::CALL_OK) {
@@ -955,7 +956,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 				GET_VARIANT_PTR(dst, 3 + argc);
 				Callable::CallError err;
-				*dst = Variant::construct(t, (const Variant **)argptrs, argc, err);
+				Variant::construct(t, *dst, (const Variant **)argptrs, argc, err);
 
 #ifdef DEBUG_ENABLED
 				if (err.error != Callable::CallError::CALL_OK) {

+ 1 - 1
modules/gdscript/gdscript_functions.cpp

@@ -599,7 +599,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
 				return;
 
 			} else {
-				r_ret = Variant::construct(Variant::Type(type), p_args, 1, r_error);
+				Variant::construct(Variant::Type(type), r_ret, p_args, 1, r_error);
 			}
 		} break;
 		case TYPE_OF: {

+ 6 - 2
modules/gdscript/gdscript_parser.cpp

@@ -2802,7 +2802,9 @@ bool GDScriptParser::validate_annotation_arguments(AnnotationNode *p_annotation)
 					Callable::CallError error;
 					Vector<Variant> args = varray(string->name);
 					const Variant *name = args.ptr();
-					p_annotation->resolved_arguments.push_back(Variant::construct(parameter.type, &(name), 1, error));
+					Variant r;
+					Variant::construct(parameter.type, r, &(name), 1, error);
+					p_annotation->resolved_arguments.push_back(r);
 					if (error.error != Callable::CallError::CALL_OK) {
 						push_error(vformat(R"(Expected %s as argument %d of annotation "%s").)", Variant::get_type_name(parameter.type), i + 1, p_annotation->name));
 						p_annotation->resolved_arguments.remove(p_annotation->resolved_arguments.size() - 1);
@@ -2824,7 +2826,9 @@ bool GDScriptParser::validate_annotation_arguments(AnnotationNode *p_annotation)
 				}
 				Callable::CallError error;
 				const Variant *args = &value;
-				p_annotation->resolved_arguments.push_back(Variant::construct(parameter.type, &(args), 1, error));
+				Variant r;
+				Variant::construct(parameter.type, r, &(args), 1, error);
+				p_annotation->resolved_arguments.push_back(r);
 				if (error.error != Callable::CallError::CALL_OK) {
 					push_error(vformat(R"(Expected %s as argument %d of annotation "%s").)", Variant::get_type_name(parameter.type), i + 1, p_annotation->name));
 					p_annotation->resolved_arguments.remove(p_annotation->resolved_arguments.size() - 1);

+ 2 - 2
modules/visual_script/visual_script.cpp

@@ -84,10 +84,10 @@ void VisualScriptNode::validate_input_default_values() {
 			Callable::CallError ce;
 			Variant existing = default_input_values[i];
 			const Variant *existingp = &existing;
-			default_input_values[i] = Variant::construct(expected, &existingp, 1, ce, false);
+			Variant::construct(expected, default_input_values[i], &existingp, 1, ce);
 			if (ce.error != Callable::CallError::CALL_OK) {
 				//could not convert? force..
-				default_input_values[i] = Variant::construct(expected, nullptr, 0, ce, false);
+				Variant::construct(expected, default_input_values[i], nullptr, 0, ce);
 			}
 		}
 	}

+ 1 - 1
modules/visual_script/visual_script_builtin_funcs.cpp

@@ -1027,7 +1027,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
 				return;
 
 			} else {
-				*r_return = Variant::construct(Variant::Type(type), p_inputs, 1, r_error);
+				Variant::construct(Variant::Type(type), *r_return, p_inputs, 1, r_error);
 			}
 		} break;
 		case VisualScriptBuiltinFunc::TYPE_OF: {

+ 7 - 4
modules/visual_script/visual_script_editor.cpp

@@ -885,7 +885,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
 							//not the same, reconvert
 							Callable::CallError ce;
 							const Variant *existingp = &value;
-							value = Variant::construct(left_type, &existingp, 1, ce, false);
+							Variant::construct(left_type, value, &existingp, 1, ce);
 						}
 
 						if (left_type == Variant::COLOR) {
@@ -1173,7 +1173,9 @@ String VisualScriptEditor::_sanitized_variant_text(const StringName &property_na
 	if (script->get_variable_info(property_name).type != Variant::NIL) {
 		Callable::CallError ce;
 		const Variant *converted = &var;
-		var = Variant::construct(script->get_variable_info(property_name).type, &converted, 1, ce, false);
+		Variant n;
+		Variant::construct(script->get_variable_info(property_name).type, n, &converted, 1, ce);
+		var = n;
 	}
 
 	return String(var);
@@ -3959,8 +3961,9 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i
 	Variant existing = vsn->get_default_input_value(p_input_port);
 	if (pinfo.type != Variant::NIL && existing.get_type() != pinfo.type) {
 		Callable::CallError ce;
-		const Variant *existingp = &existing;
-		existing = Variant::construct(pinfo.type, &existingp, 1, ce, false);
+		Variant e = existing;
+		const Variant *existingp = &e;
+		Variant::construct(pinfo.type, existing, &existingp, 1, ce);
 	}
 
 	default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_global_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y));

+ 1 - 1
modules/visual_script/visual_script_expression.cpp

@@ -1405,7 +1405,7 @@ public:
 					argp.write[i] = &arr[i];
 				}
 
-				r_ret = Variant::construct(constructor->data_type, (const Variant **)argp.ptr(), argp.size(), ce);
+				Variant::construct(constructor->data_type, r_ret, (const Variant **)argp.ptr(), argp.size(), ce);
 
 				if (ce.error != Callable::CallError::CALL_OK) {
 					r_error_str = "Invalid arguments to construct '" + Variant::get_type_name(constructor->data_type) + "'.";

+ 9 - 6
modules/visual_script/visual_script_func_nodes.cpp

@@ -976,7 +976,7 @@ void VisualScriptPropertySet::_adjust_input_index(PropertyInfo &pinfo) const {
 	if (index != StringName()) {
 		Variant v;
 		Callable::CallError ce;
-		v = Variant::construct(pinfo.type, nullptr, 0, ce);
+		Variant::construct(pinfo.type, v, nullptr, 0, ce);
 		Variant i = v.get(index);
 		pinfo.type = i.get_type();
 	}
@@ -1117,7 +1117,7 @@ void VisualScriptPropertySet::_update_cache() {
 
 		Variant v;
 		Callable::CallError ce;
-		v = Variant::construct(basic_type, nullptr, 0, ce);
+		Variant::construct(basic_type, v, nullptr, 0, ce);
 
 		List<PropertyInfo> pinfo;
 		v.get_property_list(&pinfo);
@@ -1336,7 +1336,8 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const {
 
 	if (property.name == "index") {
 		Callable::CallError ce;
-		Variant v = Variant::construct(type_cache.type, nullptr, 0, ce);
+		Variant v;
+		Variant::construct(type_cache.type, v, nullptr, 0, ce);
 		List<PropertyInfo> plist;
 		v.get_property_list(&plist);
 		String options = "";
@@ -1786,7 +1787,7 @@ void VisualScriptPropertyGet::_update_cache() {
 
 		Variant v;
 		Callable::CallError ce;
-		v = Variant::construct(basic_type, nullptr, 0, ce);
+		Variant::construct(basic_type, v, nullptr, 0, ce);
 
 		List<PropertyInfo> pinfo;
 		v.get_property_list(&pinfo);
@@ -2012,7 +2013,8 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const {
 
 	if (property.name == "index") {
 		Callable::CallError ce;
-		Variant v = Variant::construct(type_cache, nullptr, 0, ce);
+		Variant v;
+		Variant::construct(type_cache, v, nullptr, 0, ce);
 		List<PropertyInfo> plist;
 		v.get_property_list(&plist);
 		String options = "";
@@ -2368,7 +2370,8 @@ void register_visual_script_func_nodes() {
 		Variant::Type t = Variant::Type(i);
 		String type_name = Variant::get_type_name(t);
 		Callable::CallError ce;
-		Variant vt = Variant::construct(t, nullptr, 0, ce);
+		Variant vt;
+		Variant::construct(t, vt, nullptr, 0, ce);
 		List<MethodInfo> ml;
 		vt.get_method_list(&ml);
 

+ 3 - 3
modules/visual_script/visual_script_nodes.cpp

@@ -1431,7 +1431,7 @@ void VisualScriptConstant::set_constant_type(Variant::Type p_type) {
 
 	type = p_type;
 	Callable::CallError ce;
-	value = Variant::construct(type, nullptr, 0, ce);
+	Variant::construct(type, value, nullptr, 0, ce);
 	ports_changed_notify();
 	_change_notify();
 }
@@ -3255,7 +3255,7 @@ public:
 
 	virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) {
 		Callable::CallError ce;
-		*p_outputs[0] = Variant::construct(type, p_inputs, argcount, ce);
+		Variant::construct(type, *p_outputs[0], p_inputs, argcount, ce);
 		if (ce.error != Callable::CallError::CALL_OK) {
 			r_error_str = "Invalid arguments for constructor";
 		}
@@ -3727,7 +3727,7 @@ void VisualScriptDeconstruct::_update_elements() {
 	elements.clear();
 	Variant v;
 	Callable::CallError ce;
-	v = Variant::construct(type, nullptr, 0, ce);
+	Variant::construct(type, v, nullptr, 0, ce);
 
 	List<PropertyInfo> pinfo;
 	v.get_property_list(&pinfo);

+ 1 - 1
modules/visual_script/visual_script_property_selector.cpp

@@ -196,7 +196,7 @@ void VisualScriptPropertySelector::_update_search() {
 			if (type != Variant::NIL) {
 				Variant v;
 				Callable::CallError ce;
-				v = Variant::construct(type, nullptr, 0, ce);
+				Variant::construct(type, v, nullptr, 0, ce);
 				v.get_method_list(&methods);
 			} else {
 				Object *obj = ObjectDB::get_instance(script);

+ 1 - 1
scene/main/shader_globals_override.cpp

@@ -202,7 +202,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
 			Override o;
 			o.in_use = false;
 			Callable::CallError ce;
-			o.override = Variant::construct(pinfo.type, nullptr, 0, ce);
+			Variant::construct(pinfo.type, o.override, nullptr, 0, ce);
 			overrides[variables[i]] = o;
 		}