diff options
-rw-r--r-- | core/math/audio_frame.h | 12 | ||||
-rw-r--r-- | core/math/vector2.h | 35 | ||||
-rw-r--r-- | core/math/vector2i.h | 10 | ||||
-rw-r--r-- | core/math/vector3.h | 3 | ||||
-rw-r--r-- | core/math/vector3i.h | 10 | ||||
-rw-r--r-- | core/variant/variant_op.cpp | 132 | ||||
-rw-r--r-- | doc/classes/Vector2i.xml | 10 | ||||
-rw-r--r-- | doc/classes/Vector3i.xml | 10 | ||||
-rw-r--r-- | doc/classes/float.xml | 12 | ||||
-rw-r--r-- | editor/plugins/text_control_editor_plugin.cpp | 457 | ||||
-rw-r--r-- | editor/plugins/text_control_editor_plugin.h | 5 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.cpp | 4 |
12 files changed, 511 insertions, 189 deletions
diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h index 94fc3de2b1..8b244e9fe4 100644 --- a/core/math/audio_frame.h +++ b/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 diff --git a/core/math/vector2.h b/core/math/vector2.h index 9edaaebf89..123e3dc7b6 100644 --- a/core/math/vector2.h +++ b/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; diff --git a/core/math/vector2i.h b/core/math/vector2i.h index 446e05f5dd..707c8c9490 100644 --- a/core/math/vector2i.h +++ b/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; } diff --git a/core/math/vector3.h b/core/math/vector3.h index 79ba5c4f15..345329f7f3 100644 --- a/core/math/vector3.h +++ b/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; } diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 1564ee9173..d166de80aa 100644 --- a/core/math/vector3i.h +++ b/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; 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<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); diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml index 721c73d603..d7e010cc53 100644 --- a/doc/classes/Vector2i.xml +++ b/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] diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml index da729e1ec2..8a901fdf37 100644 --- a/doc/classes/Vector3i.xml +++ b/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] diff --git a/doc/classes/float.xml b/doc/classes/float.xml index 9effe9d5bf..2dae7275b5 100644 --- a/doc/classes/float.xml +++ b/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> diff --git a/editor/plugins/text_control_editor_plugin.cpp b/editor/plugins/text_control_editor_plugin.cpp index a51b5d3e03..87eff9c3e9 100644 --- a/editor/plugins/text_control_editor_plugin.cpp +++ b/editor/plugins/text_control_editor_plugin.cpp @@ -31,6 +31,7 @@ #include "text_control_editor_plugin.h" #include "editor/editor_scale.h" +#include "editor/multi_node_edit.h" void TextControlEditor::_notification(int p_notification) { switch (p_notification) { @@ -121,78 +122,162 @@ void TextControlEditor::_update_styles_menu() { } void TextControlEditor::_update_control() { - if (edited_control) { - // Get override names. - if (edited_control->is_class("RichTextLabel")) { - edited_color = "default_color"; - edited_font = "normal_font"; - edited_font_size = "normal_font_size"; - } else { - edited_color = "font_color"; - edited_font = "font"; - edited_font_size = "font_size"; - } - - // Get font override. - Ref<Font> font; - if (edited_control->has_theme_font_override(edited_font)) { - font = edited_control->get_theme_font(edited_font); - } - if (font.is_valid()) { - if (font->get_data_count() != 1) { - // Composite font, save it to "custom_font" to allow undoing font change. - custom_font = font; - _update_fonts_menu(); - font_list->select(FONT_INFO_USER_CUSTOM); - _update_styles_menu(); - font_style_list->select(0); + if (!edited_controls.is_empty()) { + int font_selected = 0; + bool same_font = true; + int style_selected = 0; + bool same_style = true; + int font_size = 0; + bool same_font_size = true; + int outline_size = 0; + bool same_outline_size = true; + Color font_color = Color{ 1.0f, 1.0f, 1.0f }; + bool same_font_color = true; + Color outline_color = Color{ 1.0f, 1.0f, 1.0f }; + bool same_outline_color = true; + + _update_fonts_menu(); + _update_styles_menu(); + + int count = edited_controls.size(); + for (int i = 0; i < count; ++i) { + Control *edited_control = edited_controls[i]; + + String edited_color; + String edited_font; + String edited_font_size; + + // Get override names. + if (edited_control->is_class("RichTextLabel")) { + edited_color = "default_color"; + edited_font = "normal_font"; + edited_font_size = "normal_font_size"; } else { - // Single face font, search for the font with matching name and style. - String name = font->get_data(0)->get_font_name(); - String style = font->get_data(0)->get_font_style_name(); - if (fonts.has(name) && fonts[name].has(style)) { - _update_fonts_menu(); - for (int i = 0; i < font_list->get_item_count(); i++) { - if (font_list->get_item_text(i) == name) { - font_list->select(i); - break; - } + edited_color = "font_color"; + edited_font = "font"; + edited_font_size = "font_size"; + } + + // Get font override. + Ref<Font> font; + if (edited_control->has_theme_font_override(edited_font)) { + font = edited_control->get_theme_font(edited_font); + } + + if (font.is_valid()) { + if (font->get_data_count() != 1) { + custom_font = font; + if (i > 0) { + same_font = same_font && (font_selected == FONT_INFO_USER_CUSTOM); + same_style = same_style && (style_selected == 0); } - _update_styles_menu(); - for (int i = 0; i < font_style_list->get_item_count(); i++) { - if (font_style_list->get_item_text(i) == style) { - font_style_list->select(i); - break; + + font_selected = FONT_INFO_USER_CUSTOM; + style_selected = 0; + } else { + String name = font->get_data(0)->get_font_name(); + String style = font->get_data(0)->get_font_style_name(); + if (fonts.has(name) && fonts[name].has(style)) { + for (int j = 0; j < font_list->get_item_count(); j++) { + if (font_list->get_item_text(j) == name) { + if (i > 0) { + same_font = same_font && (j == font_selected); + } + + font_selected = j; + break; + } } + for (int j = 0; j < font_style_list->get_item_count(); j++) { + if (font_style_list->get_item_text(j) == style) { + if (i > 0) { + same_style = same_style && (j == style_selected); + } + + style_selected = j; + break; + } + } + } else { + custom_font = font; + if (i > 0) { + same_font = same_font && (font_selected == FONT_INFO_USER_CUSTOM); + same_style = same_style && (style_selected == 0); + } + + font_selected = FONT_INFO_USER_CUSTOM; + style_selected = 0; } - } else { - // Unknown font, save it to "custom_font" to allow undoing font change. - custom_font = font; - _update_fonts_menu(); - font_list->select(FONT_INFO_USER_CUSTOM); - _update_styles_menu(); - font_style_list->select(0); } + } else { + if (i > 0) { + same_font = same_font && (font_selected == FONT_INFO_THEME_DEFAULT); + same_style = same_style && (style_selected == 0); + } + + font_selected = FONT_INFO_THEME_DEFAULT; + style_selected = 0; } + + int current_font_size = edited_control->get_theme_font_size(edited_font_size); + int current_outline_size = edited_control->get_theme_constant("outline_size"); + Color current_font_color = edited_control->get_theme_color(edited_color); + Color current_outline_color = edited_control->get_theme_color("font_outline_color"); + if (i > 0) { + same_font_size = same_font_size && (font_size == current_font_size); + same_outline_size = same_outline_size && (outline_size == current_outline_size); + same_font_color = same_font_color && (font_color == current_font_color); + same_outline_color = same_outline_color && (outline_color == current_outline_color); + } + + font_size = current_font_size; + outline_size = current_outline_size; + font_color = current_font_color; + outline_color = current_outline_color; + } + + _update_fonts_menu(); + if (same_font) { + font_list->select(font_selected); + } else { + font_list->select(-1); + } + + _update_styles_menu(); + if (same_style) { + font_style_list->select(style_selected); } else { - // No font override, select "Theme Default". - _update_fonts_menu(); - font_list->select(FONT_INFO_THEME_DEFAULT); - _update_styles_menu(); - font_style_list->select(0); + font_list->select(-1); } // Get other theme overrides. font_size_list->set_block_signals(true); - font_size_list->set_value(edited_control->get_theme_font_size(edited_font_size)); + if (same_font_size) { + font_size_list->get_line_edit()->set_text(String::num_uint64(font_size)); + font_size_list->set_value(font_size); + } else { + font_size_list->get_line_edit()->set_text(""); + } font_size_list->set_block_signals(false); outline_size_list->set_block_signals(true); - outline_size_list->set_value(edited_control->get_theme_constant("outline_size")); + if (same_outline_size) { + outline_size_list->get_line_edit()->set_text(String::num_uint64(outline_size)); + outline_size_list->set_value(outline_size); + } else { + outline_size_list->get_line_edit()->set_text(""); + } outline_size_list->set_block_signals(false); - font_color_picker->set_pick_color(edited_control->get_theme_color(edited_color)); - outline_color_picker->set_pick_color(edited_control->get_theme_color("font_outline_color")); + if (!same_font_color) { + font_color = Color{ 1.0f, 1.0f, 1.0f }; + } + font_color_picker->set_pick_color(font_color); + + if (!same_outline_color) { + outline_color = Color{ 1.0f, 1.0f, 1.0f }; + } + outline_color_picker->set_pick_color(outline_color); } } @@ -205,42 +290,54 @@ void TextControlEditor::_font_style_selected(int p_id) { } void TextControlEditor::_set_font() { - if (!edited_control) { + if (edited_controls.is_empty()) { return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Set Font")); - if (font_list->get_selected_id() == FONT_INFO_THEME_DEFAULT) { - // Remove font override. - ur->add_do_method(edited_control, "remove_theme_font_override", edited_font); - } else if (font_list->get_selected_id() == FONT_INFO_USER_CUSTOM) { - // Restore "custom_font". - ur->add_do_method(edited_control, "add_theme_font_override", edited_font, custom_font); - } else { - // Load new font resource using selected name and style. - String name = font_list->get_item_text(font_list->get_selected()); - String style = font_style_list->get_item_text(font_style_list->get_selected()); - if (style.is_empty()) { - style = "Default"; + int count = edited_controls.size(); + for (int i = 0; i < count; ++i) { + Control *edited_control = edited_controls[i]; + + String edited_font; + if (edited_control->is_class("RichTextLabel")) { + edited_font = "normal_font"; + } else { + edited_font = "font"; } - if (fonts.has(name)) { - Ref<FontData> fd = ResourceLoader::load(fonts[name][style]); - if (fd.is_valid()) { - Ref<Font> font; - font.instantiate(); - font->add_data(fd); - ur->add_do_method(edited_control, "add_theme_font_override", edited_font, font); + if (font_list->get_selected_id() == FONT_INFO_THEME_DEFAULT) { + // Remove font override. + ur->add_do_method(edited_control, "remove_theme_font_override", edited_font); + } else if (font_list->get_selected_id() == FONT_INFO_USER_CUSTOM) { + // Restore "custom_font". + ur->add_do_method(edited_control, "add_theme_font_override", edited_font, custom_font); + } else { + // Load new font resource using selected name and style. + String name = font_list->get_item_text(font_list->get_selected()); + String style = font_style_list->get_item_text(font_style_list->get_selected()); + if (style.is_empty()) { + style = "Default"; + } + + if (fonts.has(name)) { + Ref<FontData> fd = ResourceLoader::load(fonts[name][style]); + if (fd.is_valid()) { + Ref<Font> font; + font.instantiate(); + font->add_data(fd); + ur->add_do_method(edited_control, "add_theme_font_override", edited_font, font); + } } } - } - if (edited_control->has_theme_font_override(edited_font)) { - ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font)); - } else { - ur->add_undo_method(edited_control, "remove_theme_font_override", edited_font); + if (edited_control->has_theme_font_override(edited_font)) { + ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font)); + } else { + ur->add_undo_method(edited_control, "remove_theme_font_override", edited_font); + } } ur->add_do_method(this, "_update_control"); @@ -250,18 +347,30 @@ void TextControlEditor::_set_font() { } void TextControlEditor::_font_size_selected(double p_size) { - if (!edited_control) { + if (edited_controls.is_empty()) { return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Set Font Size")); - ur->add_do_method(edited_control, "add_theme_font_size_override", edited_font_size, p_size); - if (edited_control->has_theme_font_size_override(edited_font_size)) { - ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size)); - } else { - ur->add_undo_method(edited_control, "remove_theme_font_size_override", edited_font_size); + int count = edited_controls.size(); + for (int i = 0; i < count; ++i) { + Control *edited_control = edited_controls[i]; + + String edited_font_size; + if (edited_control->is_class("RichTextLabel")) { + edited_font_size = "normal_font_size"; + } else { + edited_font_size = "font_size"; + } + + ur->add_do_method(edited_control, "add_theme_font_size_override", edited_font_size, p_size); + if (edited_control->has_theme_font_size_override(edited_font_size)) { + ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size)); + } else { + ur->add_undo_method(edited_control, "remove_theme_font_size_override", edited_font_size); + } } ur->add_do_method(this, "_update_control"); @@ -271,18 +380,23 @@ void TextControlEditor::_font_size_selected(double p_size) { } void TextControlEditor::_outline_size_selected(double p_size) { - if (!edited_control) { + if (edited_controls.is_empty()) { return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Set Font Outline Size")); - ur->add_do_method(edited_control, "add_theme_constant_override", "outline_size", p_size); - if (edited_control->has_theme_constant_override("outline_size")) { - ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant("outline_size")); - } else { - ur->add_undo_method(edited_control, "remove_theme_constant_override", "outline_size"); + int count = edited_controls.size(); + for (int i = 0; i < count; ++i) { + Control *edited_control = edited_controls[i]; + + ur->add_do_method(edited_control, "add_theme_constant_override", "outline_size", p_size); + if (edited_control->has_theme_constant_override("outline_size")) { + ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant("outline_size")); + } else { + ur->add_undo_method(edited_control, "remove_theme_constant_override", "outline_size"); + } } ur->add_do_method(this, "_update_control"); @@ -292,18 +406,30 @@ void TextControlEditor::_outline_size_selected(double p_size) { } void TextControlEditor::_font_color_changed(const Color &p_color) { - if (!edited_control) { + if (edited_controls.is_empty()) { return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Set Font Color"), UndoRedo::MERGE_ENDS); - ur->add_do_method(edited_control, "add_theme_color_override", edited_color, p_color); - if (edited_control->has_theme_color_override(edited_color)) { - ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color)); - } else { - ur->add_undo_method(edited_control, "remove_theme_color_override", edited_color); + int count = edited_controls.size(); + for (int i = 0; i < count; ++i) { + Control *edited_control = edited_controls[i]; + + String edited_color; + if (edited_control->is_class("RichTextLabel")) { + edited_color = "default_color"; + } else { + edited_color = "font_color"; + } + + ur->add_do_method(edited_control, "add_theme_color_override", edited_color, p_color); + if (edited_control->has_theme_color_override(edited_color)) { + ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color)); + } else { + ur->add_undo_method(edited_control, "remove_theme_color_override", edited_color); + } } ur->add_do_method(this, "_update_control"); @@ -313,18 +439,23 @@ void TextControlEditor::_font_color_changed(const Color &p_color) { } void TextControlEditor::_outline_color_changed(const Color &p_color) { - if (!edited_control) { + if (edited_controls.is_empty()) { return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Set Font Outline Color"), UndoRedo::MERGE_ENDS); - ur->add_do_method(edited_control, "add_theme_color_override", "font_outline_color", p_color); - if (edited_control->has_theme_color_override("font_outline_color")) { - ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color("font_outline_color")); - } else { - ur->add_undo_method(edited_control, "remove_theme_color_override", "font_outline_color"); + int count = edited_controls.size(); + for (int i = 0; i < count; ++i) { + Control *edited_control = edited_controls[i]; + + ur->add_do_method(edited_control, "add_theme_color_override", "font_outline_color", p_color); + if (edited_control->has_theme_color_override("font_outline_color")) { + ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color("font_outline_color")); + } else { + ur->add_undo_method(edited_control, "remove_theme_color_override", "font_outline_color"); + } } ur->add_do_method(this, "_update_control"); @@ -334,43 +465,63 @@ void TextControlEditor::_outline_color_changed(const Color &p_color) { } void TextControlEditor::_clear_formatting() { - if (!edited_control) { + if (edited_controls.is_empty()) { return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Clear Control Formatting")); - ur->add_do_method(edited_control, "begin_bulk_theme_override"); - ur->add_undo_method(edited_control, "begin_bulk_theme_override"); + int count = edited_controls.size(); + for (int i = 0; i < count; ++i) { + Control *edited_control = edited_controls[i]; - ur->add_do_method(edited_control, "remove_theme_font_override", edited_font); - if (edited_control->has_theme_font_override(edited_font)) { - ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font)); - } + String edited_color; + String edited_font; + String edited_font_size; - ur->add_do_method(edited_control, "remove_theme_font_size_override", edited_font_size); - if (edited_control->has_theme_font_size_override(edited_font_size)) { - ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size)); - } + // Get override names. + if (edited_control->is_class("RichTextLabel")) { + edited_color = "default_color"; + edited_font = "normal_font"; + edited_font_size = "normal_font_size"; + } else { + edited_color = "font_color"; + edited_font = "font"; + edited_font_size = "font_size"; + } - ur->add_do_method(edited_control, "remove_theme_color_override", edited_color); - if (edited_control->has_theme_color_override(edited_color)) { - ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color)); - } + ur->add_do_method(edited_control, "begin_bulk_theme_override"); + ur->add_undo_method(edited_control, "begin_bulk_theme_override"); - ur->add_do_method(edited_control, "remove_theme_color_override", "font_outline_color"); - if (edited_control->has_theme_color_override("font_outline_color")) { - ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color("font_outline_color")); - } + ur->add_do_method(edited_control, "remove_theme_font_override", edited_font); + if (edited_control->has_theme_font_override(edited_font)) { + ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font)); + } - ur->add_do_method(edited_control, "remove_theme_constant_override", "outline_size"); - if (edited_control->has_theme_constant_override("outline_size")) { - ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant("outline_size")); - } + ur->add_do_method(edited_control, "remove_theme_font_size_override", edited_font_size); + if (edited_control->has_theme_font_size_override(edited_font_size)) { + ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size)); + } + + ur->add_do_method(edited_control, "remove_theme_color_override", edited_color); + if (edited_control->has_theme_color_override(edited_color)) { + ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color)); + } + + ur->add_do_method(edited_control, "remove_theme_color_override", "font_outline_color"); + if (edited_control->has_theme_color_override("font_outline_color")) { + ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color("font_outline_color")); + } + + ur->add_do_method(edited_control, "remove_theme_constant_override", "outline_size"); + if (edited_control->has_theme_constant_override("outline_size")) { + ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant("outline_size")); + } - ur->add_do_method(edited_control, "end_bulk_theme_override"); - ur->add_undo_method(edited_control, "end_bulk_theme_override"); + ur->add_do_method(edited_control, "end_bulk_theme_override"); + ur->add_undo_method(edited_control, "end_bulk_theme_override"); + } ur->add_do_method(this, "_update_control"); ur->add_undo_method(this, "_update_control"); @@ -380,24 +531,54 @@ void TextControlEditor::_clear_formatting() { void TextControlEditor::edit(Object *p_object) { Control *ctrl = Object::cast_to<Control>(p_object); - if (!ctrl) { - edited_control = nullptr; - custom_font = Ref<Font>(); - } else { - edited_control = ctrl; - custom_font = Ref<Font>(); + MultiNodeEdit *multi_node = Object::cast_to<MultiNodeEdit>(p_object); + + edited_controls.clear(); + custom_font = Ref<Font>(); + if (ctrl) { + edited_controls.append(ctrl); + _update_control(); + } else if (multi_node && handles(multi_node)) { + int count = multi_node->get_node_count(); + Node *scene = EditorNode::get_singleton()->get_edited_scene(); + + for (int i = 0; i < count; ++i) { + Control *child = Object::cast_to<Control>(scene->get_node(multi_node->get_node(i))); + edited_controls.append(child); + } _update_control(); } } bool TextControlEditor::handles(Object *p_object) const { Control *ctrl = Object::cast_to<Control>(p_object); - if (!ctrl) { + MultiNodeEdit *multi_node = Object::cast_to<MultiNodeEdit>(p_object); + + if (!ctrl && !multi_node) { return false; - } else { + } else if (ctrl) { bool valid = false; ctrl->get("text", &valid); return valid; + } else { + bool valid = true; + int count = multi_node->get_node_count(); + Node *scene = EditorNode::get_singleton()->get_edited_scene(); + + for (int i = 0; i < count; ++i) { + bool temp_valid = false; + Control *child = Object::cast_to<Control>(scene->get_node(multi_node->get_node(i))); + if (child) { + child->get("text", &temp_valid); + } + valid = valid && temp_valid; + + if (!valid) { + break; + } + } + + return valid; } } diff --git a/editor/plugins/text_control_editor_plugin.h b/editor/plugins/text_control_editor_plugin.h index d284a30f16..5941c100ec 100644 --- a/editor/plugins/text_control_editor_plugin.h +++ b/editor/plugins/text_control_editor_plugin.h @@ -62,10 +62,7 @@ class TextControlEditor : public HBoxContainer { ColorPickerButton *outline_color_picker = nullptr; Button *clear_formatting = nullptr; - Control *edited_control = nullptr; - String edited_color; - String edited_font; - String edited_font_size; + Vector<Control *> edited_controls; Ref<Font> custom_font; protected: diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 844b5616c4..c3b44f348c 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -33,6 +33,7 @@ #ifdef X11_ENABLED #include "core/config/project_settings.h" +#include "core/math/math_funcs.h" #include "core/string/print_string.h" #include "core/string/ustring.h" #include "detect_prime_x11.h" @@ -1098,7 +1099,8 @@ float DisplayServerX11::screen_get_refresh_rate(int p_screen) const { for (int mode = 0; mode < screen_info->nmode; mode++) { XRRModeInfo m_info = screen_info->modes[mode]; if (m_info.id == current_mode) { - return (float)m_info.dotClock / ((float)m_info.hTotal * (float)m_info.vTotal); + // Snap to nearest 0.01 to stay consistent with other platforms. + return Math::snapped((float)m_info.dotClock / ((float)m_info.hTotal * (float)m_info.vTotal), 0.01); } } } |