Browse Source
Merge pull request #11005 from Altua/transformed-hittest
Take Transform into account when hit testing DrawOperationWithTransform
pull/11009/head
Nikita Tsukanov
3 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with
41 additions and
10 deletions
-
src/Avalonia.Base/Rendering/SceneGraph/CustomDrawOperation.cs
-
src/Avalonia.Base/Rendering/SceneGraph/DrawOperation.cs
-
src/Avalonia.Base/Rendering/SceneGraph/EllipseNode.cs
-
src/Avalonia.Base/Rendering/SceneGraph/ExperimentalAcrylicNode.cs
-
src/Avalonia.Base/Rendering/SceneGraph/GeometryNode.cs
-
src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
-
src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs
-
src/Avalonia.Base/Rendering/SceneGraph/LineNode.cs
-
src/Avalonia.Base/Rendering/SceneGraph/OpacityMaskNode.cs
-
src/Avalonia.Base/Rendering/SceneGraph/RectangleNode.cs
-
tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
|
|
|
@ -13,7 +13,7 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
Custom = custom; |
|
|
|
} |
|
|
|
|
|
|
|
public override bool HitTest(Point p) => Custom.HitTest(p); |
|
|
|
public override bool HitTestTransformed(Point p) => Custom.HitTest(p); |
|
|
|
|
|
|
|
public override void Render(IDrawingContextImpl context) |
|
|
|
{ |
|
|
|
|
|
|
|
@ -37,5 +37,20 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
} |
|
|
|
|
|
|
|
public Matrix Transform { get; } |
|
|
|
|
|
|
|
public sealed override bool HitTest(Point p) |
|
|
|
{ |
|
|
|
if (Transform.IsIdentity) |
|
|
|
return HitTestTransformed(p); |
|
|
|
|
|
|
|
if (!Transform.HasInverse) |
|
|
|
return false; |
|
|
|
|
|
|
|
var transformedPoint = Transform.Invert().Transform(p); |
|
|
|
|
|
|
|
return HitTestTransformed(transformedPoint); |
|
|
|
} |
|
|
|
|
|
|
|
public abstract bool HitTestTransformed(Point p); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -43,7 +43,7 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
|
|
|
|
public override void Render(IDrawingContextImpl context) => context.DrawEllipse(Brush, Pen, Rect); |
|
|
|
|
|
|
|
public override bool HitTest(Point p) |
|
|
|
public override bool HitTestTransformed(Point p) |
|
|
|
{ |
|
|
|
var center = Rect.Center; |
|
|
|
|
|
|
|
|
|
|
|
@ -65,6 +65,6 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public override bool HitTest(Point p) => Rect.Rect.ContainsExclusive(p); |
|
|
|
public override bool HitTestTransformed(Point p) => Rect.Rect.ContainsExclusive(p); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -64,7 +64,7 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public override bool HitTest(Point p) |
|
|
|
public override bool HitTestTransformed(Point p) |
|
|
|
{ |
|
|
|
return (Brush != null && Geometry.FillContains(p)) || |
|
|
|
(Pen != null && Geometry.StrokeContains(Pen, p)); |
|
|
|
|
|
|
|
@ -53,7 +53,7 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public override bool HitTest(Point p) => Bounds.ContainsExclusive(p); |
|
|
|
public override bool HitTestTransformed(Point p) => Bounds.ContainsExclusive(p); |
|
|
|
|
|
|
|
public override void Dispose() |
|
|
|
{ |
|
|
|
|
|
|
|
@ -94,7 +94,7 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public override bool HitTest(Point p) => DestRect.ContainsExclusive(p); |
|
|
|
public override bool HitTestTransformed(Point p) => DestRect.ContainsExclusive(p); |
|
|
|
|
|
|
|
public override void Dispose() |
|
|
|
{ |
|
|
|
|
|
|
|
@ -66,7 +66,7 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
context.DrawLine(Pen, P1, P2); |
|
|
|
} |
|
|
|
|
|
|
|
public override bool HitTest(Point p) |
|
|
|
public override bool HitTestTransformed(Point p) |
|
|
|
{ |
|
|
|
var halfThickness = Pen.Thickness / 2; |
|
|
|
var minX = Math.Min(P1.X, P2.X) - halfThickness; |
|
|
|
|
|
|
|
@ -30,7 +30,7 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public override bool HitTest(Point p) => false; |
|
|
|
public override bool HitTestTransformed(Point p) => false; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Determines if this draw operation equals another.
|
|
|
|
|
|
|
|
@ -74,7 +74,7 @@ namespace Avalonia.Rendering.SceneGraph |
|
|
|
public override void Render(IDrawingContextImpl context) => context.DrawRectangle(Brush, Pen, Rect, BoxShadows); |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public override bool HitTest(Point p) |
|
|
|
public override bool HitTestTransformed(Point p) |
|
|
|
{ |
|
|
|
if (Brush != null) |
|
|
|
{ |
|
|
|
|
|
|
|
@ -74,6 +74,22 @@ namespace Avalonia.Base.UnitTests.Rendering.SceneGraph |
|
|
|
geometryNode.HitTest(new Point()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void HitTest_RectangleNode_With_Transform_Hits() |
|
|
|
{ |
|
|
|
var geometry = Mock.Of<IGeometryImpl>(); |
|
|
|
var geometryNode = new RectangleNode( |
|
|
|
Matrix.CreateTranslation(20,20), |
|
|
|
Brushes.Black, |
|
|
|
null, |
|
|
|
new RoundedRect(new Rect(0,0,10,10)), |
|
|
|
default); |
|
|
|
|
|
|
|
var actual = geometryNode.HitTest(new Point(25,25)); |
|
|
|
|
|
|
|
Assert.True(actual); |
|
|
|
} |
|
|
|
|
|
|
|
private class TestRectangleDrawOperation : RectangleNode |
|
|
|
{ |
|
|
|
public TestRectangleDrawOperation(Rect bounds, Matrix transform, Pen pen) |
|
|
|
@ -82,7 +98,7 @@ namespace Avalonia.Base.UnitTests.Rendering.SceneGraph |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public override bool HitTest(Point p) => false; |
|
|
|
public override bool HitTestTransformed(Point p) => false; |
|
|
|
|
|
|
|
public override void Render(IDrawingContextImpl context) { } |
|
|
|
} |
|
|
|
|