A game framework written with osu! in mind.
at master 236 lines 10 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.Drawing; 6using osu.Framework.Allocation; 7using osu.Framework.Bindables; 8using osu.Framework.Configuration; 9using osu.Framework.Graphics; 10using osu.Framework.Graphics.Containers; 11using osu.Framework.Graphics.Primitives; 12using osu.Framework.Graphics.Shapes; 13using osu.Framework.Graphics.Sprites; 14using osu.Framework.Platform; 15using osuTK; 16using osuTK.Graphics; 17 18namespace osu.Framework.Tests.Visual.Platform 19{ 20 public class TestSceneBorderless : FrameworkTestScene 21 { 22 private readonly SpriteText currentActualSize = new SpriteText(); 23 private readonly SpriteText currentClientSize = new SpriteText(); 24 private readonly SpriteText currentWindowMode = new SpriteText(); 25 private readonly SpriteText currentDisplay = new SpriteText(); 26 27 private readonly TextFlowContainer windowCaption; 28 private readonly Container paddedContainer; 29 private readonly Container screenContainer; 30 private readonly Container windowContainer; 31 private Vector2 screenContainerOffset; 32 33 private static readonly Color4 active_fill = new Color4(255, 138, 104, 255); 34 private static readonly Color4 active_stroke = new Color4(244, 74, 25, 255); 35 private static readonly Color4 screen_fill = new Color4(255, 181, 104, 255); 36 private static readonly Color4 screen_stroke = new Color4(244, 137, 25, 255); 37 private static readonly Color4 window_fill = new Color4(95, 113, 197, 255); 38 private static readonly Color4 window_stroke = new Color4(36, 59, 166, 255); 39 40 private SDL2DesktopWindow window; 41 private readonly Bindable<WindowMode> windowMode = new Bindable<WindowMode>(); 42 43 public TestSceneBorderless() 44 { 45 Child = new Container 46 { 47 RelativeSizeAxes = Axes.Both, 48 Children = new Drawable[] 49 { 50 new Container 51 { 52 RelativeSizeAxes = Axes.Both, 53 Padding = new MarginPadding(100), 54 Child = paddedContainer = new Container 55 { 56 RelativeSizeAxes = Axes.Both, 57 Child = screenContainer = new Container 58 { 59 Anchor = Anchor.Centre, 60 Origin = Anchor.Centre, 61 Child = windowContainer = new Container 62 { 63 BorderColour = window_stroke, 64 BorderThickness = 20, 65 Masking = true, 66 67 Children = new Drawable[] 68 { 69 new Box 70 { 71 RelativeSizeAxes = Axes.Both, 72 Colour = window_fill 73 }, 74 windowCaption = new TextFlowContainer(sprite => 75 { 76 sprite.Font = sprite.Font.With(size: 150); 77 sprite.Colour = Color4.White; 78 }) 79 { 80 RelativeSizeAxes = Axes.Both, 81 Padding = new MarginPadding(50), 82 Colour = Color4.White 83 } 84 } 85 } 86 } 87 } 88 }, 89 new FillFlowContainer 90 { 91 Padding = new MarginPadding(10), 92 Children = new[] 93 { 94 currentActualSize, 95 currentClientSize, 96 currentWindowMode, 97 currentDisplay 98 }, 99 } 100 } 101 }; 102 103 windowMode.ValueChanged += newMode => currentWindowMode.Text = $"Window Mode: {newMode}"; 104 windowMode.TriggerChange(); 105 } 106 107 private Container createScreen(Display display, string name) => 108 new Container 109 { 110 X = display.Bounds.X, 111 Y = display.Bounds.Y, 112 Width = display.Bounds.Width, 113 Height = display.Bounds.Height, 114 115 BorderColour = display.Index == 0 ? active_stroke : screen_stroke, 116 BorderThickness = 20, 117 Masking = true, 118 119 Children = new Drawable[] 120 { 121 new Box 122 { 123 RelativeSizeAxes = Axes.Both, 124 Colour = display.Index == 0 ? active_fill : screen_fill 125 }, 126 new SpriteText 127 { 128 Padding = new MarginPadding(50), 129 Text = name, 130 Font = new FontUsage(size: 200), 131 Colour = Color4.Black 132 } 133 } 134 }; 135 136 [BackgroundDependencyLoader] 137 private void load(FrameworkConfigManager config, GameHost host) 138 { 139 window = host.Window as SDL2DesktopWindow; 140 config.BindWith(FrameworkSetting.WindowMode, windowMode); 141 142 if (window == null) 143 { 144 Console.WriteLine("No suitable window found"); 145 return; 146 } 147 148 refreshScreens(); 149 150 AddStep("set up screens", refreshScreens); 151 152 const string desc2 = "Check whether the window size is one pixel wider than the screen in each direction"; 153 154 Point originalWindowPosition = Point.Empty; 155 156 foreach (var display in window.Displays) 157 { 158 AddLabel($"Steps for display {display.Index}"); 159 160 // set up window 161 AddStep("switch to windowed", () => windowMode.Value = WindowMode.Windowed); 162 AddStep("set client size to 1280x720", () => config.SetValue(FrameworkSetting.WindowedSize, new Size(1280, 720))); 163 AddStep("store window position", () => originalWindowPosition = window.Position); 164 165 // borderless alignment tests 166 AddStep("switch to borderless", () => windowMode.Value = WindowMode.Borderless); 167 AddAssert("check window position", () => new Point(window.Position.X + 1, window.Position.Y + 1) == display.Bounds.Location); 168 AddAssert("check window size", () => new Size(window.Size.Width - 1, window.Size.Height - 1) == display.Bounds.Size, desc2); 169 AddAssert("check current screen", () => window.CurrentDisplayBindable.Value.Index == display.Index); 170 171 // verify the window size is restored correctly 172 AddStep("switch to windowed", () => windowMode.Value = WindowMode.Windowed); 173 AddAssert("check client size", () => window.ClientSize == new Size(1280, 720)); 174 AddAssert("check window position", () => originalWindowPosition == window.Position); 175 AddAssert("check current screen", () => window.CurrentDisplayBindable.Value.Index == display.Index); 176 } 177 } 178 179 private void refreshScreens() 180 { 181 screenContainer.Remove(windowContainer); 182 screenContainer.Clear(); 183 var bounds = new RectangleI(); 184 185 foreach (var display in window.Displays) 186 { 187 screenContainer.Add(createScreen(display, display.Name)); 188 bounds = RectangleI.Union(bounds, new RectangleI(display.Bounds.X, display.Bounds.Y, display.Bounds.Width, display.Bounds.Height)); 189 } 190 191 screenContainer.Add(windowContainer); 192 screenContainerOffset = bounds.Location; 193 194 foreach (var box in screenContainer.Children) 195 { 196 box.Position -= bounds.Location; 197 } 198 199 screenContainer.Size = bounds.Size; 200 } 201 202 private void updateWindowContainer() 203 { 204 if (window == null) return; 205 206 bool fullscreen = window.WindowMode.Value == WindowMode.Fullscreen; 207 var currentBounds = window.CurrentDisplayBindable.Value.Bounds; 208 209 windowContainer.X = window.Position.X; 210 windowContainer.Y = window.Position.Y; 211 windowContainer.Width = fullscreen ? currentBounds.Width : window.Size.Width; 212 windowContainer.Height = fullscreen ? currentBounds.Height : window.Size.Height; 213 windowContainer.Position -= screenContainerOffset; 214 windowCaption.Text = $"{windowMode}\nSize: {window.Size.Width}x{window.Size.Height}\nClient: {window.ClientSize.Width}x{window.ClientSize.Height}"; 215 } 216 217 protected override void Update() 218 { 219 base.Update(); 220 221 if (window == null) 222 { 223 currentDisplay.Text = "No suitable window found"; 224 return; 225 } 226 227 updateWindowContainer(); 228 var scale = Vector2.Divide(paddedContainer.DrawSize, screenContainer.Size); 229 screenContainer.Scale = new Vector2(Math.Min(scale.X, scale.Y)); 230 231 currentActualSize.Text = $"Window size: {window?.Size}"; 232 currentClientSize.Text = $"Client size: {window?.ClientSize}"; 233 currentDisplay.Text = $"Current Display: {window?.CurrentDisplayBindable.Value.Name}"; 234 } 235 } 236}