Browse Source

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 <op> float returnig float, like with scalars.
reduz 3 years ago
parent
commit
8c7268664d

+ 12 - 0
core/math/audio_frame.h

@@ -140,4 +140,16 @@ struct AudioFrame {
 	_ALWAYS_INLINE_ AudioFrame() {}
 };
 
+_ALWAYS_INLINE_ AudioFrame operator*(float p_scalar, const AudioFrame &p_frame) {
+	return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
+}
+
+_ALWAYS_INLINE_ AudioFrame operator*(int32_t p_scalar, const AudioFrame &p_frame) {
+	return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
+}
+
+_ALWAYS_INLINE_ AudioFrame operator*(int64_t p_scalar, const AudioFrame &p_frame) {
+	return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
+}
+
 #endif // AUDIO_FRAME_H

+ 19 - 16
core/math/vector2.h

@@ -180,22 +180,6 @@ _FORCE_INLINE_ Vector2 Vector2::plane_project(const real_t p_d, const Vector2 &p
 	return p_vec - *this * (dot(p_vec) - p_d);
 }
 
-_FORCE_INLINE_ Vector2 operator*(const float p_scalar, const Vector2 &p_vec) {
-	return p_vec * p_scalar;
-}
-
-_FORCE_INLINE_ Vector2 operator*(const double p_scalar, const Vector2 &p_vec) {
-	return p_vec * p_scalar;
-}
-
-_FORCE_INLINE_ Vector2 operator*(const int32_t p_scalar, const Vector2 &p_vec) {
-	return p_vec * p_scalar;
-}
-
-_FORCE_INLINE_ Vector2 operator*(const int64_t p_scalar, const Vector2 &p_vec) {
-	return p_vec * p_scalar;
-}
-
 _FORCE_INLINE_ Vector2 Vector2::operator+(const Vector2 &p_v) const {
 	return Vector2(x + p_v.x, y + p_v.y);
 }
@@ -280,6 +264,25 @@ Vector2 Vector2::direction_to(const Vector2 &p_to) const {
 	return ret;
 }
 
