csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
2.8 KiB
109 lines
2.8 KiB
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Controls.Shapes;
|
|
using Avalonia.Input;
|
|
using Avalonia.Markup.Xaml;
|
|
using Avalonia.Media;
|
|
|
|
namespace RenderDemo.Pages;
|
|
|
|
public class GeometryHitTestingPage : UserControl
|
|
{
|
|
private readonly IBrush _hitStroke = Brushes.Yellow;
|
|
private readonly TranslateTransform _probePosition = new();
|
|
private readonly Dictionary<Shape, IBrush?> _strokes = new();
|
|
private readonly List<(Shape Shape, IntersectionResult Intersection)> _hits = new();
|
|
private readonly Geometry _probeGeometry;
|
|
private readonly Panel _scene;
|
|
private readonly Path _probe;
|
|
private readonly TextBlock _status;
|
|
|
|
public GeometryHitTestingPage()
|
|
{
|
|
InitializeComponent();
|
|
|
|
_scene = this.Get<Panel>("Scene");
|
|
_probe = this.Get<Path>("Probe");
|
|
_status = this.Get<TextBlock>("Status");
|
|
|
|
_probeGeometry = CreateProbeGeometry();
|
|
_probeGeometry.Transform = _probePosition;
|
|
_probe.Data = _probeGeometry;
|
|
|
|
foreach (var shape in _scene.Children.OfType<Shape>())
|
|
{
|
|
if (shape != _probe)
|
|
_strokes.Add(shape, shape.Stroke);
|
|
}
|
|
|
|
_scene.PointerEntered += SceneOnPointerMoved;
|
|
_scene.PointerMoved += SceneOnPointerMoved;
|
|
_scene.PointerExited += SceneOnPointerExited;
|
|
|
|
UpdateStatus();
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
AvaloniaXamlLoader.Load(this);
|
|
}
|
|
|
|
private Geometry CreateProbeGeometry()
|
|
=> new PolylineGeometry([new(0, -42), new(38, 26), new(-38, 26)], true);
|
|
|
|
private void SceneOnPointerMoved(object? sender, PointerEventArgs e)
|
|
{
|
|
_probe.IsVisible = true;
|
|
MoveProbe(e.GetPosition(_scene));
|
|
}
|
|
|
|
private void MoveProbe(Point position)
|
|
{
|
|
_probePosition.X = position.X;
|
|
_probePosition.Y = position.Y;
|
|
|
|
ClearHits();
|
|
|
|
foreach (var result in _scene.GetInputElementsAt(_probeGeometry))
|
|
{
|
|
if (result?.VisualHit is Shape shape && _strokes.ContainsKey(shape))
|
|
{
|
|
shape.Stroke = _hitStroke;
|
|
_hits.Add((shape, result.IntersectionResult));
|
|
}
|
|
}
|
|
|
|
UpdateStatus();
|
|
}
|
|
|
|
private void SceneOnPointerExited(object? sender, PointerEventArgs e)
|
|
{
|
|
_probe.IsVisible = false;
|
|
ClearHits();
|
|
UpdateStatus();
|
|
}
|
|
|
|
private void ClearHits()
|
|
{
|
|
foreach (var hit in _hits)
|
|
{
|
|
hit.Shape.Stroke = _strokes[hit.Shape];
|
|
}
|
|
|
|
_hits.Clear();
|
|
}
|
|
|
|
private void UpdateStatus()
|
|
{
|
|
if (_hits.Count == 0)
|
|
{
|
|
_status.Text = "No intersection";
|
|
return;
|
|
}
|
|
|
|
_status.Text = "Intersecting, " + string.Join(", ", _hits.Select(hit => $"{hit.Shape.Name} ({hit.Intersection})"));
|
|
}
|
|
}
|
|
|
|
|