From 8c7268664da7ef98f802ec90fa2ba17b4d695847 Mon Sep 17 00:00:00 2001 From: reduz Date: Thu, 3 Feb 2022 22:16:58 +0100 Subject: Fix integer vector mul/div operators and bindings. * Vector2i and Vector3i mul/div by a float results in Vector2 and Vector3 respectively. * Create specializations to allow proper bindings. This fixes #44408 and supersedes #44441 and keeps the same rule of int float returnig float, like with scalars. --- core/variant/variant_op.cpp | 132 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 126 insertions(+), 6 deletions(-) (limited to 'core/variant/variant_op.cpp') diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index e0ffcc9d11..f35774204b 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -45,6 +45,126 @@ void register_op(Variant::Operator p_op, Variant::Type p_type_a, Variant::Type p ptr_operator_evaluator_table[p_op][p_type_a][p_type_b] = T::ptr_evaluate; } +// Special cases that can't be done otherwise because of the forced casting to float. + +template <> +class OperatorEvaluatorMul { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector2i &a = *VariantGetInternalPtr::get_ptr(&p_left); + const double &b = *VariantGetInternalPtr::get_ptr(&p_right); + *r_ret = Vector2(a.x, a.y) * b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr::get_ptr(r_ret) = Vector2(VariantGetInternalPtr::get_ptr(left)->x, VariantGetInternalPtr::get_ptr(left)->y) * *VariantGetInternalPtr::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(Vector2(PtrToArg::convert(left).x, PtrToArg::convert(left).y) * PtrToArg::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorMul { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector2i &a = *VariantGetInternalPtr::get_ptr(&p_right); + const double &b = *VariantGetInternalPtr::get_ptr(&p_left); + *r_ret = Vector2(a.x, a.y) * b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr::get_ptr(r_ret) = Vector2(VariantGetInternalPtr::get_ptr(right)->x, VariantGetInternalPtr::get_ptr(right)->y) * *VariantGetInternalPtr::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(Vector2(PtrToArg::convert(right).x, PtrToArg::convert(right).y) * PtrToArg::convert(left), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorDivNZ { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector2i &a = *VariantGetInternalPtr::get_ptr(&p_left); + const double &b = *VariantGetInternalPtr::get_ptr(&p_right); + if (unlikely(b == 0)) { + r_valid = false; + *r_ret = "Division by zero error"; + return; + } + *r_ret = Vector2(a.x, a.y) / b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr::get_ptr(r_ret) = Vector2(VariantGetInternalPtr::get_ptr(left)->x, VariantGetInternalPtr::get_ptr(left)->y) / *VariantGetInternalPtr::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(Vector2(PtrToArg::convert(left).x, PtrToArg::convert(left).y) / PtrToArg::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorMul { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector3i &a = *VariantGetInternalPtr::get_ptr(&p_left); + const double &b = *VariantGetInternalPtr::get_ptr(&p_right); + *r_ret = Vector3(a.x, a.y, a.z) * b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr::get_ptr(r_ret) = Vector3(VariantGetInternalPtr::get_ptr(left)->x, VariantGetInternalPtr::get_ptr(left)->y, VariantGetInternalPtr::get_ptr(left)->z) * *VariantGetInternalPtr::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(Vector3(PtrToArg::convert(left).x, PtrToArg::convert(left).y, PtrToArg::convert(left).z) * PtrToArg::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorMul { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector3i &a = *VariantGetInternalPtr::get_ptr(&p_right); + const double &b = *VariantGetInternalPtr::get_ptr(&p_left); + *r_ret = Vector3(a.x, a.y, a.z) * b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr::get_ptr(r_ret) = Vector3(VariantGetInternalPtr::get_ptr(right)->x, VariantGetInternalPtr::get_ptr(right)->y, VariantGetInternalPtr::get_ptr(right)->z) * *VariantGetInternalPtr::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(Vector3(PtrToArg::convert(right).x, PtrToArg::convert(right).y, PtrToArg::convert(right).z) * PtrToArg::convert(left), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorDivNZ { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector3i &a = *VariantGetInternalPtr::get_ptr(&p_left); + const double &b = *VariantGetInternalPtr::get_ptr(&p_right); + if (unlikely(b == 0)) { + r_valid = false; + *r_ret = "Division by zero error"; + return; + } + *r_ret = Vector3(a.x, a.y, a.z) / b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr::get_ptr(r_ret) = Vector3(VariantGetInternalPtr::get_ptr(left)->x, VariantGetInternalPtr::get_ptr(left)->y, VariantGetInternalPtr::get_ptr(left)->z) / *VariantGetInternalPtr::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(Vector3(PtrToArg::convert(left).x, PtrToArg::convert(left).y, PtrToArg::convert(left).z) / PtrToArg::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + void Variant::_register_variant_operators() { memset(operator_return_type_table, 0, sizeof(operator_return_type_table)); memset(operator_evaluator_table, 0, sizeof(operator_evaluator_table)); @@ -94,9 +214,9 @@ void Variant::_register_variant_operators() { register_op>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::FLOAT); register_op>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::INT); register_op>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2); - register_op>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2I); + register_op>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2I); register_op>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3); - register_op>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3I); + register_op>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3I); register_op>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::VECTOR2); register_op>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::INT); @@ -104,7 +224,7 @@ void Variant::_register_variant_operators() { register_op>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::VECTOR2I); register_op>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::INT); - register_op>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::FLOAT); + register_op>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::FLOAT); register_op>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::VECTOR3); register_op>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::INT); @@ -112,7 +232,7 @@ void Variant::_register_variant_operators() { register_op>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::VECTOR3I); register_op>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::INT); - register_op>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::FLOAT); + register_op>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::FLOAT); register_op>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::QUATERNION); register_op>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::INT); @@ -172,7 +292,7 @@ void Variant::_register_variant_operators() { register_op>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::INT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::VECTOR2I); - register_op>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::FLOAT); + register_op>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::FLOAT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::INT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::VECTOR2); @@ -184,7 +304,7 @@ void Variant::_register_variant_operators() { register_op>(Variant::OP_DIVIDE, Variant::VECTOR3, Variant::INT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::VECTOR3I); - register_op>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT); + register_op>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::INT); register_op>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::FLOAT); -- cgit v1.2.3