diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs index 73fa065919..58d566c34b 100644 --- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -21,16 +21,22 @@ namespace osu.Game.Graphics.Cursor /// Whether any cursors can be displayed. /// public bool CanShowCursor = true; - public bool ShowMenuCursor = true; - public CursorContainer Cursor { get; } + public bool ShowMenuCursor + { + get => cursor.ShowCursor; + set => cursor.ShowCursor = value; + } + + private readonly MenuCursor cursor; + public CursorContainer Cursor => cursor; public bool ProvidingUserCursor => true; public CursorOverrideContainer() { AddRangeInternal(new Drawable[] { - Cursor = new MenuCursor { State = Visibility.Hidden }, + cursor = new MenuCursor { State = Visibility.Hidden }, content = new Container { RelativeSizeAxes = Axes.Both } }); } @@ -54,14 +60,6 @@ namespace osu.Game.Graphics.Cursor return; } - if (currentTarget?.Cursor is MenuCursor) - { - if (ShowMenuCursor && currentTarget?.Cursor.State == Visibility.Hidden) - currentTarget?.Cursor?.Show(); - else if (!ShowMenuCursor && currentTarget?.Cursor.State == Visibility.Visible) - currentTarget?.Cursor?.Hide(); - } - var newTarget = inputManager.HoveredDrawables.OfType().FirstOrDefault(t => t.ProvidingUserCursor) ?? this; if (currentTarget == newTarget) diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index bdee7d289d..4edac3e050 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -18,6 +18,9 @@ namespace osu.Game.Graphics.Cursor { public class MenuCursor : CursorContainer { + public bool ShowCursor = true; + public override bool IsPresent => ShowCursor && base.IsPresent; + protected override Drawable CreateCursor() => new Cursor(); private Bindable cursorRotate; diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index e918ff016e..0d77af8f81 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Platform; +using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; @@ -63,20 +64,31 @@ namespace osu.Game.Graphics public bool OnReleased(GlobalAction action) => false; - public async void TakeScreenshotAsync() + private volatile int screenShotTasks; + + public async Task TakeScreenshotAsync() => Task.Run(async () => { + Interlocked.Increment(ref screenShotTasks); + if (!captureMenuCursor.Value) { cursorOverrideContainer.ShowMenuCursor = false; - await Task.Run(() => - { - while (cursorOverrideContainer.Cursor.ActiveCursor.Alpha > 0) - Thread.Sleep(1); - }); + + // We need to wait for at most 3 draw nodes to be drawn, following which we can be assured at least one DrawNode has been generated/drawn with the set value + const int frames_to_wait = 3; + + int framesWaited = 0; + ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => framesWaited++, 0, true); + while (framesWaited < frames_to_wait) + Thread.Sleep(10); + + waitDelegate.Cancel(); } using (var bitmap = await host.TakeScreenshotAsync()) { + Interlocked.Decrement(ref screenShotTasks); + var fileName = getFileName(); if (fileName == null) return; @@ -104,8 +116,14 @@ namespace osu.Game.Graphics } }); } + }); - cursorOverrideContainer.ShowMenuCursor = true; + protected override void Update() + { + base.Update(); + + if (Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) + cursorOverrideContainer.ShowMenuCursor = true; } private string getFileName()