2020-04-30 12:45:21 +02:00
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Threading.Tasks;
|
2021-06-09 22:19:39 +02:00
|
|
|
using Content.Client.Viewport;
|
2020-04-30 12:45:21 +02:00
|
|
|
using Content.Shared.Input;
|
2021-02-11 01:13:03 -08:00
|
|
|
using Robust.Client.Graphics;
|
|
|
|
|
using Robust.Client.Input;
|
2021-04-19 09:52:40 +02:00
|
|
|
using Robust.Client.State;
|
2021-02-11 01:13:03 -08:00
|
|
|
using Robust.Shared.ContentPack;
|
2020-07-06 14:27:03 -07:00
|
|
|
using Robust.Shared.Input.Binding;
|
2020-04-30 12:45:21 +02:00
|
|
|
using Robust.Shared.IoC;
|
|
|
|
|
using Robust.Shared.Log;
|
|
|
|
|
using Robust.Shared.Utility;
|
|
|
|
|
using SixLabors.ImageSharp;
|
2021-04-19 09:52:40 +02:00
|
|
|
using SixLabors.ImageSharp.PixelFormats;
|
2020-04-30 12:45:21 +02:00
|
|
|
|
2021-06-09 22:19:39 +02:00
|
|
|
namespace Content.Client.Screenshot
|
2020-04-30 12:45:21 +02:00
|
|
|
{
|
2022-02-16 00:23:23 -07:00
|
|
|
internal sealed class ScreenshotHook : IScreenshotHook
|
2020-04-30 12:45:21 +02:00
|
|
|
{
|
2020-11-27 11:00:49 +01:00
|
|
|
private static readonly ResourcePath BaseScreenshotPath = new("/Screenshots");
|
2020-04-30 12:45:21 +02:00
|
|
|
|
2021-03-10 14:48:29 +01:00
|
|
|
[Dependency] private readonly IInputManager _inputManager = default!;
|
|
|
|
|
[Dependency] private readonly IClyde _clyde = default!;
|
|
|
|
|
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
2021-04-19 09:52:40 +02:00
|
|
|
[Dependency] private readonly IStateManager _stateManager = default!;
|
2020-04-30 12:45:21 +02:00
|
|
|
|
|
|
|
|
public void Initialize()
|
|
|
|
|
{
|
|
|
|
|
_inputManager.SetInputCommand(ContentKeyFunctions.TakeScreenshot, InputCmdHandler.FromDelegate(_ =>
|
|
|
|
|
{
|
2021-04-19 09:52:40 +02:00
|
|
|
_clyde.Screenshot(ScreenshotType.Final, Take);
|
2020-04-30 12:45:21 +02:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
_inputManager.SetInputCommand(ContentKeyFunctions.TakeScreenshotNoUI, InputCmdHandler.FromDelegate(_ =>
|
|
|
|
|
{
|
2021-04-19 09:52:40 +02:00
|
|
|
if (_stateManager.CurrentState is IMainViewportState state)
|
|
|
|
|
{
|
|
|
|
|
state.Viewport.Viewport.Screenshot(Take);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.InfoS("screenshot", "Can't take no-UI screenshot: current state is not GameScreen");
|
|
|
|
|
}
|
2020-04-30 12:45:21 +02:00
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-19 09:52:40 +02:00
|
|
|
private async void Take<T>(Image<T> screenshot) where T : unmanaged, IPixel<T>
|
2020-04-30 12:45:21 +02:00
|
|
|
{
|
|
|
|
|
var time = DateTime.Now.ToString("yyyy-M-dd_HH.mm.ss");
|
|
|
|
|
|
|
|
|
|
if (!_resourceManager.UserData.IsDir(BaseScreenshotPath))
|
|
|
|
|
{
|
|
|
|
|
_resourceManager.UserData.CreateDir(BaseScreenshotPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < 5; i++)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var filename = time;
|
|
|
|
|
|
|
|
|
|
if (i != 0)
|
|
|
|
|
{
|
|
|
|
|
filename = $"{filename}-{i}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await using var file =
|
2020-09-01 23:53:49 +02:00
|
|
|
_resourceManager.UserData.Open(BaseScreenshotPath / $"{filename}.png", FileMode.CreateNew, FileAccess.Write, FileShare.None);
|
2020-04-30 12:45:21 +02:00
|
|
|
|
|
|
|
|
await Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
// Saving takes forever, so don't hang the game on it.
|
|
|
|
|
screenshot.SaveAsPng(file);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Logger.InfoS("screenshot", "Screenshot taken as {0}.png", filename);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
catch (IOException e)
|
|
|
|
|
{
|
|
|
|
|
Logger.WarningS("screenshot", "Failed to save screenshot, retrying?:\n{0}", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logger.ErrorS("screenshot", "Unable to save screenshot.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public interface IScreenshotHook
|
|
|
|
|
{
|
|
|
|
|
void Initialize();
|
|
|
|
|
}
|
|
|
|
|
}
|