summaryrefslogtreecommitdiff
path: root/core/variant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/variant.cpp')
-rw-r--r--core/variant.cpp149
1 files changed, 133 insertions, 16 deletions
diff --git a/core/variant.cpp b/core/variant.cpp
index b849a83cb4..cdc9e47fc8 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -128,6 +128,14 @@ String Variant::get_type_name(Variant::Type p_type) {
return "Object";
} break;
+ case CALLABLE: {
+
+ return "Callable";
+ } break;
+ case SIGNAL: {
+
+ return "Signal";
+ } break;
case NODE_PATH: {
return "NodePath";
@@ -792,6 +800,14 @@ bool Variant::is_zero() const {
return _get_obj().obj == NULL;
} break;
+ case CALLABLE: {
+
+ return reinterpret_cast<const Callable *>(_data._mem)->is_null();
+ } break;
+ case SIGNAL: {
+
+ return reinterpret_cast<const Signal *>(_data._mem)->is_null();
+ } break;
case NODE_PATH: {
return reinterpret_cast<const NodePath *>(_data._mem)->is_empty();
@@ -1022,6 +1038,14 @@ void Variant::reference(const Variant &p_variant) {
_get_obj().id = p_variant._get_obj().id;
} break;
+ case CALLABLE: {
+
+ memnew_placement(_data._mem, Callable(*reinterpret_cast<const Callable *>(p_variant._data._mem)));
+ } break;
+ case SIGNAL: {
+
+ memnew_placement(_data._mem, Signal(*reinterpret_cast<const Signal *>(p_variant._data._mem)));
+ } break;
case NODE_PATH: {
memnew_placement(_data._mem, NodePath(*reinterpret_cast<const NodePath *>(p_variant._data._mem)));
@@ -1149,6 +1173,14 @@ void Variant::clear() {
// not much need probably
reinterpret_cast<RID *>(_data._mem)->~RID();
} break;
+ case CALLABLE: {
+
+ reinterpret_cast<Callable *>(_data._mem)->~Callable();
+ } break;
+ case SIGNAL: {
+
+ reinterpret_cast<Signal *>(_data._mem)->~Signal();
+ } break;
case DICTIONARY: {
reinterpret_cast<Dictionary *>(_data._mem)->~Dictionary();
@@ -1627,6 +1659,18 @@ String Variant::stringify(List<const void *> &stack) const {
return "[Object:null]";
} break;
+ case CALLABLE: {
+ const Callable &c = *reinterpret_cast<const Callable *>(_data._mem);
+ return c;
+ } break;
+ case SIGNAL: {
+ const Signal &s = *reinterpret_cast<const Signal *>(_data._mem);
+ return s;
+ } break;
+ case _RID: {
+ const RID &s = *reinterpret_cast<const RID *>(_data._mem);
+ return "RID(" + itos(s.get_id()) + ")";
+ } break;
default: {
return "[" + get_type_name(type) + "]";
}
@@ -1776,9 +1820,9 @@ Variant::operator RID() const {
ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, RID(), "Invalid pointer (object was freed).");
};
#endif
- Variant::CallError ce;
+ Callable::CallError ce;
Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid, NULL, 0, ce);
- if (ce.error == Variant::CallError::CALL_OK && ret.get_type() == Variant::_RID) {
+ if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::_RID) {
return ret;
}
return RID();
@@ -1836,6 +1880,22 @@ Variant::operator Dictionary() const {
return Dictionary();
}
+Variant::operator Callable() const {
+
+ if (type == CALLABLE)
+ return *reinterpret_cast<const Callable *>(_data._mem);
+ else
+ return Callable();
+}
+
+Variant::operator Signal() const {
+
+ if (type == SIGNAL)
+ return *reinterpret_cast<const Signal *>(_data._mem);
+ else
+ return Signal();
+}
+
template <class DA, class SA>
inline DA _convert_array(const SA &p_array) {
@@ -2243,6 +2303,17 @@ Variant::Variant(const Object *p_object) {
}
}
+Variant::Variant(const Callable &p_callable) {
+
+ type = CALLABLE;
+ memnew_placement(_data._mem, Callable(p_callable));
+}
+Variant::Variant(const Signal &p_callable) {
+
+ type = SIGNAL;
+ memnew_placement(_data._mem, Signal(p_callable));
+}
+
Variant::Variant(const Dictionary &p_dictionary) {
type = DICTIONARY;
@@ -2469,6 +2540,15 @@ void Variant::operator=(const Variant &p_variant) {
_get_obj().id = p_variant._get_obj().id;
} break;
+ case CALLABLE: {
+
+ *reinterpret_cast<Callable *>(_data._mem) = *reinterpret_cast<const Callable *>(p_variant._data._mem);
+ } break;
+ case SIGNAL: {
+
+ *reinterpret_cast<Signal *>(_data._mem) = *reinterpret_cast<const Signal *>(p_variant._data._mem);
+ } break;
+
case NODE_PATH: {
*reinterpret_cast<NodePath *>(_data._mem) = *reinterpret_cast<const NodePath *>(p_variant._data._mem);
@@ -2676,6 +2756,17 @@ uint32_t Variant::hash() const {
return reinterpret_cast<const Dictionary *>(_data._mem)->hash();
} break;
+ case CALLABLE: {
+
+ return reinterpret_cast<const Callable *>(_data._mem)->hash();
+
+ } break;
+ case SIGNAL: {
+
+ const Signal &s = *reinterpret_cast<const Signal *>(_data._mem);
+ uint32_t hash = s.get_name().hash();
+ return hash_djb2_one_64(s.get_object_id(), hash);
+ } break;
case ARRAY: {
const Array &arr = *reinterpret_cast<const Array *>(_data._mem);
@@ -3054,24 +3145,24 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) {
argc++;
}
- CallError error;
+ Callable::CallError error;
Variant ret = call(p_method, argptr, argc, error);
switch (error.error) {
- case CallError::CALL_ERROR_INVALID_ARGUMENT: {
+ case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
- String err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(error.expected) + "'.";
+ String err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(Variant::Type(error.expected)) + "'.";
ERR_PRINT(err.utf8().get_data());
} break;
- case CallError::CALL_ERROR_INVALID_METHOD: {
+ case Callable::CallError::CALL_ERROR_INVALID_METHOD: {
String err = "Invalid method '" + p_method + "' for type '" + Variant::get_type_name(type) + "'.";
ERR_PRINT(err.utf8().get_data());
} break;
- case CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
+ case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
String err = "Too many arguments for method '" + p_method + "'";
ERR_PRINT(err.utf8().get_data());
@@ -3096,26 +3187,26 @@ String Variant::get_construct_string() const {
return vars;
}
-String Variant::get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Variant::CallError &ce) {
+String Variant::get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {
String err_text;
- if (ce.error == Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
+ if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
int errorarg = ce.argument;
if (p_argptrs) {
- err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(ce.expected) + ".";
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
} else {
- err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(ce.expected) + ".";
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
}
- } else if (ce.error == Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
+ } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
- } else if (ce.error == Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
+ } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
- } else if (ce.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) {
+ } else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
err_text = "Method not found.";
- } else if (ce.error == Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
+ } else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
err_text = "Instance is null";
- } else if (ce.error == Variant::CallError::CALL_OK) {
+ } else if (ce.error == Callable::CallError::CALL_OK) {
return "Call OK";
}
@@ -3128,6 +3219,32 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method,
return "'" + class_name + "::" + String(p_method) + "': " + err_text;
}
+String Variant::get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {
+
+ String err_text;
+
+ if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
+ int errorarg = ce.argument;
+ if (p_argptrs) {
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ } else {
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ }
+ } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
+ err_text = "Method not found.";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
+ err_text = "Instance is null";
+ } else if (ce.error == Callable::CallError::CALL_OK) {
+ return "Call OK";
+ }
+
+ return String(p_callable) + " : " + err_text;
+}
+
String vformat(const String &p_text, const Variant &p1, const Variant &p2, const Variant &p3, const Variant &p4, const Variant &p5) {
Array args;