diff --git a/Source/Editor/GUI/Input/DoubleValueBox.cs b/Source/Editor/GUI/Input/DoubleValueBox.cs index 181911e31..273bc6d97 100644 --- a/Source/Editor/GUI/Input/DoubleValueBox.cs +++ b/Source/Editor/GUI/Input/DoubleValueBox.cs @@ -1,7 +1,6 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. using System; -using System.Globalization; using FlaxEditor.Utilities; using FlaxEngine; @@ -20,8 +19,8 @@ namespace FlaxEditor.GUI.Input get => _value; set { - value = Mathf.Clamp(value, _min, _max); - if (Math.Abs(_value - value) > Mathf.Epsilon) + value = Mathd.Clamp(value, _min, _max); + if (Math.Abs(_value - value) > Mathd.Epsilon) { // Set value _value = value; @@ -39,7 +38,7 @@ namespace FlaxEditor.GUI.Input get => _min; set { - if (!Mathf.NearEqual(_min, value)) + if (!Mathd.NearEqual(_min, value)) { if (value > _max) throw new ArgumentException(); @@ -56,7 +55,7 @@ namespace FlaxEditor.GUI.Input get => _max; set { - if (!Mathf.NearEqual(_max, value)) + if (!Mathd.NearEqual(_max, value)) { if (value < _min) throw new ArgumentException(); @@ -78,7 +77,7 @@ namespace FlaxEditor.GUI.Input /// The maximum value. /// The slide speed. public DoubleValueBox(double value, float x = 0, float y = 0, float width = 120, double min = double.MinValue, double max = double.MaxValue, float slideSpeed = 1) - : base(Mathf.Clamp(value, min, max), x, y, width, min, max, slideSpeed) + : base(Mathd.Clamp(value, min, max), x, y, width, min, max, slideSpeed) { UpdateText(); } @@ -133,15 +132,7 @@ namespace FlaxEditor.GUI.Input /// protected sealed override void UpdateText() { - string text; - if (double.IsPositiveInfinity(_value) || _value == double.MaxValue) - text = "Infinity"; - else if (double.IsNegativeInfinity(_value) || _value == double.MinValue) - text = "-Infinity"; - else - text = _value.ToString(CultureInfo.InvariantCulture); - - SetText(text); + SetText(Utilities.Utils.FormatFloat(_value)); } /// diff --git a/Source/Editor/GUI/Input/FloatValueBox.cs b/Source/Editor/GUI/Input/FloatValueBox.cs index d079146ad..2f7fa77a5 100644 --- a/Source/Editor/GUI/Input/FloatValueBox.cs +++ b/Source/Editor/GUI/Input/FloatValueBox.cs @@ -140,15 +140,7 @@ namespace FlaxEditor.GUI.Input /// protected sealed override void UpdateText() { - string text; - if (float.IsPositiveInfinity(_value) || _value == float.MaxValue) - text = "Infinity"; - else if (float.IsNegativeInfinity(_value) || _value == float.MinValue) - text = "-Infinity"; - else - text = _value.ToString(CultureInfo.InvariantCulture); - - SetText(text); + SetText(Utilities.Utils.FormatFloat(_value)); } /// @@ -157,7 +149,7 @@ namespace FlaxEditor.GUI.Input try { var value = ShuntingYard.Parse(Text); - Value = (float)Math.Round(value, 5); + Value = (float)value; } catch (Exception ex) { diff --git a/Source/Editor/Utilities/ShuntingYardParser.cs b/Source/Editor/Utilities/ShuntingYardParser.cs index b5563bf29..83994a6d2 100644 --- a/Source/Editor/Utilities/ShuntingYardParser.cs +++ b/Source/Editor/Utilities/ShuntingYardParser.cs @@ -272,8 +272,7 @@ namespace FlaxEditor.Utilities // Operators go on stack, unless last operator on stack has higher precedence case TokenType.Operator: - while (stack.Any() && stack.Peek().Type == TokenType.Operator && - CompareOperators(tok.Value, stack.Peek().Value)) + while (stack.Any() && stack.Peek().Type == TokenType.Operator && CompareOperators(tok.Value, stack.Peek().Value)) { yield return stack.Pop(); } diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index dbdac487b..1960951d5 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -1,6 +1,7 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. using System; +using System.Globalization; using System.Collections.Generic; using System.IO; using System.Reflection; @@ -911,5 +912,98 @@ namespace FlaxEditor.Utilities } return StringUtils.GetPathWithoutExtension(path); } + + /// + /// Formats the floating point value (double precision) into the readable text representation. + /// + /// The value. + /// The text representation. + public static string FormatFloat(float value) + { + if (float.IsPositiveInfinity(value) || value == float.MaxValue) + return "Infinity"; + if (float.IsNegativeInfinity(value) || value == float.MinValue) + return "-Infinity"; + string str = value.ToString("r", CultureInfo.InvariantCulture); + return FormatFloat(str, value < 0); + } + + /// + /// Formats the floating point value (single precision) into the readable text representation. + /// + /// The value. + /// The text representation. + public static string FormatFloat(double value) + { + if (double.IsPositiveInfinity(value) || value == double.MaxValue) + return "Infinity"; + if (double.IsNegativeInfinity(value) || value == double.MinValue) + return "-Infinity"; + string str = value.ToString("r", CultureInfo.InvariantCulture); + return FormatFloat(str, value < 0); + } + + internal static string FormatFloat(string str, bool isNegative) + { + // Reference: https://stackoverflow.com/questions/1546113/double-to-string-conversion-without-scientific-notation + int x = str.IndexOf('E'); + if (x < 0) + return str; + int x1 = x + 1; + string s, exp = str.Substring(x1, str.Length - x1); + int e = int.Parse(exp); + int numDecimals = 0; + if (isNegative) + { + int len = x - 3; + if (e >= 0) + { + if (len > 0) + { + s = str.Substring(0, 2) + str.Substring(3, len); + numDecimals = len; + } + else + s = str.Substring(0, 2); + } + else + { + if (len > 0) + { + s = str.Substring(1, 1) + str.Substring(3, len); + numDecimals = len; + } + else + s = str.Substring(1, 1); + } + } + else + { + int len = x - 2; + if (len > 0) + { + s = str[0] + str.Substring(2, len); + numDecimals = len; + } + else + s = str[0].ToString(); + } + if (e >= 0) + { + e -= numDecimals; + string z = new string('0', e); + s = s + z; + } + else + { + e = -e - 1; + string z = new string('0', e); + if (isNegative) + s = "-0." + z + s; + else + s = "0." + z + s; + } + return s; + } } } diff --git a/Source/Tools/FlaxEngine.Tests/FlaxEngine.Tests.csproj b/Source/Tools/FlaxEngine.Tests/FlaxEngine.Tests.csproj index 9ee085dc4..ede414a44 100644 --- a/Source/Tools/FlaxEngine.Tests/FlaxEngine.Tests.csproj +++ b/Source/Tools/FlaxEngine.Tests/FlaxEngine.Tests.csproj @@ -47,6 +47,7 @@ + diff --git a/Source/Tools/FlaxEngine.Tests/TestEditorUtils.cs b/Source/Tools/FlaxEngine.Tests/TestEditorUtils.cs new file mode 100644 index 000000000..5ff507e34 --- /dev/null +++ b/Source/Tools/FlaxEngine.Tests/TestEditorUtils.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +using NUnit.Framework; + +namespace FlaxEngine.Tests +{ + /// + /// Tests for . + /// + [TestFixture] + public class TestEditorUtils + { + /// + /// Test floating point values formatting to readable text. + /// + [Test] + public void TestFormatFloat() + { + Assert.AreEqual("0", FlaxEditor.Utilities.Utils.FormatFloat(0.0f)); + Assert.AreEqual("0", FlaxEditor.Utilities.Utils.FormatFloat(0.0d)); + Assert.AreEqual("0.1234", FlaxEditor.Utilities.Utils.FormatFloat(0.1234f)); + Assert.AreEqual("0.1234", FlaxEditor.Utilities.Utils.FormatFloat(0.1234d)); + Assert.AreEqual("1234", FlaxEditor.Utilities.Utils.FormatFloat(1234.0f)); + Assert.AreEqual("1234", FlaxEditor.Utilities.Utils.FormatFloat(1234.0d)); + Assert.AreEqual("1234.123", FlaxEditor.Utilities.Utils.FormatFloat(1234.123f)); + Assert.AreEqual("1234.1234", FlaxEditor.Utilities.Utils.FormatFloat(1234.1234d)); + + double[] values = + { + 123450000000000000.0, 1.0 / 7, 10000000000.0 / 7, 100000000000000000.0 / 7, 0.001 / 7, 0.0001 / 7, 100000000000000000.0, 0.00000000001, + 1.23e-2, 1.234e-5, 1.2345E-10, 1.23456E-20, 5E-20, 1.23E+2, 1.234e5, 1.2345E10, -7.576E-05, 1.23456e20, 5e+20, 9.1093822E-31, 5.9736e24, + double.Epsilon, Mathd.Epsilon, Mathf.Epsilon + }; + foreach (int sign in new[] { 1, -1 }) + { + foreach (double value in values) + { + double value1 = sign * value; + string text = FlaxEditor.Utilities.Utils.FormatFloat(value1); + Assert.IsFalse(text.Contains("e")); + Assert.IsFalse(text.Contains("E")); + double value2 = double.Parse(text); + Assert.AreEqual(value2, value1); + } + } + foreach (int sign in new[] { 1, -1 }) + { + foreach (double value in values) + { + float value1 = (float)(sign * value); + string text = FlaxEditor.Utilities.Utils.FormatFloat(value1); + Assert.IsFalse(text.Contains("e")); + Assert.IsFalse(text.Contains("E")); + float value2 = float.Parse(text); + Assert.AreEqual(value2, value1); + } + } + } + } +}