1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-14 22:43:05 +08:00

Merge pull request #26697 from LeNitrous/add/scaled-screenshot

Crop screenshots to scaling container
This commit is contained in:
Dean Herbert 2024-01-25 15:03:56 +09:00 committed by GitHub
commit 45b4edcd23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
@ -24,6 +22,8 @@ using osu.Game.Overlays;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
using SixLabors.ImageSharp; using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace osu.Game.Graphics namespace osu.Game.Graphics
{ {
@ -37,30 +37,26 @@ namespace osu.Game.Graphics
/// </summary> /// </summary>
public IBindable<bool> CursorVisibility => cursorVisibility; public IBindable<bool> CursorVisibility => cursorVisibility;
private Bindable<ScreenshotFormat> screenshotFormat; [Resolved]
private Bindable<bool> captureMenuCursor; private GameHost host { get; set; } = null!;
[Resolved] [Resolved]
private GameHost host { get; set; } private Clipboard clipboard { get; set; } = null!;
[Resolved] [Resolved]
private Clipboard clipboard { get; set; } private INotificationOverlay notificationOverlay { get; set; } = null!;
private Storage storage;
[Resolved] [Resolved]
private INotificationOverlay notificationOverlay { get; set; } private OsuConfigManager config { get; set; } = null!;
private Sample shutter; private Storage storage = null!;
private Sample? shutter;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config, Storage storage, AudioManager audio) private void load(Storage storage, AudioManager audio)
{ {
this.storage = storage.GetStorageForDirectory(@"screenshots"); this.storage = storage.GetStorageForDirectory(@"screenshots");
screenshotFormat = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat);
captureMenuCursor = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor);
shutter = audio.Samples.Get("UI/shutter"); shutter = audio.Samples.Get("UI/shutter");
} }
@ -72,7 +68,7 @@ namespace osu.Game.Graphics
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.TakeScreenshot: case GlobalAction.TakeScreenshot:
shutter.Play(); shutter?.Play();
TakeScreenshotAsync().FireAndForget(); TakeScreenshotAsync().FireAndForget();
return true; return true;
} }
@ -90,9 +86,12 @@ namespace osu.Game.Graphics
{ {
Interlocked.Increment(ref screenShotTasks); Interlocked.Increment(ref screenShotTasks);
ScreenshotFormat screenshotFormat = config.Get<ScreenshotFormat>(OsuSetting.ScreenshotFormat);
bool captureMenuCursor = config.Get<bool>(OsuSetting.ScreenshotCaptureMenuCursor);
try try
{ {
if (!captureMenuCursor.Value) if (!captureMenuCursor)
{ {
cursorVisibility.Value = false; cursorVisibility.Value = false;
@ -101,7 +100,7 @@ namespace osu.Game.Graphics
int framesWaited = 0; int framesWaited = 0;
using (var framesWaitedEvent = new ManualResetEventSlim(false)) using (ManualResetEventSlim framesWaitedEvent = new ManualResetEventSlim(false))
{ {
ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() =>
{ {
@ -117,17 +116,41 @@ namespace osu.Game.Graphics
} }
} }
using (var image = await host.TakeScreenshotAsync().ConfigureAwait(false)) using (Image<Rgba32>? image = await host.TakeScreenshotAsync().ConfigureAwait(false))
{ {
if (config.Get<ScalingMode>(OsuSetting.Scaling) == ScalingMode.Everything)
{
float posX = config.Get<float>(OsuSetting.ScalingPositionX);
float posY = config.Get<float>(OsuSetting.ScalingPositionY);
float sizeX = config.Get<float>(OsuSetting.ScalingSizeX);
float sizeY = config.Get<float>(OsuSetting.ScalingSizeY);
image.Mutate(m =>
{
Rectangle rect = new Rectangle(Point.Empty, m.GetCurrentSize());
// Reduce size by user scale settings...
int sx = (rect.Width - (int)(rect.Width * sizeX)) / 2;
int sy = (rect.Height - (int)(rect.Height * sizeY)) / 2;
rect.Inflate(-sx, -sy);
// ...then adjust the region based on their positional offset.
rect.X = (int)(rect.X * posX) * 2;
rect.Y = (int)(rect.Y * posY) * 2;
m.Crop(rect);
});
}
clipboard.SetImage(image); clipboard.SetImage(image);
(string filename, var stream) = getWritableStream(); (string? filename, Stream? stream) = getWritableStream(screenshotFormat);
if (filename == null) return; if (filename == null) return;
using (stream) using (stream)
{ {
switch (screenshotFormat.Value) switch (screenshotFormat)
{ {
case ScreenshotFormat.Png: case ScreenshotFormat.Png:
await image.SaveAsPngAsync(stream).ConfigureAwait(false); await image.SaveAsPngAsync(stream).ConfigureAwait(false);
@ -140,7 +163,7 @@ namespace osu.Game.Graphics
break; break;
default: default:
throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat.Value}."); throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat}.");
} }
} }
@ -164,12 +187,12 @@ namespace osu.Game.Graphics
private static readonly object filename_reservation_lock = new object(); private static readonly object filename_reservation_lock = new object();
private (string filename, Stream stream) getWritableStream() private (string? filename, Stream? stream) getWritableStream(ScreenshotFormat format)
{ {
lock (filename_reservation_lock) lock (filename_reservation_lock)
{ {
var dt = DateTime.Now; DateTime dt = DateTime.Now;
string fileExt = screenshotFormat.ToString().ToLowerInvariant(); string fileExt = format.ToString().ToLowerInvariant();
string withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}"; string withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}";
if (!storage.Exists(withoutIndex)) if (!storage.Exists(withoutIndex))