+// Multiplication operators required to workaround issues with LLVM using implicit conversion
+// to Vector2i instead for integers where it should not.
+
+_FORCE_INLINE_ Vector2 operator*(const float p_scalar, const Vector2 &p_vec) {
+	return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2 operator*(const double p_scalar, const Vector2 &p_vec) {
+	return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2 operator*(const int32_t p_scalar, const Vector2 &p_vec) {
+	return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector2 operator*(const int64_t p_scalar, const Vector2 &p_vec) {
+	return p_vec * p_scalar;
+}
+
 typedef Vector2 Size2;
 typedef Vector2 Point2;
 

+ 6 - 4
core/math/vector2i.h

@@ -119,19 +119,21 @@ struct _NO_DISCARD_ Vector2i {
 	}
 };
 
-_FORCE_INLINE_ Vector2i operator*(const int32_t &p_scalar, const Vector2i &p_vector) {
+// Multiplication operators required to workaround issues with LLVM using implicit conversion.
+
+_FORCE_INLINE_ Vector2i operator*(const int32_t p_scalar, const Vector2i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2i operator*(const int64_t &p_scalar, const Vector2i &p_vector) {
+_FORCE_INLINE_ Vector2i operator*(const int64_t p_scalar, const Vector2i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2i operator*(const float &p_scalar, const Vector2i &p_vector) {
+_FORCE_INLINE_ Vector2i operator*(const float p_scalar, const Vector2i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2i operator*(const double &p_scalar, const Vector2i &p_vector) {
+_FORCE_INLINE_ Vector2i operator*(const double p_scalar, const Vector2i &p_vector) {
 	return p_vector * p_scalar;
 }
 

+ 3 - 0
core/math/vector3.h

@@ -343,6 +343,9 @@ Vector3 &Vector3::operator*=(const real_t p_scalar) {
 	return *this;
 }
 
+// Multiplication operators required to workaround issues with LLVM using implicit conversion
+// to Vector2i instead for integers where it should not.
+
 _FORCE_INLINE_ Vector3 operator*(const float p_scalar, const Vector3 &p_vec) {
 	return p_vec * p_scalar;
 }

+ 6 - 4
core/math/vector3i.h

@@ -194,6 +194,12 @@ Vector3i &Vector3i::operator*=(const int32_t p_scalar) {
 	return *this;
 }
 
+Vector3i Vector3i::operator*(const int32_t p_scalar) const {
+	return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar);
+}
+
+// Multiplication operators required to workaround issues with LLVM using implicit conversion.
+
 _FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar, const Vector3i &p_vector) {
 	return p_vector * p_scalar;
 }
@@ -210,10 +216,6 @@ _FORCE_INLINE_ Vector3i operator*(const double p_scalar, const Vector3i &p_vecto
 	return p_vector * p_scalar;
 }
 
-Vector3i Vector3i::operator*(const int32_t p_scalar) const {
-	return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar);
-}
-
 Vector3i &Vector3i::operator/=(const int32_t p_scalar) {
 	x /= p_scalar;
 	y /= p_scalar;

+ 126 - 6
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<Vector2, Vector2i, double> {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Vector2i &a = *VariantGetInternalPtr<Vector2i>::get_ptr(&p_left);
+		const double &b = *VariantGetInternalPtr<double>::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<Vector2>::get_ptr(r_ret) = Vector2(VariantGetInternalPtr<Vector2i>::get_ptr(left)->x, VariantGetInternalPtr<Vector2i>::get_ptr(left)->y) * *VariantGetInternalPtr<double>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<Vector2>::encode(Vector2(PtrToArg<Vector2i>::convert(left).x, PtrToArg<Vector2i>::convert(left).y) * PtrToArg<double>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<Vector2>::VARIANT_TYPE; }
+};
+
+template <>
+class OperatorEvaluatorMul<Vector2, double, Vector2i> {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Vector2i &a = *VariantGetInternalPtr<Vector2i>::get_ptr(&p_right);
+		const double &b = *VariantGetInternalPtr<double>::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<Vector2>::get_ptr(r_ret) = Vector2(VariantGetInternalPtr<Vector2i>::get_ptr(right)->x, VariantGetInternalPtr<Vector2i>::get_ptr(right)->y) * *VariantGetInternalPtr<double>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<Vector2>::encode(Vector2(PtrToArg<Vector2i>::convert(right).x, PtrToArg<Vector2i>::convert(right).y) * PtrToArg<double>::convert(left), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<Vector2>::VARIANT_TYPE; }
+};
+
+template <>
+class OperatorEvaluatorDivNZ<Vector2, Vector2i, double> {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Vector2i &a = *VariantGetInternalPtr<Vector2i>::get_ptr(&p_left);
+		const double &b = *VariantGetInternalPtr<double>::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<Vector2>::get_ptr(r_ret) = Vector2(VariantGetInternalPtr<Vector2i>::get_ptr(left)->x, VariantGetInternalPtr<Vector2i>::get_ptr(left)->y) / *VariantGetInternalPtr<double>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<Vector2>::encode(Vector2(PtrToArg<Vector2i>::convert(left).x, PtrToArg<Vector2i>::convert(left).y) / PtrToArg<double>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<Vector2>::VARIANT_TYPE; }
+};
+
+template <>
+class OperatorEvaluatorMul<Vector3, Vector3i, double> {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Vector3i &a = *VariantGetInternalPtr<Vector3i>::get_ptr(&p_left);
+		const double &b = *VariantGetInternalPtr<double>::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<Vector3>::get_ptr(r_ret) = Vector3(VariantGetInternalPtr<Vector3i>::get_ptr(left)->x, VariantGetInternalPtr<Vector3i>::get_ptr(left)->y, VariantGetInternalPtr<Vector3i>::get_ptr(left)->z) * *VariantGetInternalPtr<double>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<Vector3>::encode(Vector3(PtrToArg<Vector3i>::convert(left).x, PtrToArg<Vector3i>::convert(left).y, PtrToArg<Vector3i>::convert(left).z) * PtrToArg<double>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<Vector3>::VARIANT_TYPE; }
+};
+
+template <>
+class OperatorEvaluatorMul<Vector3, double, Vector3i> {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Vector3i &a = *VariantGetInternalPtr<Vector3i>::get_ptr(&p_right);
+		const double &b = *VariantGetInternalPtr<double>::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<Vector3>::get_ptr(r_ret) = Vector3(VariantGetInternalPtr<Vector3i>::get_ptr(right)->x, VariantGetInternalPtr<Vector3i>::get_ptr(right)->y, VariantGetInternalPtr<Vector3i>::get_ptr(right)->z) * *VariantGetInternalPtr<double>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<Vector3>::encode(Vector3(PtrToArg<Vector3i>::convert(right).x, PtrToArg<Vector3i>::convert(right).y, PtrToArg<Vector3i>::convert(right).z) * PtrToArg<double>::convert(left), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<Vector3>::VARIANT_TYPE; }
+};
+
+template <>
+class OperatorEvaluatorDivNZ<Vector3, Vector3i, double> {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Vector3i &a = *VariantGetInternalPtr<Vector3i>::get_ptr(&p_left);
+		const double &b = *VariantGetInternalPtr<double>::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<Vector3>::get_ptr(r_ret) = Vector3(VariantGetInternalPtr<Vector3i>::get_ptr(left)->x, VariantGetInternalPtr<Vector3i>::get_ptr(left)->y, VariantGetInternalPtr<Vector3i>::get_ptr(left)->z) / *VariantGetInternalPtr<double>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<Vector3>::encode(Vector3(PtrToArg<Vector3i>::convert(left).x, PtrToArg<Vector3i>::convert(left).y, PtrToArg<Vector3i>::convert(left).z) / PtrToArg<double>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<Vector3>::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<OperatorEvaluatorMul<double, double, double>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::FLOAT);
 	register_op<OperatorEvaluatorMul<double, double, int64_t>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::INT);
 	register_op<OperatorEvaluatorMul<Vector2, double, Vector2>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2);
-	register_op<OperatorEvaluatorMul<Vector2i, double, Vector2i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2I);
+	register_op<OperatorEvaluatorMul<Vector2, double, Vector2i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2I);
 	register_op<OperatorEvaluatorMul<Vector3, double, Vector3>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3);
-	register_op<OperatorEvaluatorMul<Vector3i, double, Vector3i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3I);
+	register_op<OperatorEvaluatorMul<Vector3, double, Vector3i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3I);
 
 	register_op<OperatorEvaluatorMul<Vector2, Vector2, Vector2>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::VECTOR2);
 	register_op<OperatorEvaluatorMul<Vector2, Vector2, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::INT);
