using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Media3D; using System.Windows.Shapes; namespace PamhagenSysCtrl.Helpers.Pipeline { public class ConveyorBelt : INode { public const double WIDTH = 35; public const double HEIGHT = 120; public double CenterX { get; set; } public double CenterY { get; set; } public string Label { get; set; } public ISet Inputs { get; init; } public ISet Outputs { get; init; } public bool IsActive { get => _active; set { _active = value; if (value) { _storyboard?.Resume(); } else { _storyboard?.Pause(); } } } private bool _active; private Shape? _rect; private Polyline? _polyline; private Storyboard? _storyboard; public ConveyorBelt(string label, double x, double y) { CenterX = x; CenterY = y; Label = label; Inputs = new HashSet(); Outputs = new HashSet(); } public void Draw(Canvas canvas) { _rect = new Rectangle() { Width = WIDTH, Height = HEIGHT, Stroke = Brushes.Black, StrokeThickness = 2, Fill = Brushes.WhiteSmoke, StrokeLineJoin = PenLineJoin.Round, }; _rect.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2); _rect.SetValue(Canvas.TopProperty, CenterY - HEIGHT / 2); var d = 20; int n = (int)(HEIGHT / d) + 2; _polyline = new Polyline() { Points = [.. Enumerable.Range(0, n).SelectMany(i => new List() { new(-WIDTH, i * d), new(WIDTH, i * d), new(-WIDTH, i * d) })], Fill = Brushes.Transparent, Stroke = Brushes.Black, StrokeThickness = 2, }; _polyline.SetValue(Canvas.TopProperty, 0.0); var slideUp = new DoubleAnimation { From = 0, To = -d, Duration = new Duration(TimeSpan.FromSeconds(1)), RepeatBehavior = RepeatBehavior.Forever, }; _storyboard = new Storyboard(); _storyboard.Children.Add(slideUp); Storyboard.SetTarget(slideUp, _polyline); Storyboard.SetTargetProperty(slideUp, new PropertyPath(Canvas.TopProperty)); var clipCanvas = new Canvas() { Width = WIDTH - 20, Height = HEIGHT - 2, ClipToBounds = true, }; clipCanvas.SetValue(Canvas.TopProperty, CenterY - HEIGHT / 2 + 2); clipCanvas.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2 + 10); clipCanvas.Children.Add(_polyline); canvas.Children.Add(_rect); canvas.Children.Add(clipCanvas); _storyboard.Begin(); _storyboard.Pause(); } public bool IsInside(double x, double y) { return Math.Abs(x - CenterX) <= WIDTH / 2 && Math.Abs(y - CenterY) <= HEIGHT / 2; } public void Update(bool isHovering, bool isPressed) { _rect?.Fill = IsActive && isHovering && isPressed ? PamhagenBrushes.Red : IsActive && isHovering ? PamhagenBrushes.Red : !IsActive && isHovering && isPressed ? PamhagenBrushes.Green : !IsActive && isHovering ? PamhagenBrushes.Green : IsActive ? PamhagenBrushes.Green : Brushes.WhiteSmoke; } } }