A game framework written with osu! in mind.
at master 105 lines 4.0 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 osuTK; 6 7namespace osu.Framework.Graphics.Containers 8{ 9 /// <summary> 10 /// A <see cref="Container"/> filling its parent while preserving a given target 11 /// <see cref="Drawable.DrawSize"/> according to a <see cref="DrawSizePreservationStrategy"/>. 12 /// This is useful, for example, to automatically scale the user interface according to 13 /// the window resolution, or to provide automatic HiDPI display support. 14 /// </summary> 15 public class DrawSizePreservingFillContainer : Container 16 { 17 private readonly Container content; 18 19 protected override Container<Drawable> Content => content; 20 21 /// <summary> 22 /// The target <see cref="Drawable.DrawSize"/> to be enforced according to <see cref="Strategy"/>. 23 /// </summary> 24 public Vector2 TargetDrawSize = new Vector2(1024, 768); 25 26 /// <summary> 27 /// The strategy to be used for enforcing <see cref="TargetDrawSize"/>. The default strategy 28 /// is Minimum, which preserves the aspect ratio of all children while ensuring one of the 29 /// two axes matches <see cref="TargetDrawSize"/> while the other is always larger. 30 /// </summary> 31 public DrawSizePreservationStrategy Strategy; 32 33 public DrawSizePreservingFillContainer() 34 { 35 AddInternal(content = new Container 36 { 37 RelativeSizeAxes = Axes.Both, 38 }); 39 40 RelativeSizeAxes = Axes.Both; 41 } 42 43 protected override void Update() 44 { 45 base.Update(); 46 47 Vector2 drawSizeRatio = Vector2.Divide(Parent.ChildSize, TargetDrawSize); 48 49 switch (Strategy) 50 { 51 case DrawSizePreservationStrategy.Minimum: 52 content.Scale = new Vector2(Math.Min(drawSizeRatio.X, drawSizeRatio.Y)); 53 break; 54 55 case DrawSizePreservationStrategy.Maximum: 56 content.Scale = new Vector2(Math.Max(drawSizeRatio.X, drawSizeRatio.Y)); 57 break; 58 59 case DrawSizePreservationStrategy.Average: 60 content.Scale = new Vector2(0.5f * (drawSizeRatio.X + drawSizeRatio.Y)); 61 break; 62 63 case DrawSizePreservationStrategy.Separate: 64 content.Scale = drawSizeRatio; 65 break; 66 } 67 68 content.Size = Vector2.Divide(Vector2.One, content.Scale); 69 } 70 } 71 72 /// <summary> 73 /// Strategies used by <see cref="DrawSizePreservingFillContainer"/> to enforce its 74 /// <see cref="DrawSizePreservingFillContainer.TargetDrawSize"/>. 75 /// </summary> 76 public enum DrawSizePreservationStrategy 77 { 78 /// <summary> 79 /// Preserves the aspect ratio of all children while ensuring one of the 80 /// two axes matches <see cref="DrawSizePreservingFillContainer.TargetDrawSize"/> 81 /// while the other is always larger. 82 /// </summary> 83 Minimum, 84 85 /// <summary> 86 /// Preserves the aspect ratio of all children while ensuring one of the 87 /// two axes matches <see cref="DrawSizePreservingFillContainer.TargetDrawSize"/> 88 /// while the other is always smaller. 89 /// </summary> 90 Maximum, 91 92 /// <summary> 93 /// Preserves the aspect ratio of all children while one axis is always larger and 94 /// the other always smaller than <see cref="DrawSizePreservingFillContainer.TargetDrawSize"/>, 95 /// achieving a good compromise. 96 /// </summary> 97 Average, 98 99 /// <summary> 100 /// Ensures <see cref="DrawSizePreservingFillContainer.TargetDrawSize"/> is perfectly 101 /// matched while aspect ratio of children is disregarded. 102 /// </summary> 103 Separate, 104 } 105}