@@ -104,7 +224,7 @@ void Variant::_register_variant_operators() {
 
 	register_op<OperatorEvaluatorMul<Vector2i, Vector2i, Vector2i>>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::VECTOR2I);
 	register_op<OperatorEvaluatorMul<Vector2i, Vector2i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::INT);
-	register_op<OperatorEvaluatorMul<Vector2i, Vector2i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::FLOAT);
+	register_op<OperatorEvaluatorMul<Vector2, Vector2i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::FLOAT);
 
 	register_op<OperatorEvaluatorMul<Vector3, Vector3, Vector3>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::VECTOR3);
 	register_op<OperatorEvaluatorMul<Vector3, Vector3, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::INT);
@@ -112,7 +232,7 @@ void Variant::_register_variant_operators() {
 
 	register_op<OperatorEvaluatorMul<Vector3i, Vector3i, Vector3i>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::VECTOR3I);
 	register_op<OperatorEvaluatorMul<Vector3i, Vector3i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::INT);
-	register_op<OperatorEvaluatorMul<Vector3i, Vector3i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::FLOAT);
+	register_op<OperatorEvaluatorMul<Vector3, Vector3i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::FLOAT);
 
 	register_op<OperatorEvaluatorMul<Quaternion, Quaternion, Quaternion>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::QUATERNION);
 	register_op<OperatorEvaluatorMul<Quaternion, Quaternion, int64_t>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::INT);
@@ -172,7 +292,7 @@ void Variant::_register_variant_operators() {
 	register_op<OperatorEvaluatorDiv<Vector2, Vector2, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::INT);
 
 	register_op<OperatorEvaluatorDivNZ<Vector2i, Vector2i, Vector2i>>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::VECTOR2I);
-	register_op<OperatorEvaluatorDivNZ<Vector2i, Vector2i, double>>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::FLOAT);
+	register_op<OperatorEvaluatorDivNZ<Vector2, Vector2i, double>>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::FLOAT);
 	register_op<OperatorEvaluatorDivNZ<Vector2i, Vector2i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::INT);
 
 	register_op<OperatorEvaluatorDiv<Vector2, Vector2, Vector2>>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::VECTOR2);
