From ce92286112282e5cead7fd5f9fc40590c4bb46cc Mon Sep 17 00:00:00 2001 From: JaggerJo Date: Mon, 22 Jul 2019 00:21:43 +0200 Subject: [PATCH 1/9] add basic operations as static methods and use them in the declared operators. - Dot - Cross - Normalize - Divide - Multiply - Add - Subtract - Negate --- src/Avalonia.Visuals/Vector.cs | 115 +++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 19 deletions(-) diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs index 2f1690184d..f185682dc0 100644 --- a/src/Avalonia.Visuals/Vector.cs +++ b/src/Avalonia.Visuals/Vector.cs @@ -65,9 +65,7 @@ namespace Avalonia /// Second vector /// The dot product public static double operator *(Vector a, Vector b) - { - return a.X * b.X + a.Y * b.Y; - } + => Dot(a, b); /// /// Scales a vector. @@ -76,9 +74,7 @@ namespace Avalonia /// The scaling factor. /// The scaled vector. public static Vector operator *(Vector vector, double scale) - { - return new Vector(vector._x * scale, vector._y * scale); - } + => Multiply(vector, scale); /// /// Scales a vector. @@ -87,9 +83,7 @@ namespace Avalonia /// The divisor. /// The scaled vector. public static Vector operator /(Vector vector, double scale) - { - return new Vector(vector._x / scale, vector._y / scale); - } + => Divide(vector, scale); /// /// Length of the vector @@ -102,9 +96,7 @@ namespace Avalonia /// The vector. /// The negated vector. public static Vector operator -(Vector a) - { - return new Vector(-a._x, -a._y); - } + => Negate(a); /// /// Adds two vectors. @@ -113,9 +105,7 @@ namespace Avalonia /// The second vector. /// A vector that is the result of the addition. public static Vector operator +(Vector a, Vector b) - { - return new Vector(a._x + b._x, a._y + b._y); - } + => Add(a, b); /// /// Subtracts two vectors. @@ -124,9 +114,7 @@ namespace Avalonia /// The second vector. /// A vector that is the result of the subtraction. public static Vector operator -(Vector a, Vector b) - { - return new Vector(a._x - b._x, a._y - b._y); - } + => Subtract(a, b); /// /// Check if two vectors are equal (bitwise). @@ -155,7 +143,8 @@ namespace Avalonia public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(null, obj)) + return false; return obj is Vector vector && Equals(vector); } @@ -206,5 +195,93 @@ namespace Avalonia { return new Vector(_x, y); } + + /// + /// Returns the dot product of two vectors. + /// + /// The first vector. + /// The second vector. + /// The dot product. + public static double Dot(Vector a, Vector b) + => a._x * b._x + a._y * b._y; + + /// + /// Returns the cross product of two vectors. + /// + /// The first vector. + /// The second vector. + /// The cross product. + public static double Cross(Vector a, Vector b) + => a._x * b._y - a._y * b._x; + + /// + /// Normalizes the given vector. + /// + /// The vector + /// The normalized vector. + public static Vector Normalize(Vector vector) + => Divide(vector, vector.Length); + + /// + /// Divides the first vector by the second. + /// + /// The first vector. + /// The second vector. + /// The scaled vector. + public static Vector Divide(Vector a, Vector b) + => new Vector(a._x / b._x, a._y / b._y); + + /// + /// Divides the vector by the given scalar. + /// + /// The vector + /// The scalar value + /// The scaled vector. + public static Vector Divide(Vector vector, double scalar) + => new Vector(vector._x / scalar, vector._y / scalar); + + /// + /// Multiplies the first vector by the second. + /// + /// The first vector. + /// The second vector. + /// The scaled vector. + public static Vector Multiply(Vector a, Vector b) + => new Vector(a._x * b._x, a._y * b._y); + + /// + /// Multiplies the vector by the given scalar. + /// + /// The vector + /// The scalar value + /// The scaled vector. + public static Vector Multiply(Vector vector, double scalar) + => new Vector(vector._x * scalar, vector._y * scalar); + + /// + /// Adds the second to the first vector + /// + /// The first vector. + /// The second vector. + /// The summed vector. + public static Vector Add(Vector a, Vector b) + => new Vector(a._x + b._x, a._y + b._y); + + /// + /// Subtracts the second from the first vector + /// + /// The first vector. + /// The second vector. + /// The difference vector. + public static Vector Subtract(Vector a, Vector b) + => new Vector(a._x - b._x, a._y - b._y); + + /// + /// Negates the vector + /// + /// The vector to negate. + /// The scaled vector. + public static Vector Negate(Vector vector) + => new Vector(-vector._x, -vector._y); } } From 7d96244e3c2480d63782245e0e52b2744d0dee5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josua=20J=C3=A4ger?= Date: Thu, 15 Aug 2019 20:17:58 +0200 Subject: [PATCH 2/9] add squared length --- src/Avalonia.Visuals/Vector.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs index f185682dc0..78ed688295 100644 --- a/src/Avalonia.Visuals/Vector.cs +++ b/src/Avalonia.Visuals/Vector.cs @@ -90,6 +90,11 @@ namespace Avalonia /// public double Length => Math.Sqrt(X * X + Y * Y); + /// + /// Squared Length of the vector + /// + public double SquaredLength => Math.Sqrt(Length); + /// /// Negates a vector. /// From 22ac34d89b912cef0b5de1b5660201e27916e011 Mon Sep 17 00:00:00 2001 From: JaggerJo Date: Thu, 15 Aug 2019 20:28:42 +0200 Subject: [PATCH 3/9] add - Zero - One - UnitX - UnitY --- src/Avalonia.Visuals/Vector.cs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs index f185682dc0..aede9f3905 100644 --- a/src/Avalonia.Visuals/Vector.cs +++ b/src/Avalonia.Visuals/Vector.cs @@ -283,5 +283,29 @@ namespace Avalonia /// The scaled vector. public static Vector Negate(Vector vector) => new Vector(-vector._x, -vector._y); + + /// + /// Returnes the vector (0.0, 0.0) + /// + public static Vector Zero + => new Vector(0, 0); + + /// + /// Returnes the vector (1.0, 1.0) + /// + public static Vector One + => new Vector(1, 1); + + /// + /// Returnes the vector (1.0, 0.0) + /// + public static Vector UnitX + => new Vector(1, 0); + + /// + /// Returnes the vector (0.0, 1.0) + /// + public static Vector UnitY + => new Vector(0, 1); } } From b475acab1e677c3d570e83fe791fdffac54f0e0b Mon Sep 17 00:00:00 2001 From: JaggerJo Date: Thu, 15 Aug 2019 21:17:38 +0200 Subject: [PATCH 4/9] - add tests - add instance methods for normalize & negate - make length squared simpler --- src/Avalonia.Visuals/Vector.cs | 18 ++- .../Avalonia.Visuals.UnitTests/VectorTests.cs | 112 ++++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 tests/Avalonia.Visuals.UnitTests/VectorTests.cs diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs index 2c02c00d00..782a917c62 100644 --- a/src/Avalonia.Visuals/Vector.cs +++ b/src/Avalonia.Visuals/Vector.cs @@ -88,12 +88,12 @@ namespace Avalonia /// /// Length of the vector /// - public double Length => Math.Sqrt(X * X + Y * Y); + public double Length => Math.Sqrt(_x * _x + _y * _y); /// /// Squared Length of the vector /// - public double SquaredLength => Math.Sqrt(Length); + public double SquaredLength => _x * _x + _y * _y; /// /// Negates a vector. @@ -201,6 +201,20 @@ namespace Avalonia return new Vector(_x, y); } + /// + /// Returns a normalized version of this vector. + /// + /// The normalized vector. + public Vector Normalize() + => Normalize(this); + + /// + /// Returns a negated version of this vector. + /// + /// The negated vector. + public Vector Negate() + => Negate(this); + /// /// Returns the dot product of two vectors. /// diff --git a/tests/Avalonia.Visuals.UnitTests/VectorTests.cs b/tests/Avalonia.Visuals.UnitTests/VectorTests.cs new file mode 100644 index 0000000000..1bcc165aef --- /dev/null +++ b/tests/Avalonia.Visuals.UnitTests/VectorTests.cs @@ -0,0 +1,112 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using Xunit; +using Avalonia; +using System; + +namespace Avalonia.Visuals.UnitTests +{ + public class VectorTests + { + [Fact] + public void Length_Should_Return_Correct_Length_Of_Vector() + { + var vector = new Vector(2, 4); + var length = Math.Sqrt(2 * 2 + 4 * 4); + + Assert.Equal(length, vector.Length); + } + + [Fact] + public void Length_Squared_Should_Return_Correct_Length_Of_Vector() + { + var vectorA = new Vector(2, 4); + var squaredLengthA = 2 * 2 + 4 * 4; + + Assert.Equal(squaredLengthA, vectorA.SquaredLength); + } + + [Fact] + public void Normalize_Should_Return_Normalized_Vector() + { + // the length of a normalized vector must be 1 + + var vectorA = new Vector(13, 84); + var vectorB = new Vector(-34, 345); + var vectorC = new Vector(-34, -84); + + Assert.Equal(1.0, vectorA.Normalize().Length); + Assert.Equal(1.0, vectorB.Normalize().Length); + Assert.Equal(1.0, vectorC.Normalize().Length); + } + + [Fact] + public void Negate_Should_Return_Negated_Vector() + { + var vector = new Vector(2, 4); + var negated = new Vector(-2, -4); + + Assert.Equal(negated, vector.Negate()); + } + + [Fact] + public void Dot_Should_Return_Correct_Value() + { + var a = new Vector(-6, 8.0); + var b = new Vector(5, 12.0); + + Assert.Equal(66.0, Vector.Dot(a, b)); + } + + [Fact] + public void Cross_Should_Return_Correct_Value() + { + var a = new Vector(-6, 8.0); + var b = new Vector(5, 12.0); + + Assert.Equal(-112.0, Vector.Cross(a, b)); + } + + [Fact] + public void Divied_By_Vector_Should_Return_Correct_Value() + { + var a = new Vector(10, 2); + var b = new Vector(5, 2); + + var expected = new Vector(2, 1); + + Assert.Equal(expected, Vector.Divide(a, b)); + } + + [Fact] + public void Divied_Should_Return_Correct_Value() + { + var vector = new Vector(10, 2); + var expected = new Vector(5, 1); + + Assert.Equal(expected, Vector.Divide(vector, 2)); + } + + [Fact] + public void Multiply_By_Vector_Should_Return_Correct_Value() + { + var a = new Vector(10, 2); + var b = new Vector(2, 2); + + var expected = new Vector(20, 4); + + Assert.Equal(expected, Vector.Multiply(a, b)); + } + + [Fact] + public void Multiply_Should_Return_Correct_Value() + { + var vector = new Vector(10, 2); + + var expected = new Vector(20, 4); + + Assert.Equal(expected, Vector.Multiply(vector, 2)); + } + } +} From ba873bf33936234ad533c56da161a2890954c958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josua=20J=C3=A4ger?= Date: Sat, 17 Aug 2019 17:48:01 +0200 Subject: [PATCH 5/9] use field directly instead of property Co-Authored-By: Benedikt Schroeder --- src/Avalonia.Visuals/Vector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs index 782a917c62..11bda8b00e 100644 --- a/src/Avalonia.Visuals/Vector.cs +++ b/src/Avalonia.Visuals/Vector.cs @@ -88,7 +88,7 @@ namespace Avalonia /// /// Length of the vector /// - public double Length => Math.Sqrt(_x * _x + _y * _y); + public double Length => Math.Sqrt(SquaredLength); /// /// Squared Length of the vector From 33f154148b8929853480df3ef6c0946da7763762 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 7 Sep 2019 22:29:01 +0100 Subject: [PATCH 6/9] Add static method to open devtools. --- src/Avalonia.Diagnostics/DevTools.xaml.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Diagnostics/DevTools.xaml.cs b/src/Avalonia.Diagnostics/DevTools.xaml.cs index 1fcfb525cb..037e80e372 100644 --- a/src/Avalonia.Diagnostics/DevTools.xaml.cs +++ b/src/Avalonia.Diagnostics/DevTools.xaml.cs @@ -28,6 +28,11 @@ namespace Avalonia { Diagnostics.DevTools.Attach(control, gesture); } + + public static void OpenDevTools(this TopLevel control) + { + Diagnostics.DevTools.OpenDevTools(control); + } } } @@ -73,7 +78,7 @@ namespace Avalonia.Diagnostics RoutingStrategies.Tunnel); } - private static void OpenDevTools(TopLevel control) + internal static void OpenDevTools(TopLevel control) { if (s_open.TryGetValue(control, out var devToolsWindow)) { From 90eb54f8eb28df515c4c957fab32af8ad5ee73cf Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 9 Sep 2019 12:25:26 +0100 Subject: [PATCH 7/9] fix nuget replace script. --- scripts/ReplaceNugetCache.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/ReplaceNugetCache.sh b/scripts/ReplaceNugetCache.sh index 4cc11edd60..e1c0487d60 100755 --- a/scripts/ReplaceNugetCache.sh +++ b/scripts/ReplaceNugetCache.sh @@ -2,7 +2,6 @@ cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia/$1/lib/netcoreapp2.0/ cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia/$1/lib/netstandard2.0/ - cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.gtk3/$1/lib/netstandard2.0/ cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.skia/$1/lib/netstandard2.0/ cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.native/$1/lib/netstandard2.0/ From f56a47ed49343b804ec3041a22217eddfe7e5213 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 9 Sep 2019 12:22:31 +0100 Subject: [PATCH 8/9] fix osx managed file dialogs. --- .../MacOSMountedVolumeInfoProvider.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs b/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs index eea695d77e..92b2915e2e 100644 --- a/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs +++ b/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs @@ -8,16 +8,16 @@ using Avalonia.Controls.Platform; namespace Avalonia.Native { - internal class WindowsMountedVolumeInfoListener : IDisposable + internal class MacOSMountedVolumeInfoListener : IDisposable { private readonly CompositeDisposable _disposables; - private readonly ObservableCollection _targetObs; private bool _beenDisposed = false; private ObservableCollection mountedDrives; - public WindowsMountedVolumeInfoListener(ObservableCollection mountedDrives) + public MacOSMountedVolumeInfoListener(ObservableCollection mountedDrives) { this.mountedDrives = mountedDrives; + _disposables = new CompositeDisposable(); var pollTimer = Observable.Interval(TimeSpan.FromSeconds(1)) @@ -30,7 +30,8 @@ namespace Avalonia.Native private void Poll(long _) { - var mountVolInfos = Directory.GetDirectories("/Volumes") + var mountVolInfos = Directory.GetDirectories("/Volumes/") + .Where(p=> p != null) .Select(p => new MountedVolumeInfo() { VolumeLabel = Path.GetFileName(p), @@ -38,15 +39,15 @@ namespace Avalonia.Native VolumeSizeBytes = 0 }) .ToArray(); - - if (_targetObs.SequenceEqual(mountVolInfos)) + + if (mountedDrives.SequenceEqual(mountVolInfos)) return; else { - _targetObs.Clear(); + mountedDrives.Clear(); foreach (var i in mountVolInfos) - _targetObs.Add(i); + mountedDrives.Add(i); } } @@ -72,7 +73,7 @@ namespace Avalonia.Native public IDisposable Listen(ObservableCollection mountedDrives) { Contract.Requires(mountedDrives != null); - return new WindowsMountedVolumeInfoListener(mountedDrives); + return new MacOSMountedVolumeInfoListener(mountedDrives); } } } From 734b9f39b39b38c091e5a36a4c8dcb18de88b2dd Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 9 Sep 2019 12:25:06 +0100 Subject: [PATCH 9/9] fix windows mounted listener. --- .../Avalonia.Win32/WindowsMountedVolumeInfoListener.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs index 102e027584..a17e6b8b51 100644 --- a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs +++ b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs @@ -10,8 +10,7 @@ namespace Avalonia.Win32 { internal class WindowsMountedVolumeInfoListener : IDisposable { - private readonly CompositeDisposable _disposables; - private readonly ObservableCollection _targetObs = new ObservableCollection(); + private readonly CompositeDisposable _disposables; private bool _beenDisposed = false; private ObservableCollection mountedDrives; @@ -41,14 +40,14 @@ namespace Avalonia.Win32 }) .ToArray(); - if (_targetObs.SequenceEqual(mountVolInfos)) + if (mountedDrives.SequenceEqual(mountVolInfos)) return; else { - _targetObs.Clear(); + mountedDrives.Clear(); foreach (var i in mountVolInfos) - _targetObs.Add(i); + mountedDrives.Add(i); } }