mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 19:05:37 +08:00
Merge pull request #1205 from peppy/song-select-context-menus
Add support for hiding individual beatmap difficulties
This commit is contained in:
commit
9a4cff8813
@ -1 +1 @@
|
|||||||
Subproject commit 167d5cda8f3ddae702ffc8d8d22dac67e48b509c
|
Subproject commit 2bd341b29d6a7ed864aa9c1c5fad4668dafe03a4
|
@ -52,6 +52,8 @@ namespace osu.Game.Beatmaps
|
|||||||
[JsonProperty("file_sha2")]
|
[JsonProperty("file_sha2")]
|
||||||
public string Hash { get; set; }
|
public string Hash { get; set; }
|
||||||
|
|
||||||
|
public bool Hidden { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MD5 is kept for legacy support (matching against replays, osu-web-10 etc.).
|
/// MD5 is kept for legacy support (matching against replays, osu-web-10 etc.).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -33,11 +33,21 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<BeatmapSetInfo> BeatmapSetAdded;
|
public event Action<BeatmapSetInfo> BeatmapSetAdded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when a single difficulty has been hidden.
|
||||||
|
/// </summary>
|
||||||
|
public event Action<BeatmapInfo> BeatmapHidden;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a <see cref="BeatmapSetInfo"/> is removed from the database.
|
/// Fired when a <see cref="BeatmapSetInfo"/> is removed from the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<BeatmapSetInfo> BeatmapSetRemoved;
|
public event Action<BeatmapSetInfo> BeatmapSetRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when a single difficulty has been restored.
|
||||||
|
/// </summary>
|
||||||
|
public event Action<BeatmapInfo> BeatmapRestored;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -71,6 +81,8 @@ namespace osu.Game.Beatmaps
|
|||||||
beatmaps = new BeatmapStore(connection);
|
beatmaps = new BeatmapStore(connection);
|
||||||
beatmaps.BeatmapSetAdded += s => BeatmapSetAdded?.Invoke(s);
|
beatmaps.BeatmapSetAdded += s => BeatmapSetAdded?.Invoke(s);
|
||||||
beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s);
|
beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s);
|
||||||
|
beatmaps.BeatmapHidden += b => BeatmapHidden?.Invoke(b);
|
||||||
|
beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b);
|
||||||
|
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
this.files = files;
|
this.files = files;
|
||||||
@ -162,24 +174,34 @@ namespace osu.Game.Beatmaps
|
|||||||
// If we have an ID then we already exist in the database.
|
// If we have an ID then we already exist in the database.
|
||||||
if (beatmapSetInfo.ID != 0) return;
|
if (beatmapSetInfo.ID != 0) return;
|
||||||
|
|
||||||
lock (beatmaps)
|
beatmaps.Add(beatmapSetInfo);
|
||||||
beatmaps.Add(beatmapSetInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a beatmap from the manager.
|
/// Delete a beatmap from the manager.
|
||||||
/// Is a no-op for already deleted beatmaps.
|
/// Is a no-op for already deleted beatmaps.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmapSet">The beatmap to delete.</param>
|
/// <param name="beatmapSet">The beatmap set to delete.</param>
|
||||||
public void Delete(BeatmapSetInfo beatmapSet)
|
public void Delete(BeatmapSetInfo beatmapSet)
|
||||||
{
|
{
|
||||||
lock (beatmaps)
|
if (!beatmaps.Delete(beatmapSet)) return;
|
||||||
if (!beatmaps.Delete(beatmapSet)) return;
|
|
||||||
|
|
||||||
if (!beatmapSet.Protected)
|
if (!beatmapSet.Protected)
|
||||||
files.Dereference(beatmapSet.Files.Select(f => f.FileInfo).ToArray());
|
files.Dereference(beatmapSet.Files.Select(f => f.FileInfo).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete a beatmap difficulty.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmap">The beatmap difficulty to hide.</param>
|
||||||
|
public void Hide(BeatmapInfo beatmap) => beatmaps.Hide(beatmap);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restore a beatmap difficulty.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmap">The beatmap difficulty to restore.</param>
|
||||||
|
public void Restore(BeatmapInfo beatmap) => beatmaps.Restore(beatmap);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a <see cref="BeatmapSetInfo"/> to a usable state if it has previously been deleted but not yet purged.
|
/// Returns a <see cref="BeatmapSetInfo"/> to a usable state if it has previously been deleted but not yet purged.
|
||||||
/// Is a no-op for already usable beatmaps.
|
/// Is a no-op for already usable beatmaps.
|
||||||
@ -187,8 +209,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <param name="beatmapSet">The beatmap to restore.</param>
|
/// <param name="beatmapSet">The beatmap to restore.</param>
|
||||||
public void Undelete(BeatmapSetInfo beatmapSet)
|
public void Undelete(BeatmapSetInfo beatmapSet)
|
||||||
{
|
{
|
||||||
lock (beatmaps)
|
if (!beatmaps.Undelete(beatmapSet)) return;
|
||||||
if (!beatmaps.Undelete(beatmapSet)) return;
|
|
||||||
|
|
||||||
if (!beatmapSet.Protected)
|
if (!beatmapSet.Protected)
|
||||||
files.Reference(beatmapSet.Files.Select(f => f.FileInfo).ToArray());
|
files.Reference(beatmapSet.Files.Select(f => f.FileInfo).ToArray());
|
||||||
@ -248,6 +269,13 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh an existing instance of a <see cref="BeatmapSetInfo"/> from the store.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmapSet">A stale instance.</param>
|
||||||
|
/// <returns>A fresh instance.</returns>
|
||||||
|
public BeatmapSetInfo Refresh(BeatmapSetInfo beatmapSet) => QueryBeatmapSet(s => s.ID == beatmapSet.ID);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a lookup query on available <see cref="BeatmapSetInfo"/>s.
|
/// Perform a lookup query on available <see cref="BeatmapSetInfo"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -255,7 +283,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <returns>Results from the provided query.</returns>
|
/// <returns>Results from the provided query.</returns>
|
||||||
public List<BeatmapSetInfo> QueryBeatmapSets(Expression<Func<BeatmapSetInfo, bool>> query)
|
public List<BeatmapSetInfo> QueryBeatmapSets(Expression<Func<BeatmapSetInfo, bool>> query)
|
||||||
{
|
{
|
||||||
lock (beatmaps) return beatmaps.QueryAndPopulate(query);
|
return beatmaps.QueryAndPopulate(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -265,15 +293,12 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <returns>The first result for the provided query, or null if no results were found.</returns>
|
/// <returns>The first result for the provided query, or null if no results were found.</returns>
|
||||||
public BeatmapInfo QueryBeatmap(Func<BeatmapInfo, bool> query)
|
public BeatmapInfo QueryBeatmap(Func<BeatmapInfo, bool> query)
|
||||||
{
|
{
|
||||||
lock (beatmaps)
|
BeatmapInfo set = beatmaps.Query<BeatmapInfo>().FirstOrDefault(query);
|
||||||
{
|
|
||||||
BeatmapInfo set = beatmaps.Query<BeatmapInfo>().FirstOrDefault(query);
|
|
||||||
|
|
||||||
if (set != null)
|
if (set != null)
|
||||||
beatmaps.Populate(set);
|
beatmaps.Populate(set);
|
||||||
|
|
||||||
return set;
|
return set;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -16,11 +16,14 @@ namespace osu.Game.Beatmaps
|
|||||||
public event Action<BeatmapSetInfo> BeatmapSetAdded;
|
public event Action<BeatmapSetInfo> BeatmapSetAdded;
|
||||||
public event Action<BeatmapSetInfo> BeatmapSetRemoved;
|
public event Action<BeatmapSetInfo> BeatmapSetRemoved;
|
||||||
|
|
||||||
|
public event Action<BeatmapInfo> BeatmapHidden;
|
||||||
|
public event Action<BeatmapInfo> BeatmapRestored;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of this store. Used for migrations (see <see cref="PerformMigration(int, int)"/>).
|
/// The current version of this store. Used for migrations (see <see cref="PerformMigration(int, int)"/>).
|
||||||
/// The initial version is 1.
|
/// The initial version is 1.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override int StoreVersion => 3;
|
protected override int StoreVersion => 4;
|
||||||
|
|
||||||
public BeatmapStore(SQLiteConnection connection)
|
public BeatmapStore(SQLiteConnection connection)
|
||||||
: base(connection)
|
: base(connection)
|
||||||
@ -81,6 +84,10 @@ namespace osu.Game.Beatmaps
|
|||||||
// Added MD5Hash column to BeatmapInfo
|
// Added MD5Hash column to BeatmapInfo
|
||||||
Connection.MigrateTable<BeatmapInfo>();
|
Connection.MigrateTable<BeatmapInfo>();
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
// Added Hidden column to BeatmapInfo
|
||||||
|
Connection.MigrateTable<BeatmapInfo>();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,7 +107,7 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a <see cref="BeatmapSetInfo"/> to the database.
|
/// Delete a <see cref="BeatmapSetInfo"/> from the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmapSet">The beatmap to delete.</param>
|
/// <param name="beatmapSet">The beatmap to delete.</param>
|
||||||
/// <returns>Whether the beatmap's <see cref="BeatmapSetInfo.DeletePending"/> was changed.</returns>
|
/// <returns>Whether the beatmap's <see cref="BeatmapSetInfo.DeletePending"/> was changed.</returns>
|
||||||
@ -131,6 +138,38 @@ namespace osu.Game.Beatmaps
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hide a <see cref="BeatmapInfo"/> in the database.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmap">The beatmap to hide.</param>
|
||||||
|
/// <returns>Whether the beatmap's <see cref="BeatmapInfo.Hidden"/> was changed.</returns>
|
||||||
|
public bool Hide(BeatmapInfo beatmap)
|
||||||
|
{
|
||||||
|
if (beatmap.Hidden) return false;
|
||||||
|
|
||||||
|
beatmap.Hidden = true;
|
||||||
|
Connection.Update(beatmap);
|
||||||
|
|
||||||
|
BeatmapHidden?.Invoke(beatmap);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restore a previously hidden <see cref="BeatmapInfo"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmap">The beatmap to restore.</param>
|
||||||
|
/// <returns>Whether the beatmap's <see cref="BeatmapInfo.Hidden"/> was changed.</returns>
|
||||||
|
public bool Restore(BeatmapInfo beatmap)
|
||||||
|
{
|
||||||
|
if (!beatmap.Hidden) return false;
|
||||||
|
|
||||||
|
beatmap.Hidden = false;
|
||||||
|
Connection.Update(beatmap);
|
||||||
|
|
||||||
|
BeatmapRestored?.Invoke(beatmap);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void cleanupPendingDeletions()
|
private void cleanupPendingDeletions()
|
||||||
{
|
{
|
||||||
Connection.RunInTransaction(() =>
|
Connection.RunInTransaction(() =>
|
||||||
|
@ -23,6 +23,12 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<BeatmapInfo> StartRequested;
|
public Action<BeatmapInfo> StartRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapSetInfo> DeleteRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapSetInfo> RestoreHiddenRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapInfo> HideDifficultyRequested;
|
||||||
|
|
||||||
public BeatmapSetHeader Header;
|
public BeatmapSetHeader Header;
|
||||||
|
|
||||||
private BeatmapGroupState state;
|
private BeatmapGroupState state;
|
||||||
@ -66,14 +72,17 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
Header = new BeatmapSetHeader(beatmap)
|
Header = new BeatmapSetHeader(beatmap)
|
||||||
{
|
{
|
||||||
GainedSelection = headerGainedSelection,
|
GainedSelection = headerGainedSelection,
|
||||||
|
DeleteRequested = b => DeleteRequested(b),
|
||||||
|
RestoreHiddenRequested = b => RestoreHiddenRequested(b),
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
};
|
};
|
||||||
|
|
||||||
BeatmapSet.Beatmaps = BeatmapSet.Beatmaps.OrderBy(b => b.StarDifficulty).ToList();
|
BeatmapSet.Beatmaps = BeatmapSet.Beatmaps.Where(b => !b.Hidden).OrderBy(b => b.StarDifficulty).ToList();
|
||||||
BeatmapPanels = BeatmapSet.Beatmaps.Select(b => new BeatmapPanel(b)
|
BeatmapPanels = BeatmapSet.Beatmaps.Select(b => new BeatmapPanel(b)
|
||||||
{
|
{
|
||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
GainedSelection = panelGainedSelection,
|
GainedSelection = panelGainedSelection,
|
||||||
|
HideRequested = p => HideDifficultyRequested?.Invoke(p),
|
||||||
StartRequested = p => { StartRequested?.Invoke(p.Beatmap); },
|
StartRequested = p => { StartRequested?.Invoke(p.Beatmap); },
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Backgrounds;
|
using osu.Game.Graphics.Backgrounds;
|
||||||
@ -14,16 +15,20 @@ using OpenTK.Graphics;
|
|||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Drawables
|
namespace osu.Game.Beatmaps.Drawables
|
||||||
{
|
{
|
||||||
public class BeatmapPanel : Panel
|
public class BeatmapPanel : Panel, IHasContextMenu
|
||||||
{
|
{
|
||||||
public BeatmapInfo Beatmap;
|
public BeatmapInfo Beatmap;
|
||||||
private readonly Sprite background;
|
private readonly Sprite background;
|
||||||
|
|
||||||
public Action<BeatmapPanel> GainedSelection;
|
public Action<BeatmapPanel> GainedSelection;
|
||||||
public Action<BeatmapPanel> StartRequested;
|
public Action<BeatmapPanel> StartRequested;
|
||||||
|
public Action<BeatmapPanel> EditRequested;
|
||||||
|
public Action<BeatmapInfo> HideRequested;
|
||||||
|
|
||||||
private readonly Triangles triangles;
|
private readonly Triangles triangles;
|
||||||
private readonly StarCounter starCounter;
|
private readonly StarCounter starCounter;
|
||||||
|
|
||||||
@ -148,5 +153,12 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MenuItem[] ContextMenuItems => new MenuItem[]
|
||||||
|
{
|
||||||
|
new OsuMenuItem("Play", MenuItemType.Highlighted, () => StartRequested?.Invoke(this)),
|
||||||
|
new OsuMenuItem("Edit", MenuItemType.Standard, () => EditRequested?.Invoke(this)),
|
||||||
|
new OsuMenuItem("Hide", MenuItemType.Destructive, () => HideRequested?.Invoke(Beatmap)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,22 +3,31 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Drawables
|
namespace osu.Game.Beatmaps.Drawables
|
||||||
{
|
{
|
||||||
public class BeatmapSetHeader : Panel
|
public class BeatmapSetHeader : Panel, IHasContextMenu
|
||||||
{
|
{
|
||||||
public Action<BeatmapSetHeader> GainedSelection;
|
public Action<BeatmapSetHeader> GainedSelection;
|
||||||
|
|
||||||
|
public Action<BeatmapSetInfo> DeleteRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapSetInfo> RestoreHiddenRequested;
|
||||||
|
|
||||||
private readonly SpriteText title;
|
private readonly SpriteText title;
|
||||||
private readonly SpriteText artist;
|
private readonly SpriteText artist;
|
||||||
|
|
||||||
@ -148,5 +157,23 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
foreach (var p in panels)
|
foreach (var p in panels)
|
||||||
difficultyIcons.Add(new DifficultyIcon(p.Beatmap));
|
difficultyIcons.Add(new DifficultyIcon(p.Beatmap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MenuItem[] ContextMenuItems
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<MenuItem> items = new List<MenuItem>();
|
||||||
|
|
||||||
|
if (State == PanelSelectedState.NotSelected)
|
||||||
|
items.Add(new OsuMenuItem("Expand", MenuItemType.Highlighted, () => State = PanelSelectedState.Selected));
|
||||||
|
|
||||||
|
if (beatmap.BeatmapSetInfo.Beatmaps.Any(b => b.Hidden))
|
||||||
|
items.Add(new OsuMenuItem("Restore all hidden", MenuItemType.Standard, () => RestoreHiddenRequested?.Invoke(beatmap.BeatmapSetInfo)));
|
||||||
|
|
||||||
|
items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, () => DeleteRequested?.Invoke(beatmap.BeatmapSetInfo)));
|
||||||
|
|
||||||
|
return items.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
|||||||
{
|
{
|
||||||
private OsuButton importButton;
|
private OsuButton importButton;
|
||||||
private OsuButton deleteButton;
|
private OsuButton deleteButton;
|
||||||
|
private OsuButton restoreButton;
|
||||||
|
|
||||||
protected override string Header => "General";
|
protected override string Header => "General";
|
||||||
|
|
||||||
@ -41,6 +42,20 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
|||||||
Task.Run(() => beatmaps.DeleteAll()).ContinueWith(t => Schedule(() => deleteButton.Enabled.Value = true));
|
Task.Run(() => beatmaps.DeleteAll()).ContinueWith(t => Schedule(() => deleteButton.Enabled.Value = true));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
restoreButton = new OsuButton
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Text = "Restore all hidden difficulties",
|
||||||
|
Action = () =>
|
||||||
|
{
|
||||||
|
restoreButton.Enabled.Value = false;
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
foreach (var b in beatmaps.QueryBeatmaps(b => b.Hidden))
|
||||||
|
beatmaps.Restore(b);
|
||||||
|
}).ContinueWith(t => Schedule(() => restoreButton.Enabled.Value = true));
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,17 +107,44 @@ namespace osu.Game.Screens.Select
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveBeatmap(BeatmapSetInfo beatmapSet)
|
public void RemoveBeatmap(BeatmapSetInfo beatmapSet) => removeGroup(groups.Find(b => b.BeatmapSet.ID == beatmapSet.ID));
|
||||||
|
|
||||||
|
internal void UpdateBeatmap(BeatmapInfo beatmap)
|
||||||
{
|
{
|
||||||
Schedule(delegate
|
// todo: this method should not run more than once for the same BeatmapSetInfo.
|
||||||
|
var set = manager.Refresh(beatmap.BeatmapSet);
|
||||||
|
|
||||||
|
// todo: this method should be smarter as to not recreate panels that haven't changed, etc.
|
||||||
|
var group = groups.Find(b => b.BeatmapSet.ID == set.ID);
|
||||||
|
|
||||||
|
if (group == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var newGroup = createGroup(set);
|
||||||
|
|
||||||
|
int i = groups.IndexOf(group);
|
||||||
|
groups.RemoveAt(i);
|
||||||
|
groups.Insert(i, newGroup);
|
||||||
|
|
||||||
|
if (selectedGroup == group && newGroup.BeatmapPanels.Count == 0)
|
||||||
|
selectedGroup = null;
|
||||||
|
|
||||||
|
Filter(null, false);
|
||||||
|
|
||||||
|
//check if we can/need to maintain our current selection.
|
||||||
|
if (selectedGroup == group && newGroup.BeatmapPanels.Count > 0)
|
||||||
{
|
{
|
||||||
removeGroup(groups.Find(b => b.BeatmapSet.ID == beatmapSet.ID));
|
var newSelection =
|
||||||
});
|
newGroup.BeatmapPanels.Find(p => p.Beatmap.ID == selectedPanel?.Beatmap.ID) ??
|
||||||
|
newGroup.BeatmapPanels[Math.Min(newGroup.BeatmapPanels.Count - 1, group.BeatmapPanels.IndexOf(selectedPanel))];
|
||||||
|
|
||||||
|
selectGroup(newGroup, newSelection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectBeatmap(BeatmapInfo beatmap, bool animated = true)
|
public void SelectBeatmap(BeatmapInfo beatmap, bool animated = true)
|
||||||
{
|
{
|
||||||
if (beatmap == null)
|
if (beatmap == null || beatmap.Hidden)
|
||||||
{
|
{
|
||||||
SelectNext();
|
SelectNext();
|
||||||
return;
|
return;
|
||||||
@ -140,6 +167,12 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
public Action StartRequested;
|
public Action StartRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapSetInfo> DeleteRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapSetInfo> RestoreRequested;
|
||||||
|
|
||||||
|
public Action<BeatmapInfo> HideDifficultyRequested;
|
||||||
|
|
||||||
public void SelectNext(int direction = 1, bool skipDifficulties = true)
|
public void SelectNext(int direction = 1, bool skipDifficulties = true)
|
||||||
{
|
{
|
||||||
if (groups.All(g => g.State == BeatmapGroupState.Hidden))
|
if (groups.All(g => g.State == BeatmapGroupState.Hidden))
|
||||||
@ -306,6 +339,9 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
SelectionChanged = (g, p) => selectGroup(g, p),
|
SelectionChanged = (g, p) => selectGroup(g, p),
|
||||||
StartRequested = b => StartRequested?.Invoke(),
|
StartRequested = b => StartRequested?.Invoke(),
|
||||||
|
DeleteRequested = b => DeleteRequested?.Invoke(b),
|
||||||
|
RestoreHiddenRequested = s => RestoreRequested?.Invoke(s),
|
||||||
|
HideDifficultyRequested = b => HideDifficultyRequested?.Invoke(b),
|
||||||
State = BeatmapGroupState.Collapsed
|
State = BeatmapGroupState.Collapsed
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
@ -19,23 +18,18 @@ namespace osu.Game.Screens.Select
|
|||||||
manager = beatmapManager;
|
manager = beatmapManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BeatmapDeleteDialog(WorkingBeatmap beatmap)
|
public BeatmapDeleteDialog(BeatmapSetInfo beatmap)
|
||||||
{
|
{
|
||||||
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
|
BodyText = $@"{beatmap.Metadata?.Artist} - {beatmap.Metadata?.Title}";
|
||||||
|
|
||||||
Icon = FontAwesome.fa_trash_o;
|
Icon = FontAwesome.fa_trash_o;
|
||||||
HeaderText = @"Confirm deletion of";
|
HeaderText = @"Confirm deletion of";
|
||||||
BodyText = $@"{beatmap.Metadata?.Artist} - {beatmap.Metadata?.Title}";
|
|
||||||
Buttons = new PopupDialogButton[]
|
Buttons = new PopupDialogButton[]
|
||||||
{
|
{
|
||||||
new PopupDialogOkButton
|
new PopupDialogOkButton
|
||||||
{
|
{
|
||||||
Text = @"Yes. Totally. Delete it.",
|
Text = @"Yes. Totally. Delete it.",
|
||||||
Action = () =>
|
Action = () => manager.Delete(beatmap),
|
||||||
{
|
|
||||||
beatmap.Dispose();
|
|
||||||
manager.Delete(beatmap.BeatmapSetInfo);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
new PopupDialogCancelButton
|
new PopupDialogCancelButton
|
||||||
{
|
{
|
||||||
|
@ -54,13 +54,11 @@ namespace osu.Game.Screens.Select
|
|||||||
ValidForResume = false;
|
ValidForResume = false;
|
||||||
Push(new Editor());
|
Push(new Editor());
|
||||||
}, Key.Number3);
|
}, Key.Number3);
|
||||||
|
|
||||||
Beatmap.ValueChanged += beatmap_ValueChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void beatmap_ValueChanged(WorkingBeatmap beatmap)
|
protected override void UpdateBeatmap(WorkingBeatmap beatmap)
|
||||||
{
|
{
|
||||||
if (!IsCurrentScreen) return;
|
base.UpdateBeatmap(beatmap);
|
||||||
|
|
||||||
beatmap.Mods.BindTo(modSelect.SelectedMods);
|
beatmap.Mods.BindTo(modSelect.SelectedMods);
|
||||||
|
|
||||||
|
@ -106,6 +106,9 @@ namespace osu.Game.Screens.Select
|
|||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.CentreRight,
|
||||||
SelectionChanged = carouselSelectionChanged,
|
SelectionChanged = carouselSelectionChanged,
|
||||||
BeatmapsChanged = carouselBeatmapsLoaded,
|
BeatmapsChanged = carouselBeatmapsLoaded,
|
||||||
|
DeleteRequested = b => promptDelete(b),
|
||||||
|
RestoreRequested = s => { foreach (var b in s.Beatmaps) manager.Restore(b); },
|
||||||
|
HideDifficultyRequested = b => manager.Hide(b),
|
||||||
StartRequested = () => carouselRaisedStart(),
|
StartRequested = () => carouselRaisedStart(),
|
||||||
});
|
});
|
||||||
Add(FilterControl = new FilterControl
|
Add(FilterControl = new FilterControl
|
||||||
@ -163,7 +166,7 @@ namespace osu.Game.Screens.Select
|
|||||||
Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2);
|
Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2);
|
||||||
Footer.AddButton(@"options", colours.Blue, BeatmapOptions.ToggleVisibility, Key.F3);
|
Footer.AddButton(@"options", colours.Blue, BeatmapOptions.ToggleVisibility, Key.F3);
|
||||||
|
|
||||||
BeatmapOptions.AddButton(@"Delete", @"Beatmap", FontAwesome.fa_trash, colours.Pink, promptDelete, Key.Number4, float.MaxValue);
|
BeatmapOptions.AddButton(@"Delete", @"Beatmap", FontAwesome.fa_trash, colours.Pink, () => promptDelete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manager == null)
|
if (manager == null)
|
||||||
@ -174,6 +177,8 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
manager.BeatmapSetAdded += onBeatmapSetAdded;
|
manager.BeatmapSetAdded += onBeatmapSetAdded;
|
||||||
manager.BeatmapSetRemoved += onBeatmapSetRemoved;
|
manager.BeatmapSetRemoved += onBeatmapSetRemoved;
|
||||||
|
manager.BeatmapHidden += onBeatmapHidden;
|
||||||
|
manager.BeatmapRestored += onBeatmapRestored;
|
||||||
|
|
||||||
dialogOverlay = dialog;
|
dialogOverlay = dialog;
|
||||||
|
|
||||||
@ -190,6 +195,9 @@ namespace osu.Game.Screens.Select
|
|||||||
carousel.AllowSelection = !Beatmap.Disabled;
|
carousel.AllowSelection = !Beatmap.Disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onBeatmapRestored(BeatmapInfo b) => carousel.UpdateBeatmap(b);
|
||||||
|
private void onBeatmapHidden(BeatmapInfo b) => carousel.UpdateBeatmap(b);
|
||||||
|
|
||||||
private void carouselBeatmapsLoaded()
|
private void carouselBeatmapsLoaded()
|
||||||
{
|
{
|
||||||
if (Beatmap.Value.BeatmapSetInfo?.DeletePending == false)
|
if (Beatmap.Value.BeatmapSetInfo?.DeletePending == false)
|
||||||
@ -236,7 +244,7 @@ namespace osu.Game.Screens.Select
|
|||||||
ensurePlayingSelected(preview);
|
ensurePlayingSelected(preview);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeBackground(Beatmap.Value);
|
UpdateBeatmap(Beatmap.Value);
|
||||||
};
|
};
|
||||||
|
|
||||||
selectionChangedDebounce?.Cancel();
|
selectionChangedDebounce?.Cancel();
|
||||||
@ -248,7 +256,8 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
if (beatmap == null)
|
if (beatmap == null)
|
||||||
{
|
{
|
||||||
performLoad();
|
if (!Beatmap.IsDefault)
|
||||||
|
performLoad();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -303,7 +312,7 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
if (Beatmap != null && !Beatmap.Value.BeatmapSetInfo.DeletePending)
|
if (Beatmap != null && !Beatmap.Value.BeatmapSetInfo.DeletePending)
|
||||||
{
|
{
|
||||||
changeBackground(Beatmap);
|
UpdateBeatmap(Beatmap);
|
||||||
ensurePlayingSelected();
|
ensurePlayingSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +358,12 @@ namespace osu.Game.Screens.Select
|
|||||||
initialAddSetsTask?.Cancel();
|
initialAddSetsTask?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeBackground(WorkingBeatmap beatmap)
|
/// <summary>
|
||||||
|
/// Allow components in SongSelect to update their loaded beatmap details.
|
||||||
|
/// This is a debounced call (unlike directly binding to WorkingBeatmap.ValueChanged).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmap">The working beatmap.</param>
|
||||||
|
protected virtual void UpdateBeatmap(WorkingBeatmap beatmap)
|
||||||
{
|
{
|
||||||
var backgroundModeBeatmap = Background as BackgroundScreenBeatmap;
|
var backgroundModeBeatmap = Background as BackgroundScreenBeatmap;
|
||||||
if (backgroundModeBeatmap != null)
|
if (backgroundModeBeatmap != null)
|
||||||
@ -377,10 +391,7 @@ namespace osu.Game.Screens.Select
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBeatmapSet(BeatmapSetInfo beatmapSet)
|
private void addBeatmapSet(BeatmapSetInfo beatmapSet) => carousel.AddBeatmap(beatmapSet);
|
||||||
{
|
|
||||||
carousel.AddBeatmap(beatmapSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeBeatmapSet(BeatmapSetInfo beatmapSet)
|
private void removeBeatmapSet(BeatmapSetInfo beatmapSet)
|
||||||
{
|
{
|
||||||
@ -389,10 +400,12 @@ namespace osu.Game.Screens.Select
|
|||||||
Beatmap.SetDefault();
|
Beatmap.SetDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void promptDelete()
|
private void promptDelete(BeatmapSetInfo beatmap)
|
||||||
{
|
{
|
||||||
if (Beatmap != null && !Beatmap.IsDefault)
|
if (beatmap == null)
|
||||||
dialogOverlay?.Push(new BeatmapDeleteDialog(Beatmap));
|
return;
|
||||||
|
|
||||||
|
dialogOverlay?.Push(new BeatmapDeleteDialog(beatmap));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||||
@ -408,7 +421,8 @@ namespace osu.Game.Screens.Select
|
|||||||
case Key.Delete:
|
case Key.Delete:
|
||||||
if (state.Keyboard.ShiftPressed)
|
if (state.Keyboard.ShiftPressed)
|
||||||
{
|
{
|
||||||
promptDelete();
|
if (!Beatmap.IsDefault)
|
||||||
|
promptDelete(Beatmap.Value.BeatmapSetInfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user