diff --git a/osu-framework b/osu-framework
index eb6362eaf1..7e8788e601 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit eb6362eaf1317b0fa27b2c9e559bd9a0f1ce357c
+Subproject commit 7e8788e601b62577e51197a29e24f56eeeac0286
diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs
index 5ff3ddbe05..c7f555ff0f 100644
--- a/osu.Game/Configuration/OsuConfigManager.cs
+++ b/osu.Game/Configuration/OsuConfigManager.cs
@@ -84,6 +84,7 @@ namespace osu.Game.Configuration
Set(OsuSetting.Version, string.Empty);
Set(OsuSetting.ScreenshotFormat, ScreenshotFormat.Jpg);
+ Set(OsuSetting.ScreenshotCaptureMenuCursor, false);
}
public OsuConfigManager(Storage storage) : base(storage)
@@ -128,6 +129,7 @@ namespace osu.Game.Configuration
ShowConvertedBeatmaps,
SpeedChangeVisualisation,
Skin,
- ScreenshotFormat
+ ScreenshotFormat,
+ ScreenshotCaptureMenuCursor
}
}
diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs
index 81ae3198c7..1e56cb6052 100644
--- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs
+++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs
@@ -20,7 +20,7 @@ namespace osu.Game.Graphics.Cursor
///
/// Whether any cursors can be displayed.
///
- public bool CanShowCursor = true;
+ internal bool CanShowCursor = true;
public CursorContainer Cursor { get; }
public bool ProvidingUserCursor => true;
diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs
index 34d815ec14..5f57fb76b0 100644
--- a/osu.Game/Graphics/Cursor/MenuCursor.cs
+++ b/osu.Game/Graphics/Cursor/MenuCursor.cs
@@ -12,12 +12,16 @@ using osu.Framework.Input;
using osu.Game.Configuration;
using System;
using System.Diagnostics;
+using JetBrains.Annotations;
using osu.Framework.Graphics.Textures;
namespace osu.Game.Graphics.Cursor
{
public class MenuCursor : CursorContainer
{
+ private readonly IBindable screenshotCursorVisibility = new Bindable(true);
+ public override bool IsPresent => screenshotCursorVisibility.Value && base.IsPresent;
+
protected override Drawable CreateCursor() => new Cursor();
private Bindable cursorRotate;
@@ -25,6 +29,15 @@ namespace osu.Game.Graphics.Cursor
private bool startRotation;
+ [BackgroundDependencyLoader(true)]
+ private void load([NotNull] OsuConfigManager config, [CanBeNull] ScreenshotManager screenshotManager)
+ {
+ cursorRotate = config.GetBindable(OsuSetting.CursorRotation);
+
+ if (screenshotManager != null)
+ screenshotCursorVisibility.BindTo(screenshotManager.CursorVisibility);
+ }
+
protected override bool OnMouseMove(InputState state)
{
if (cursorRotate && dragging)
@@ -104,12 +117,6 @@ namespace osu.Game.Graphics.Cursor
ActiveCursor.ScaleTo(0.6f, 250, Easing.In);
}
- [BackgroundDependencyLoader]
- private void load(OsuConfigManager config)
- {
- cursorRotate = config.GetBindable(OsuSetting.CursorRotation);
- }
-
public class Cursor : Container
{
private Container cursorContainer;
diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs
index 5e0b9c9340..90580c50df 100644
--- a/osu.Game/Graphics/ScreenshotManager.cs
+++ b/osu.Game/Graphics/ScreenshotManager.cs
@@ -4,6 +4,8 @@
using System;
using System.Drawing.Imaging;
using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
@@ -12,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.Input.Bindings;
using osu.Game.Overlays;
@@ -21,7 +24,17 @@ namespace osu.Game.Graphics
{
public class ScreenshotManager : Container, IKeyBindingHandler, IHandleGlobalInput
{
+ private readonly BindableBool cursorVisibility = new BindableBool(true);
+
+ ///
+ /// Changed when screenshots are being or have finished being taken, to control whether cursors should be visible.
+ /// If cursors should not be visible, cursors have 3 frames to hide themselves.
+ ///
+ public IBindable CursorVisibility => cursorVisibility;
+
private Bindable screenshotFormat;
+ private Bindable captureMenuCursor;
+
private GameHost host;
private Storage storage;
private NotificationOverlay notificationOverlay;
@@ -36,6 +49,7 @@ namespace osu.Game.Graphics
this.notificationOverlay = notificationOverlay;
screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat);
+ captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor);
shutter = audio.Sample.Get("UI/shutter");
}
@@ -55,10 +69,31 @@ namespace osu.Game.Graphics
public bool OnReleased(GlobalAction action) => false;
- public async void TakeScreenshotAsync()
+ private volatile int screenShotTasks;
+
+ public async Task TakeScreenshotAsync() => await Task.Run(async () =>
{
+ Interlocked.Increment(ref screenShotTasks);
+
+ if (!captureMenuCursor.Value)
+ {
+ cursorVisibility.Value = false;
+
+ // 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;
@@ -86,6 +121,14 @@ namespace osu.Game.Graphics
}
});
}
+ });
+
+ protected override void Update()
+ {
+ base.Update();
+
+ if (cursorVisibility == false && Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0)
+ cursorVisibility.Value = true;
}
private string getFileName()
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 2d65d6738d..941e49e87e 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -60,6 +60,8 @@ namespace osu.Game
private BeatmapSetOverlay beatmapSetOverlay;
+ private ScreenshotManager screenshotManager;
+
public virtual Storage GetStorageForStableInstall() => null;
private Intro intro
@@ -200,6 +202,9 @@ namespace osu.Game
protected override void LoadComplete()
{
+ // this needs to be cached before base.LoadComplete as it is used by CursorOverrideContainer.
+ dependencies.Cache(screenshotManager = new ScreenshotManager());
+
base.LoadComplete();
// The next time this is updated is in UpdateAfterChildren, which occurs too late and results
@@ -243,7 +248,8 @@ namespace osu.Game
loadComponentSingleFile(volume = new VolumeOverlay(), overlayContent.Add);
loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add);
- loadComponentSingleFile(new ScreenshotManager(), Add);
+
+ loadComponentSingleFile(screenshotManager, Add);
//overlay elements
loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add);
diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs
index a78cb29468..54049bfb1f 100644
--- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs
+++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs
@@ -30,6 +30,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{
LabelText = "Screenshot format",
Bindable = config.GetBindable(OsuSetting.ScreenshotFormat)
+ },
+ new SettingsCheckbox
+ {
+ LabelText = "Show menu cursor in screenshots",
+ Bindable = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor)
}
};
}
diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs
index 33e423a558..542ddd2c92 100644
--- a/osu.Game/Screens/Menu/Button.cs
+++ b/osu.Game/Screens/Menu/Button.cs
@@ -222,7 +222,7 @@ namespace osu.Game.Screens.Menu
boxHoverLayer.FadeOut(800, Easing.OutExpo);
}
- public override bool HandleKeyboardInput => state != ButtonState.Exploded;
+ public override bool HandleKeyboardInput => state == ButtonState.Expanded;
public override bool HandleMouseInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f;
protected override void Update()