@@ -184,7 +304,7 @@ void Variant::_register_variant_operators() {
 	register_op<OperatorEvaluatorDiv<Vector3, Vector3, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR3, Variant::INT);
 
 	register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, Vector3i>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::VECTOR3I);
-	register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, double>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT);
+	register_op<OperatorEvaluatorDivNZ<Vector3, Vector3i, double>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT);
 	register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::INT);
 
 	register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, double>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::FLOAT);

+ 5 - 5
doc/classes/Vector2i.xml

@@ -174,12 +174,12 @@
 			</description>
 		</operator>
 		<operator name="operator *">
-			<return type="Vector2i" />
+			<return type="Vector2" />
 			<argument index="0" name="right" type="float" />
 			<description>
-				Multiplies each component of the [Vector2i] by the given [float] truncated to an integer.
+				Multiplies each component of the [Vector2i] by the given [float]. Returns a [Vector2].
 				[codeblock]
-				print(Vector2i(10, 20) * 0.9) # Prints "(0, 0)"
+				print(Vector2i(10, 15) * 0.9) # Prints "(9, 13.5)"
 				[/codeblock]
 			</description>
 		</operator>
@@ -221,10 +221,10 @@
 			</description>
 		</operator>
 		<operator name="operator /">
-			<return type="Vector2i" />
+			<return type="Vector2" />
 			<argument index="0" name="right" type="float" />
 			<description>
-				Divides each component of the [Vector2i] by the given [float] truncated to an integer.
+				Divides each component of the [Vector2i] by the given [float]. Returns a [Vector2].
 				[codeblock]
 				print(Vector2i(10, 20) / 2.9) # Prints "(5, 10)"
 				[/codeblock]

+ 5 - 5
doc/classes/Vector3i.xml

@@ -180,12 +180,12 @@
 			</description>
 		</operator>
 		<operator name="operator *">
-			<return type="Vector3i" />
+			<return type="Vector3" />
 			<argument index="0" name="right" type="float" />
 			<description>
-				Multiplies each component of the [Vector3i] by the given [float] truncated to an integer.
+				Multiplies each component of the [Vector3i] by the given [float]. Returns a [Vector3].
 				[codeblock]
-				print(Vector3i(10, 20, 30) * 0.9) # Prints "(0, 0, 0)"
+				print(Vector3i(10, 15, 20) * 0.9) # Prints "(9, 13.5, 18)"
 				[/codeblock]
 			</description>
 		</operator>
@@ -227,10 +227,10 @@
 			</description>
 		</operator>
 		<operator name="operator /">
-			<return type="Vector3i" />
+			<return type="Vector3" />
 			<argument index="0" name="right" type="float" />
 			<description>
-				Divides each component of the [Vector3i] by the given [float] truncated to an integer.
+				Divides each component of the [Vector3i] by the given [float]. Returns a [Vector3].
 				[codeblock]
 				print(Vector3i(10, 20, 30) / 2.9) # Prints "(5, 10, 15)"
 				[/codeblock]

+ 6 - 6
doc/classes/float.xml

@@ -89,12 +89,12 @@
 			</description>
 		</operator>
 		<operator name="operator *">
-			<return type="Vector2i" />
+			<return type="Vector2" />
 			<argument index="0" name="right" type="Vector2i" />
 			<description>
-				Multiplies each component of the [Vector2i] by the given [float] truncated to an integer.
+				Multiplies each component of the [Vector2i] by the given [float]. Returns a [Vector2].
 				[codeblock]
-				print(0.9 * Vector2i(10, 20)) # Prints "(0, 0)"
+				print(0.9 * Vector2i(10, 15)) # Prints "(9, 13.5)"
 				[/codeblock]
 			</description>
 		</operator>
@@ -106,12 +106,12 @@
 			</description>
 		</operator>
 		<operator name="operator *">
-			<return type="Vector3i" />
+			<return type="Vector3" />
 			<argument index="0" name="right" type="Vector3i" />
 			<description>
-				Multiplies each component of the [Vector3i] by the given [float] truncated to an integer.
+				Multiplies each component of the [Vector3i] by the given [float]. Returns a [Vector3].
 				[codeblock]
-				print(0.9 * Vector3i(10, 20, 30)) # Prints "(0, 0, 0)"
+				print(0.9 * Vector3i(10, 15, 20)) # Prints "(9, 13.5, 18)"
 				[/codeblock]
 			</description>
 		</operator>