A game framework written with osu! in mind.
at master 121 lines 3.8 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using System.Linq; 6using osu.Framework.Allocation; 7using osu.Framework.Bindables; 8using osu.Framework.Graphics; 9using osu.Framework.Graphics.Containers; 10using osu.Framework.Graphics.Lines; 11using osu.Framework.Graphics.Shapes; 12using osu.Framework.Utils; 13using osuTK; 14using osuTK.Graphics; 15 16namespace osu.Framework.Tests.Visual.Drawables 17{ 18 public class TestSceneCircularArcBoundingBox : FrameworkTestScene 19 { 20 private SmoothPath path; 21 private Box boundingBox; 22 23 private readonly BindableList<Vector2> controlPoints = new BindableList<Vector2>(); 24 25 private float startAngle, endAngle, radius; 26 27 [BackgroundDependencyLoader] 28 private void load() 29 { 30 Child = new Container 31 { 32 AutoSizeAxes = Axes.Both, 33 Children = new Drawable[] 34 { 35 boundingBox = new Box 36 { 37 RelativeSizeAxes = Axes.None, 38 Colour = Color4.Red 39 }, 40 path = new SmoothPath 41 { 42 Colour = Color4.White, 43 PathRadius = 2 44 } 45 } 46 }; 47 48 AddSliderStep("starting angle", 0, 360, 90, angle => 49 { 50 startAngle = angle; 51 generateControlPoints(); 52 }); 53 54 AddSliderStep("end angle", 0, 360, 270, angle => 55 { 56 endAngle = angle; 57 generateControlPoints(); 58 }); 59 60 AddSliderStep("radius", 1, 300, 150, radius => 61 { 62 this.radius = radius; 63 generateControlPoints(); 64 }); 65 } 66 67 protected override void LoadComplete() 68 { 69 controlPoints.BindCollectionChanged((_, __) => 70 { 71 var copy = controlPoints.ToArray(); 72 if (copy.Length != 3) 73 return; 74 75 path.Vertices = PathApproximator.ApproximateCircularArc(copy); 76 77 var bounds = PathApproximator.CircularArcBoundingBox(copy); 78 boundingBox.Size = bounds.Size; 79 80 // because SmoothPath's bounding box is not exact, 81 // adjust our box's anchoring so that it's always aligned correctly to encapsulate the arc. 82 83 Anchor anchor = 0; 84 85 if (path.Vertices.All(v => v.X < 0)) 86 anchor |= Anchor.x0; 87 else if (path.Vertices.All(v => v.X > 0)) 88 anchor |= Anchor.x2; 89 else 90 anchor |= Anchor.x1; 91 92 if (path.Vertices.All(v => v.Y < 0)) 93 anchor |= Anchor.y0; 94 else if (path.Vertices.All(v => v.Y > 0)) 95 anchor |= Anchor.y2; 96 else 97 anchor |= Anchor.y1; 98 99 boundingBox.Anchor = boundingBox.Origin = anchor; 100 }); 101 } 102 103 private void generateControlPoints() 104 { 105 float midpoint = (startAngle + endAngle) / 2; 106 107 Vector2 polarToCartesian(float r, float theta) => 108 new Vector2( 109 r * MathF.Cos(MathHelper.DegreesToRadians(theta)), 110 r * MathF.Sin(MathHelper.DegreesToRadians(theta))); 111 112 controlPoints.Clear(); 113 controlPoints.AddRange(new[] 114 { 115 polarToCartesian(radius, startAngle), 116 polarToCartesian(radius, midpoint), 117 polarToCartesian(radius, endAngle) 118 }); 119 } 120 } 121}