mirror of
https://github.com/ppy/osu.git
synced 2026-05-20 00:20:21 +08:00
Merge pull request #36101 from bdach/guest-difficulty-export
Add explicit menu item for exporting guest difficulties from editor
This commit is contained in:
@@ -476,9 +476,11 @@ namespace osu.Game.Beatmaps
|
||||
public Task<ExternalEditOperation<BeatmapSetInfo>> BeginExternalEditing(BeatmapSetInfo model) =>
|
||||
beatmapImporter.BeginExternalEditing(model);
|
||||
|
||||
public Task Export(BeatmapSetInfo beatmap) => beatmapExporter.ExportAsync(beatmap.ToLive(Realm));
|
||||
public Task Export(BeatmapSetInfo beatmapSet) => beatmapExporter.ExportAsync(beatmapSet.ToLive(Realm));
|
||||
|
||||
public Task ExportLegacy(BeatmapSetInfo beatmap) => legacyBeatmapExporter.ExportAsync(beatmap.ToLive(Realm));
|
||||
public Task ExportLegacy(BeatmapSetInfo beatmapSet) => legacyBeatmapExporter.ExportAsync(beatmapSet.ToLive(Realm));
|
||||
|
||||
public Task ExportLegacy(BeatmapInfo beatmap) => legacyBeatmapExporter.ExportAsync(beatmap.ToLive(Realm));
|
||||
|
||||
private void updateHashAndMarkDirty(BeatmapSetInfo setInfo)
|
||||
{
|
||||
|
||||
@@ -2,17 +2,22 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Database
|
||||
@@ -175,5 +180,54 @@ namespace osu.Game.Database
|
||||
}
|
||||
|
||||
protected override string FileExtension => @".osz";
|
||||
|
||||
public Task ExportAsync(Live<BeatmapInfo> beatmap) => Task.Run(() =>
|
||||
{
|
||||
string itemFilename = Path.GetFileNameWithoutExtension(beatmap.PerformRead(s => s.File!.Filename.GetValidFilename()));
|
||||
const string osu_extension = @".osu";
|
||||
|
||||
if (itemFilename.Length > MAX_FILENAME_LENGTH - osu_extension.Length)
|
||||
itemFilename = itemFilename.Remove(MAX_FILENAME_LENGTH - osu_extension.Length);
|
||||
|
||||
IEnumerable<string> existingExports = ExportStorage
|
||||
.GetFiles(string.Empty, $"{itemFilename}*{osu_extension}")
|
||||
.Concat(ExportStorage.GetDirectories(string.Empty));
|
||||
|
||||
string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{osu_extension}");
|
||||
|
||||
ProgressNotification notification = new ProgressNotification
|
||||
{
|
||||
State = ProgressNotificationState.Active,
|
||||
Text = $"Exporting {itemFilename}...",
|
||||
};
|
||||
|
||||
PostNotification?.Invoke(notification);
|
||||
|
||||
try
|
||||
{
|
||||
beatmap.PerformRead(b =>
|
||||
{
|
||||
using var exportStream = ExportStorage.CreateFileSafely(filename);
|
||||
using var inputFile = GetFileContents(b.BeatmapSet!, b.File!);
|
||||
|
||||
if (inputFile == null)
|
||||
throw new InvalidOperationException($"Beatmap file {b.File!.Filename} could not be opened!");
|
||||
|
||||
inputFile.CopyTo(exportStream);
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
notification.State = ProgressNotificationState.Cancelled;
|
||||
|
||||
// cleanup if export is failed or canceled.
|
||||
ExportStorage.Delete(filename);
|
||||
throw;
|
||||
}
|
||||
|
||||
notification.CompletionText = $"Exported {itemFilename}! Click to view.";
|
||||
notification.CompletionClickAction = () => ExportStorage.PresentFileExternally(filename);
|
||||
notification.State = ProgressNotificationState.Completed;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ namespace osu.Game.Database
|
||||
protected abstract string FileExtension { get; }
|
||||
|
||||
protected readonly Storage UserFileStorage;
|
||||
private readonly Storage exportStorage;
|
||||
protected readonly Storage ExportStorage;
|
||||
|
||||
public Action<Notification>? PostNotification { get; set; }
|
||||
|
||||
protected LegacyExporter(Storage storage)
|
||||
{
|
||||
exportStorage = (storage as OsuStorage)?.GetExportStorage() ?? storage.GetStorageForDirectory(@"exports");
|
||||
ExportStorage = (storage as OsuStorage)?.GetExportStorage() ?? storage.GetStorageForDirectory(@"exports");
|
||||
UserFileStorage = storage.GetStorageForDirectory(@"files");
|
||||
}
|
||||
|
||||
@@ -74,9 +74,9 @@ namespace osu.Game.Database
|
||||
if (itemFilename.Length > MAX_FILENAME_LENGTH - FileExtension.Length)
|
||||
itemFilename = itemFilename.Remove(MAX_FILENAME_LENGTH - FileExtension.Length);
|
||||
|
||||
IEnumerable<string> existingExports = exportStorage
|
||||
IEnumerable<string> existingExports = ExportStorage
|
||||
.GetFiles(string.Empty, $"{itemFilename}*{FileExtension}")
|
||||
.Concat(exportStorage.GetDirectories(string.Empty));
|
||||
.Concat(ExportStorage.GetDirectories(string.Empty));
|
||||
|
||||
string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}");
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace osu.Game.Database
|
||||
|
||||
try
|
||||
{
|
||||
using (var stream = exportStorage.CreateFileSafely(filename))
|
||||
using (var stream = ExportStorage.CreateFileSafely(filename))
|
||||
{
|
||||
await ExportToStreamAsync(model, stream, notification, linkedSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
@@ -102,12 +102,12 @@ namespace osu.Game.Database
|
||||
notification.State = ProgressNotificationState.Cancelled;
|
||||
|
||||
// cleanup if export is failed or canceled.
|
||||
exportStorage.Delete(filename);
|
||||
ExportStorage.Delete(filename);
|
||||
throw;
|
||||
}
|
||||
|
||||
notification.CompletionText = $"Exported {itemFilename}! Click to view.";
|
||||
notification.CompletionClickAction = () => exportStorage.PresentFileExternally(filename);
|
||||
notification.CompletionClickAction = () => ExportStorage.PresentFileExternally(filename);
|
||||
notification.State = ProgressNotificationState.Completed;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,11 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString ExportForCompatibility => new TranslatableString(getKey(@"export_for_compatibility"), @"For compatibility (.osz)");
|
||||
|
||||
/// <summary>
|
||||
/// "Guest difficulty (.osu)"
|
||||
/// </summary>
|
||||
public static LocalisableString ExportGuestDifficulty => new TranslatableString(getKey(@"export_guest_difficulty"), @"Guest difficulty (.osu)");
|
||||
|
||||
/// <summary>
|
||||
/// "Create new difficulty"
|
||||
/// </summary>
|
||||
|
||||
@@ -1329,8 +1329,9 @@ namespace osu.Game.Screens.Edit
|
||||
{
|
||||
var exportItems = new List<MenuItem>
|
||||
{
|
||||
new EditorMenuItem(EditorStrings.ExportForEditing, MenuItemType.Standard, () => exportBeatmap(false)),
|
||||
new EditorMenuItem(EditorStrings.ExportForCompatibility, MenuItemType.Standard, () => exportBeatmap(true)),
|
||||
new EditorMenuItem(EditorStrings.ExportForEditing, MenuItemType.Standard, () => runExport(manager => manager.Export(Beatmap.Value.BeatmapSetInfo))),
|
||||
new EditorMenuItem(EditorStrings.ExportForCompatibility, MenuItemType.Standard, () => runExport(manager => manager.ExportLegacy(Beatmap.Value.BeatmapSetInfo))),
|
||||
new EditorMenuItem(EditorStrings.ExportGuestDifficulty, MenuItemType.Standard, () => runExport(manager => manager.ExportLegacy(Beatmap.Value.BeatmapInfo))),
|
||||
};
|
||||
|
||||
return new EditorMenuItem(CommonStrings.Export) { Items = exportItems };
|
||||
@@ -1396,7 +1397,7 @@ namespace osu.Game.Screens.Edit
|
||||
void startSubmission() => this.Push(new BeatmapSubmissionScreen());
|
||||
}
|
||||
|
||||
private void exportBeatmap(bool legacy)
|
||||
private void runExport(Func<BeatmapManager, Task> exportAction)
|
||||
{
|
||||
if (HasUnsavedChanges)
|
||||
{
|
||||
@@ -1405,20 +1406,12 @@ namespace osu.Game.Screens.Edit
|
||||
if (!Save())
|
||||
return Task.CompletedTask;
|
||||
|
||||
return runExport();
|
||||
return exportAction.Invoke(beatmapManager);
|
||||
})));
|
||||
}
|
||||
else
|
||||
{
|
||||
attemptAsyncMutationOperation(runExport);
|
||||
}
|
||||
|
||||
Task runExport()
|
||||
{
|
||||
if (legacy)
|
||||
return beatmapManager.ExportLegacy(Beatmap.Value.BeatmapSetInfo);
|
||||
else
|
||||
return beatmapManager.Export(Beatmap.Value.BeatmapSetInfo);
|
||||
attemptAsyncMutationOperation(() => exportAction(beatmapManager));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user