summaryrefslogtreecommitdiffstats
path: root/core/variant/variant_utility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/variant/variant_utility.cpp')
-rw-r--r--core/variant/variant_utility.cpp260
1 files changed, 219 insertions, 41 deletions
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index b51df89bec..cc48394b64 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -121,16 +121,27 @@ Variant VariantUtilityFunctions::floor(Variant x, Callable::CallError &r_error)
case Variant::VECTOR2: {
return VariantInternalAccessor<Vector2>::get(&x).floor();
} break;
+ case Variant::VECTOR2I: {
+ return VariantInternalAccessor<Vector2i>::get(&x);
+ } break;
case Variant::VECTOR3: {
return VariantInternalAccessor<Vector3>::get(&x).floor();
} break;
+ case Variant::VECTOR3I: {
+ return VariantInternalAccessor<Vector3i>::get(&x);
+ } break;
case Variant::VECTOR4: {
return VariantInternalAccessor<Vector4>::get(&x).floor();
} break;
+ case Variant::VECTOR4I: {
+ return VariantInternalAccessor<Vector4i>::get(&x);
+ } break;
default: {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)";
+ } break;
}
}
@@ -154,16 +165,27 @@ Variant VariantUtilityFunctions::ceil(Variant x, Callable::CallError &r_error) {
case Variant::VECTOR2: {
return VariantInternalAccessor<Vector2>::get(&x).ceil();
} break;
+ case Variant::VECTOR2I: {
+ return VariantInternalAccessor<Vector2i>::get(&x);
+ } break;
case Variant::VECTOR3: {
return VariantInternalAccessor<Vector3>::get(&x).ceil();
} break;
+ case Variant::VECTOR3I: {
+ return VariantInternalAccessor<Vector3i>::get(&x);
+ } break;
case Variant::VECTOR4: {
return VariantInternalAccessor<Vector4>::get(&x).ceil();
} break;
+ case Variant::VECTOR4I: {
+ return VariantInternalAccessor<Vector4i>::get(&x);
+ } break;
default: {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)";
+ } break;
}
}
@@ -187,16 +209,27 @@ Variant VariantUtilityFunctions::round(Variant x, Callable::CallError &r_error)
case Variant::VECTOR2: {
return VariantInternalAccessor<Vector2>::get(&x).round();
} break;
+ case Variant::VECTOR2I: {
+ return VariantInternalAccessor<Vector2i>::get(&x);
+ } break;
case Variant::VECTOR3: {
return VariantInternalAccessor<Vector3>::get(&x).round();
} break;
+ case Variant::VECTOR3I: {
+ return VariantInternalAccessor<Vector3i>::get(&x);
+ } break;
case Variant::VECTOR4: {
return VariantInternalAccessor<Vector4>::get(&x).round();
} break;
+ case Variant::VECTOR4I: {
+ return VariantInternalAccessor<Vector4i>::get(&x);
+ } break;
default: {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)";
+ } break;
}
}
@@ -236,9 +269,11 @@ Variant VariantUtilityFunctions::abs(const Variant &x, Callable::CallError &r_er
return VariantInternalAccessor<Vector4i>::get(&x).abs();
} break;
default: {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)";
+ } break;
}
}
@@ -278,9 +313,11 @@ Variant VariantUtilityFunctions::sign(const Variant &x, Callable::CallError &r_e
return VariantInternalAccessor<Vector4i>::get(&x).sign();
} break;
default: {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)";
+ } break;
}
}
@@ -333,13 +370,40 @@ int VariantUtilityFunctions::step_decimals(float step) {
}
Variant VariantUtilityFunctions::snapped(const Variant &x, const Variant &step, Callable::CallError &r_error) {
- r_error.error = Callable::CallError::CALL_OK;
- if (x.get_type() != step.get_type() && !((x.get_type() == Variant::INT && step.get_type() == Variant::FLOAT) || (x.get_type() == Variant::FLOAT && step.get_type() == Variant::INT))) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 1;
- return Variant();
+ switch (x.get_type()) {
+ case Variant::INT:
+ case Variant::FLOAT:
+ case Variant::VECTOR2:
+ case Variant::VECTOR2I:
+ case Variant::VECTOR3:
+ case Variant::VECTOR3I:
+ case Variant::VECTOR4:
+ case Variant::VECTOR4I:
+ break;
+ default:
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ return R"(Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".)";
+ }
+
+ if (x.get_type() != step.get_type()) {
+ if (x.get_type() == Variant::INT || x.get_type() == Variant::FLOAT) {
+ if (step.get_type() != Variant::INT && step.get_type() != Variant::FLOAT) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::NIL;
+ return R"(Argument "step" must be "int" or "float".)";
+ }
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = x.get_type();
+ return Variant();
+ }
}
+ r_error.error = Callable::CallError::CALL_OK;
switch (step.get_type()) {
case Variant::INT: {
return snappedi(x, VariantInternalAccessor<int64_t>::get(&step));
@@ -366,9 +430,8 @@ Variant VariantUtilityFunctions::snapped(const Variant &x, const Variant &step,
return VariantInternalAccessor<Vector4i>::get(&x).snapped(VariantInternalAccessor<Vector4i>::get(&step));
} break;
default: {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
+ return Variant(); // Already handled.
+ } break;
}
}
@@ -381,14 +444,31 @@ int64_t VariantUtilityFunctions::snappedi(double x, int64_t step) {
}
Variant VariantUtilityFunctions::lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error) {
- r_error.error = Callable::CallError::CALL_OK;
+ switch (from.get_type()) {
+ case Variant::INT:
+ case Variant::FLOAT:
+ case Variant::VECTOR2:
+ case Variant::VECTOR3:
+ case Variant::VECTOR4:
+ case Variant::QUATERNION:
+ case Variant::BASIS:
+ case Variant::COLOR:
+ break;
+ default:
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ return R"(Argument "from" must be "int", "float", "Vector2", "Vector3", "Vector4", "Quaternion", "Basis, or "Color".)";
+ }
+
if (from.get_type() != to.get_type()) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.expected = from.get_type();
r_error.argument = 1;
+ r_error.expected = from.get_type();
return Variant();
}
+ r_error.error = Callable::CallError::CALL_OK;
switch (from.get_type()) {
case Variant::INT: {
return lerpf(VariantInternalAccessor<int64_t>::get(&from), to, weight);
@@ -415,9 +495,8 @@ Variant VariantUtilityFunctions::lerp(const Variant &from, const Variant &to, do
return VariantInternalAccessor<Color>::get(&from).lerp(VariantInternalAccessor<Color>::get(&to), weight);
} break;
default: {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
+ return Variant(); // Already handled.
+ } break;
}
}
@@ -451,6 +530,10 @@ double VariantUtilityFunctions::bezier_derivative(double p_start, double p_contr
return Math::bezier_derivative(p_start, p_control_1, p_control_2, p_end, p_t);
}
+double VariantUtilityFunctions::angle_difference(double from, double to) {
+ return Math::angle_difference(from, to);
+}
+
double VariantUtilityFunctions::lerp_angle(double from, double to, double weight) {
return Math::lerp_angle(from, to, weight);
}
@@ -471,6 +554,10 @@ double VariantUtilityFunctions::move_toward(double from, double to, double delta
return Math::move_toward(from, to, delta);
}
+double VariantUtilityFunctions::rotate_toward(double from, double to, double delta) {
+ return Math::rotate_toward(from, to, delta);
+}
+
double VariantUtilityFunctions::deg_to_rad(double angle_deg) {
return Math::deg_to_rad(angle_deg);
}
@@ -492,7 +579,7 @@ Variant VariantUtilityFunctions::wrap(const Variant &p_x, const Variant &p_min,
if (x_type != Variant::INT && x_type != Variant::FLOAT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = x_type;
+ r_error.expected = Variant::FLOAT;
return Variant();
}
@@ -558,8 +645,8 @@ Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Cal
Variant::Type arg_type = p_args[i]->get_type();
if (arg_type != Variant::INT && arg_type != Variant::FLOAT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.expected = Variant::FLOAT;
r_error.argument = i;
+ r_error.expected = Variant::FLOAT;
return Variant();
}
if (i == 0) {
@@ -569,8 +656,8 @@ Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Cal
Variant::evaluate(Variant::OP_LESS, base, *p_args[i], ret, valid);
if (!valid) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.expected = base.get_type();
r_error.argument = i;
+ r_error.expected = base.get_type();
return Variant();
}
if (ret.booleanize()) {
@@ -602,8 +689,8 @@ Variant VariantUtilityFunctions::min(const Variant **p_args, int p_argcount, Cal
Variant::Type arg_type = p_args[i]->get_type();
if (arg_type != Variant::INT && arg_type != Variant::FLOAT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.expected = Variant::FLOAT;
r_error.argument = i;
+ r_error.expected = Variant::FLOAT;
return Variant();
}
if (i == 0) {
@@ -613,8 +700,8 @@ Variant VariantUtilityFunctions::min(const Variant **p_args, int p_argcount, Cal
Variant::evaluate(Variant::OP_GREATER, base, *p_args[i], ret, valid);
if (!valid) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.expected = base.get_type();
r_error.argument = i;
+ r_error.expected = base.get_type();
return Variant();
}
if (ret.booleanize()) {
@@ -642,8 +729,8 @@ Variant VariantUtilityFunctions::clamp(const Variant &x, const Variant &min, con
Variant::evaluate(Variant::OP_LESS, value, min, ret, valid);
if (!valid) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.expected = value.get_type();
r_error.argument = 1;
+ r_error.expected = value.get_type();
return Variant();
}
if (ret.booleanize()) {
@@ -652,8 +739,8 @@ Variant VariantUtilityFunctions::clamp(const Variant &x, const Variant &min, con
Variant::evaluate(Variant::OP_GREATER, value, max, ret, valid);
if (!valid) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.expected = value.get_type();
r_error.argument = 2;
+ r_error.expected = value.get_type();
return Variant();
}
if (ret.booleanize()) {
@@ -752,10 +839,94 @@ int64_t VariantUtilityFunctions::_typeof(const Variant &obj) {
return obj.get_type();
}
+Variant VariantUtilityFunctions::type_convert(const Variant &p_variant, const Variant::Type p_type) {
+ switch (p_type) {
+ case Variant::Type::NIL:
+ return Variant();
+ case Variant::Type::BOOL:
+ return p_variant.operator bool();
+ case Variant::Type::INT:
+ return p_variant.operator int64_t();
+ case Variant::Type::FLOAT:
+ return p_variant.operator double();
+ case Variant::Type::STRING:
+ return p_variant.operator String();
+ case Variant::Type::VECTOR2:
+ return p_variant.operator Vector2();
+ case Variant::Type::VECTOR2I:
+ return p_variant.operator Vector2i();
+ case Variant::Type::RECT2:
+ return p_variant.operator Rect2();
+ case Variant::Type::RECT2I:
+ return p_variant.operator Rect2i();
+ case Variant::Type::VECTOR3:
+ return p_variant.operator Vector3();
+ case Variant::Type::VECTOR3I:
+ return p_variant.operator Vector3i();
+ case Variant::Type::TRANSFORM2D:
+ return p_variant.operator Transform2D();
+ case Variant::Type::VECTOR4:
+ return p_variant.operator Vector4();
+ case Variant::Type::VECTOR4I:
+ return p_variant.operator Vector4i();
+ case Variant::Type::PLANE:
+ return p_variant.operator Plane();
+ case Variant::Type::QUATERNION:
+ return p_variant.operator Quaternion();
+ case Variant::Type::AABB:
+ return p_variant.operator ::AABB();
+ case Variant::Type::BASIS:
+ return p_variant.operator Basis();
+ case Variant::Type::TRANSFORM3D:
+ return p_variant.operator Transform3D();
+ case Variant::Type::PROJECTION:
+ return p_variant.operator Projection();
+ case Variant::Type::COLOR:
+ return p_variant.operator Color();
+ case Variant::Type::STRING_NAME:
+ return p_variant.operator StringName();
+ case Variant::Type::NODE_PATH:
+ return p_variant.operator NodePath();
+ case Variant::Type::RID:
+ return p_variant.operator ::RID();
+ case Variant::Type::OBJECT:
+ return p_variant.operator Object *();
+ case Variant::Type::CALLABLE:
+ return p_variant.operator Callable();
+ case Variant::Type::SIGNAL:
+ return p_variant.operator Signal();
+ case Variant::Type::DICTIONARY:
+ return p_variant.operator Dictionary();
+ case Variant::Type::ARRAY:
+ return p_variant.operator Array();
+ case Variant::Type::PACKED_BYTE_ARRAY:
+ return p_variant.operator PackedByteArray();
+ case Variant::Type::PACKED_INT32_ARRAY:
+ return p_variant.operator PackedInt32Array();
+ case Variant::Type::PACKED_INT64_ARRAY:
+ return p_variant.operator PackedInt64Array();
+ case Variant::Type::PACKED_FLOAT32_ARRAY:
+ return p_variant.operator PackedFloat32Array();
+ case Variant::Type::PACKED_FLOAT64_ARRAY:
+ return p_variant.operator PackedFloat64Array();
+ case Variant::Type::PACKED_STRING_ARRAY:
+ return p_variant.operator PackedStringArray();
+ case Variant::Type::PACKED_VECTOR2_ARRAY:
+ return p_variant.operator PackedVector2Array();
+ case Variant::Type::PACKED_VECTOR3_ARRAY:
+ return p_variant.operator PackedVector3Array();
+ case Variant::Type::PACKED_COLOR_ARRAY:
+ return p_variant.operator PackedColorArray();
+ case Variant::Type::VARIANT_MAX:
+ ERR_PRINT("Invalid type argument to type_convert(), use the TYPE_* constants. Returning the unconverted Variant.");
+ }
+ return p_variant;
+}
+
String VariantUtilityFunctions::str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
if (p_arg_count < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
+ r_error.expected = 1;
return String();
}
String s;
@@ -782,6 +953,11 @@ String VariantUtilityFunctions::error_string(Error error) {
return String(error_names[error]);
}
+String VariantUtilityFunctions::type_string(Variant::Type p_type) {
+ ERR_FAIL_INDEX_V_MSG((int)p_type, (int)Variant::VARIANT_MAX, "<invalid type>", "Invalid type argument to type_string(), use the TYPE_* constants.");
+ return Variant::get_type_name(p_type);
+}
+
void VariantUtilityFunctions::print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
String s;
for (int i = 0; i < p_arg_count; i++) {
@@ -899,7 +1075,7 @@ void VariantUtilityFunctions::printraw(const Variant **p_args, int p_arg_count,
void VariantUtilityFunctions::push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
if (p_arg_count < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
+ r_error.expected = 1;
}
String s;
for (int i = 0; i < p_arg_count; i++) {
@@ -919,7 +1095,7 @@ void VariantUtilityFunctions::push_error(const Variant **p_args, int p_arg_count
void VariantUtilityFunctions::push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
if (p_arg_count < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
+ r_error.expected = 1;
}
String s;
for (int i = 0; i < p_arg_count; i++) {
@@ -1569,12 +1745,14 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(cubic_interpolate_angle_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(bezier_derivative, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(angle_difference, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(remap, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(rotate_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(deg_to_rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(rad_to_deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH);
@@ -1615,8 +1793,10 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDVR(weakref, sarray("obj"), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDR(_typeof, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDR(type_convert, sarray("variant", "type"), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGS(str, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDR(error_string, sarray("error"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDR(type_string, sarray("type"), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(print, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(print_rich, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(printerr, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
@@ -1664,14 +1844,12 @@ void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, co
if (unlikely(!bfi->is_vararg && p_argcount < bfi->argcount)) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 0;
r_error.expected = bfi->argcount;
return;
}
if (unlikely(!bfi->is_vararg && p_argcount > bfi->argcount)) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
- r_error.argument = 0;
r_error.expected = bfi->argcount;
return;
}
@@ -1788,7 +1966,7 @@ bool Variant::is_utility_function_vararg(const StringName &p_name) {
uint32_t Variant::get_utility_function_hash(const StringName &p_name) {
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
- ERR_FAIL_COND_V(!bfi, 0);
+ ERR_FAIL_NULL_V(bfi, 0);
uint32_t hash = hash_murmur3_one_32(bfi->is_vararg);
hash = hash_murmur3_one_32(bfi->returns_value, hash);