mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 09:27:29 +08:00
Merge branch 'master' into multiplayer-participant-rank
This commit is contained in:
commit
b68dbbceff
@ -165,10 +165,10 @@ namespace osu.Game.Tests.Online
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, CancellationToken cancellationToken = default)
|
||||
public override async Task<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await AllowImport.Task;
|
||||
return await (CurrentImportTask = base.Import(item, archive, cancellationToken));
|
||||
return await (CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,8 +277,7 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
userId.Value = user.Id.ToString();
|
||||
userId.BindValueChanged(idString =>
|
||||
{
|
||||
if (!(int.TryParse(idString.NewValue, out var parsed)))
|
||||
return;
|
||||
int.TryParse(idString.NewValue, out var parsed);
|
||||
|
||||
user.Id = parsed;
|
||||
|
||||
|
@ -217,6 +217,8 @@ namespace osu.Game.Tournament
|
||||
|
||||
req.Success += res =>
|
||||
{
|
||||
user.Id = res.Id;
|
||||
|
||||
user.Username = res.Username;
|
||||
user.Statistics = res.Statistics;
|
||||
user.Country = res.Country;
|
||||
@ -225,7 +227,11 @@ namespace osu.Game.Tournament
|
||||
success?.Invoke();
|
||||
};
|
||||
|
||||
req.Failure += _ => failure?.Invoke();
|
||||
req.Failure += _ =>
|
||||
{
|
||||
user.Id = 1;
|
||||
failure?.Invoke();
|
||||
};
|
||||
|
||||
if (immediate)
|
||||
API.Perform(req);
|
||||
|
@ -27,6 +27,8 @@ namespace osu.Game.Audio
|
||||
|
||||
protected TrackManagerPreviewTrack CurrentTrack;
|
||||
|
||||
private readonly BindableNumber<double> globalTrackVolumeAdjust = new BindableNumber<double>(OsuGameBase.GLOBAL_TRACK_VOLUME_ADJUST);
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -35,6 +37,7 @@ namespace osu.Game.Audio
|
||||
trackStore = new PreviewTrackStore(new OnlineStore());
|
||||
|
||||
audio.AddItem(trackStore);
|
||||
trackStore.AddAdjustment(AdjustableProperty.Volume, globalTrackVolumeAdjust);
|
||||
trackStore.AddAdjustment(AdjustableProperty.Volume, audio.VolumeTrack);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,12 @@ namespace osu.Game.Beatmaps
|
||||
[JsonProperty(@"tags")]
|
||||
public string Tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time in milliseconds to begin playing the track for preview purposes.
|
||||
/// If -1, the track should begin playing at 40% of its length.
|
||||
/// </summary>
|
||||
public int PreviewTime { get; set; }
|
||||
|
||||
public string AudioFile { get; set; }
|
||||
public string BackgroundFile { get; set; }
|
||||
|
||||
|
@ -266,6 +266,26 @@ namespace osu.Game.Beatmaps
|
||||
[NotNull]
|
||||
public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the correct track restart point from beatmap metadata and sets looping to enabled.
|
||||
/// </summary>
|
||||
public void PrepareTrackForPreviewLooping()
|
||||
{
|
||||
Track.Looping = true;
|
||||
Track.RestartPoint = Metadata.PreviewTime;
|
||||
|
||||
if (Track.RestartPoint == -1)
|
||||
{
|
||||
if (!Track.IsLoaded)
|
||||
{
|
||||
// force length to be populated (https://github.com/ppy/osu-framework/issues/4202)
|
||||
Track.Seek(Track.CurrentTime);
|
||||
}
|
||||
|
||||
Track.RestartPoint = 0.4f * Track.Length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transfer a valid audio track into this working beatmap. Used as an optimisation to avoid reload / track swap
|
||||
/// across difficulties in the same beatmap set.
|
||||
|
@ -29,6 +29,14 @@ namespace osu.Game.Collections
|
||||
/// </summary>
|
||||
protected virtual bool ShowManageCollectionsItem => true;
|
||||
|
||||
private readonly BindableWithCurrent<CollectionFilterMenuItem> current = new BindableWithCurrent<CollectionFilterMenuItem>();
|
||||
|
||||
public new Bindable<CollectionFilterMenuItem> Current
|
||||
{
|
||||
get => current.Current;
|
||||
set => current.Current = value;
|
||||
}
|
||||
|
||||
private readonly IBindableList<BeatmapCollection> collections = new BindableList<BeatmapCollection>();
|
||||
private readonly IBindableList<BeatmapInfo> beatmaps = new BindableList<BeatmapInfo>();
|
||||
private readonly BindableList<CollectionFilterMenuItem> filters = new BindableList<CollectionFilterMenuItem>();
|
||||
@ -36,25 +44,28 @@ namespace osu.Game.Collections
|
||||
[Resolved(CanBeNull = true)]
|
||||
private ManageCollectionsDialog manageCollectionsDialog { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private CollectionManager collectionManager { get; set; }
|
||||
|
||||
public CollectionFilterDropdown()
|
||||
{
|
||||
ItemSource = filters;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(permitNulls: true)]
|
||||
private void load([CanBeNull] CollectionManager collectionManager)
|
||||
{
|
||||
if (collectionManager != null)
|
||||
collections.BindTo(collectionManager.Collections);
|
||||
|
||||
collections.CollectionChanged += (_, __) => collectionsChanged();
|
||||
collectionsChanged();
|
||||
Current.Value = new AllBeatmapsCollectionFilterMenuItem();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
if (collectionManager != null)
|
||||
collections.BindTo(collectionManager.Collections);
|
||||
|
||||
// Dropdown has logic which triggers a change on the bindable with every change to the contained items.
|
||||
// This is not desirable here, as it leads to multiple filter operations running even though nothing has changed.
|
||||
// An extra bindable is enough to subvert this behaviour.
|
||||
base.Current = Current;
|
||||
|
||||
collections.BindCollectionChanged((_, __) => collectionsChanged(), true);
|
||||
Current.BindValueChanged(filterChanged, true);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
@ -9,7 +10,7 @@ namespace osu.Game.Collections
|
||||
/// <summary>
|
||||
/// A <see cref="BeatmapCollection"/> filter.
|
||||
/// </summary>
|
||||
public class CollectionFilterMenuItem
|
||||
public class CollectionFilterMenuItem : IEquatable<CollectionFilterMenuItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// The collection to filter beatmaps from.
|
||||
@ -33,6 +34,11 @@ namespace osu.Game.Collections
|
||||
Collection = collection;
|
||||
CollectionName = Collection?.Name.GetBoundCopy() ?? new Bindable<string>("All beatmaps");
|
||||
}
|
||||
|
||||
public bool Equals(CollectionFilterMenuItem other)
|
||||
=> other != null && CollectionName.Value == other.CollectionName.Value;
|
||||
|
||||
public override int GetHashCode() => CollectionName.Value.GetHashCode();
|
||||
}
|
||||
|
||||
public class AllBeatmapsCollectionFilterMenuItem : CollectionFilterMenuItem
|
||||
|
@ -139,35 +139,43 @@ namespace osu.Game.Collections
|
||||
PostNotification?.Invoke(notification);
|
||||
|
||||
var collection = readCollections(stream, notification);
|
||||
bool importCompleted = false;
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
importCollections(collection);
|
||||
importCompleted = true;
|
||||
});
|
||||
|
||||
while (!IsDisposed && !importCompleted)
|
||||
await Task.Delay(10);
|
||||
await importCollections(collection);
|
||||
|
||||
notification.CompletionText = $"Imported {collection.Count} collections";
|
||||
notification.State = ProgressNotificationState.Completed;
|
||||
}
|
||||
|
||||
private void importCollections(List<BeatmapCollection> newCollections)
|
||||
private Task importCollections(List<BeatmapCollection> newCollections)
|
||||
{
|
||||
foreach (var newCol in newCollections)
|
||||
{
|
||||
var existing = Collections.FirstOrDefault(c => c.Name == newCol.Name);
|
||||
if (existing == null)
|
||||
Collections.Add(existing = new BeatmapCollection { Name = { Value = newCol.Name.Value } });
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
foreach (var newBeatmap in newCol.Beatmaps)
|
||||
Schedule(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!existing.Beatmaps.Contains(newBeatmap))
|
||||
existing.Beatmaps.Add(newBeatmap);
|
||||
foreach (var newCol in newCollections)
|
||||
{
|
||||
var existing = Collections.FirstOrDefault(c => c.Name == newCol.Name);
|
||||
if (existing == null)
|
||||
Collections.Add(existing = new BeatmapCollection { Name = { Value = newCol.Name.Value } });
|
||||
|
||||
foreach (var newBeatmap in newCol.Beatmaps)
|
||||
{
|
||||
if (!existing.Beatmaps.Contains(newBeatmap))
|
||||
existing.Beatmaps.Add(newBeatmap);
|
||||
}
|
||||
}
|
||||
|
||||
tcs.SetResult(true);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(e, "Failed to import collection.");
|
||||
tcs.SetException(e);
|
||||
}
|
||||
});
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
private List<BeatmapCollection> readCollections(Stream stream, ProgressNotification notification = null)
|
||||
|
@ -38,6 +38,11 @@ namespace osu.Game.Database
|
||||
{
|
||||
private const int import_queue_request_concurrency = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The size of a batch import operation before considering it a lower priority operation.
|
||||
/// </summary>
|
||||
private const int low_priority_import_batch_size = 1;
|
||||
|
||||
/// <summary>
|
||||
/// A singleton scheduler shared by all <see cref="ArchiveModelManager{TModel,TFileModel}"/>.
|
||||
/// </summary>
|
||||
@ -47,6 +52,13 @@ namespace osu.Game.Database
|
||||
/// </remarks>
|
||||
private static readonly ThreadedTaskScheduler import_scheduler = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(ArchiveModelManager<TModel, TFileModel>));
|
||||
|
||||
/// <summary>
|
||||
/// A second scheduler for lower priority imports.
|
||||
/// For simplicity, these will just run in parallel with normal priority imports, but a future refactor would see this implemented via a custom scheduler/queue.
|
||||
/// See https://gist.github.com/peppy/f0e118a14751fc832ca30dd48ba3876b for an incomplete version of this.
|
||||
/// </summary>
|
||||
private static readonly ThreadedTaskScheduler import_scheduler_low_priority = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(ArchiveModelManager<TModel, TFileModel>));
|
||||
|
||||
/// <summary>
|
||||
/// Set an endpoint for notifications to be posted to.
|
||||
/// </summary>
|
||||
@ -103,8 +115,11 @@ namespace osu.Game.Database
|
||||
|
||||
/// <summary>
|
||||
/// Import one or more <typeparamref name="TModel"/> items from filesystem <paramref name="paths"/>.
|
||||
/// This will post notifications tracking progress.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will be treated as a low priority import if more than one path is specified; use <see cref="Import(ImportTask[])"/> to always import at standard priority.
|
||||
/// This will post notifications tracking progress.
|
||||
/// </remarks>
|
||||
/// <param name="paths">One or more archive locations on disk.</param>
|
||||
public Task Import(params string[] paths)
|
||||
{
|
||||
@ -133,13 +148,15 @@ namespace osu.Game.Database
|
||||
|
||||
var imported = new List<TModel>();
|
||||
|
||||
bool isLowPriorityImport = tasks.Length > low_priority_import_batch_size;
|
||||
|
||||
await Task.WhenAll(tasks.Select(async task =>
|
||||
{
|
||||
notification.CancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
try
|
||||
{
|
||||
var model = await Import(task, notification.CancellationToken);
|
||||
var model = await Import(task, isLowPriorityImport, notification.CancellationToken);
|
||||
|
||||
lock (imported)
|
||||
{
|
||||
@ -193,15 +210,16 @@ namespace osu.Game.Database
|
||||
/// Note that this bypasses the UI flow and should only be used for special cases or testing.
|
||||
/// </summary>
|
||||
/// <param name="task">The <see cref="ImportTask"/> containing data about the <typeparamref name="TModel"/> to import.</param>
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
/// <returns>The imported model, if successful.</returns>
|
||||
internal async Task<TModel> Import(ImportTask task, CancellationToken cancellationToken = default)
|
||||
internal async Task<TModel> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
TModel import;
|
||||
using (ArchiveReader reader = task.GetReader())
|
||||
import = await Import(reader, cancellationToken);
|
||||
import = await Import(reader, lowPriority, cancellationToken);
|
||||
|
||||
// We may or may not want to delete the file depending on where it is stored.
|
||||
// e.g. reconstructing/repairing database with items from default storage.
|
||||
@ -226,11 +244,12 @@ namespace osu.Game.Database
|
||||
public Action<IEnumerable<TModel>> PresentImport;
|
||||
|
||||
/// <summary>
|
||||
/// Import an item from an <see cref="ArchiveReader"/>.
|
||||
/// Silently import an item from an <see cref="ArchiveReader"/>.
|
||||
/// </summary>
|
||||
/// <param name="archive">The archive to be imported.</param>
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
public Task<TModel> Import(ArchiveReader archive, CancellationToken cancellationToken = default)
|
||||
public Task<TModel> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
@ -253,7 +272,7 @@ namespace osu.Game.Database
|
||||
return null;
|
||||
}
|
||||
|
||||
return Import(model, archive, cancellationToken);
|
||||
return Import(model, archive, lowPriority, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -303,12 +322,13 @@ namespace osu.Game.Database
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import an item from a <typeparamref name="TModel"/>.
|
||||
/// Silently import an item from a <typeparamref name="TModel"/>.
|
||||
/// </summary>
|
||||
/// <param name="item">The model to be imported.</param>
|
||||
/// <param name="archive">An optional archive to use for model population.</param>
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
public virtual async Task<TModel> Import(TModel item, ArchiveReader archive = null, CancellationToken cancellationToken = default) => await Task.Factory.StartNew(async () =>
|
||||
public virtual async Task<TModel> Import(TModel item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) => await Task.Factory.StartNew(async () =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
@ -383,7 +403,7 @@ namespace osu.Game.Database
|
||||
|
||||
flushEvents(true);
|
||||
return item;
|
||||
}, cancellationToken, TaskCreationOptions.HideScheduler, import_scheduler).Unwrap();
|
||||
}, cancellationToken, TaskCreationOptions.HideScheduler, lowPriority ? import_scheduler_low_priority : import_scheduler).Unwrap();
|
||||
|
||||
/// <summary>
|
||||
/// Exports an item to a legacy (.zip based) package.
|
||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
public double? PP { get; set; }
|
||||
|
||||
[JsonProperty(@"room_id")]
|
||||
public int RoomID { get; set; }
|
||||
public long RoomID { get; set; }
|
||||
|
||||
[JsonProperty("total_score")]
|
||||
public long TotalScore { get; set; }
|
||||
|
@ -95,7 +95,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
private Room? apiRoom;
|
||||
|
||||
// Todo: This is temporary, until the multiplayer server returns the item id on match start or otherwise.
|
||||
private int playlistItemId;
|
||||
private long playlistItemId;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Online
|
||||
/// A <see cref="Container"/> for displaying online content which require a local user to be logged in.
|
||||
/// Shows its children only when the local user is logged in and supports displaying a placeholder if not.
|
||||
/// </summary>
|
||||
public abstract class OnlineViewContainer : Container
|
||||
public class OnlineViewContainer : Container
|
||||
{
|
||||
protected LoadingSpinner LoadingSpinner { get; private set; }
|
||||
|
||||
@ -30,7 +30,7 @@ namespace osu.Game.Online
|
||||
[Resolved]
|
||||
protected IAPIProvider API { get; private set; }
|
||||
|
||||
protected OnlineViewContainer(string placeholderMessage)
|
||||
public OnlineViewContainer(string placeholderMessage)
|
||||
{
|
||||
this.placeholderMessage = placeholderMessage;
|
||||
}
|
||||
|
@ -9,11 +9,11 @@ namespace osu.Game.Online.Rooms
|
||||
{
|
||||
public class CreateRoomScoreRequest : APIRequest<APIScoreToken>
|
||||
{
|
||||
private readonly int roomId;
|
||||
private readonly int playlistItemId;
|
||||
private readonly long roomId;
|
||||
private readonly long playlistItemId;
|
||||
private readonly string versionHash;
|
||||
|
||||
public CreateRoomScoreRequest(int roomId, int playlistItemId, string versionHash)
|
||||
public CreateRoomScoreRequest(long roomId, long playlistItemId, string versionHash)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
this.playlistItemId = playlistItemId;
|
||||
|
@ -7,9 +7,9 @@ namespace osu.Game.Online.Rooms
|
||||
{
|
||||
public class GetRoomLeaderboardRequest : APIRequest<APILeaderboard>
|
||||
{
|
||||
private readonly int roomId;
|
||||
private readonly long roomId;
|
||||
|
||||
public GetRoomLeaderboardRequest(int roomId)
|
||||
public GetRoomLeaderboardRequest(long roomId)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ namespace osu.Game.Online.Rooms
|
||||
{
|
||||
public class GetRoomRequest : APIRequest<Room>
|
||||
{
|
||||
public readonly int RoomId;
|
||||
public readonly long RoomId;
|
||||
|
||||
public GetRoomRequest(int roomId)
|
||||
public GetRoomRequest(long roomId)
|
||||
{
|
||||
RoomId = roomId;
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ namespace osu.Game.Online.Rooms
|
||||
/// </summary>
|
||||
public class IndexPlaylistScoresRequest : APIRequest<IndexedMultiplayerScores>
|
||||
{
|
||||
public readonly int RoomId;
|
||||
public readonly int PlaylistItemId;
|
||||
public readonly long RoomId;
|
||||
public readonly long PlaylistItemId;
|
||||
|
||||
[CanBeNull]
|
||||
public readonly Cursor Cursor;
|
||||
@ -24,13 +24,13 @@ namespace osu.Game.Online.Rooms
|
||||
[CanBeNull]
|
||||
public readonly IndexScoresParams IndexParams;
|
||||
|
||||
public IndexPlaylistScoresRequest(int roomId, int playlistItemId)
|
||||
public IndexPlaylistScoresRequest(long roomId, long playlistItemId)
|
||||
{
|
||||
RoomId = roomId;
|
||||
PlaylistItemId = playlistItemId;
|
||||
}
|
||||
|
||||
public IndexPlaylistScoresRequest(int roomId, int playlistItemId, [NotNull] Cursor cursor, [NotNull] IndexScoresParams indexParams)
|
||||
public IndexPlaylistScoresRequest(long roomId, long playlistItemId, [NotNull] Cursor cursor, [NotNull] IndexScoresParams indexParams)
|
||||
: this(roomId, playlistItemId)
|
||||
{
|
||||
Cursor = cursor;
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Online.Rooms
|
||||
public class MultiplayerScore
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int ID { get; set; }
|
||||
public long ID { get; set; }
|
||||
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Online.Rooms
|
||||
public class PlaylistItem : IEquatable<PlaylistItem>
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int ID { get; set; }
|
||||
public long ID { get; set; }
|
||||
|
||||
[JsonProperty("beatmap_id")]
|
||||
public int BeatmapID { get; set; }
|
||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Online.Rooms
|
||||
{
|
||||
[Cached]
|
||||
[JsonProperty("id")]
|
||||
public readonly Bindable<int?> RoomID = new Bindable<int?>();
|
||||
public readonly Bindable<long?> RoomID = new Bindable<long?>();
|
||||
|
||||
[Cached]
|
||||
[JsonProperty("name")]
|
||||
|
@ -7,11 +7,11 @@ namespace osu.Game.Online.Rooms
|
||||
{
|
||||
public class ShowPlaylistUserScoreRequest : APIRequest<MultiplayerScore>
|
||||
{
|
||||
private readonly int roomId;
|
||||
private readonly int playlistItemId;
|
||||
private readonly long roomId;
|
||||
private readonly long playlistItemId;
|
||||
private readonly long userId;
|
||||
|
||||
public ShowPlaylistUserScoreRequest(int roomId, int playlistItemId, long userId)
|
||||
public ShowPlaylistUserScoreRequest(long roomId, long playlistItemId, long userId)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
this.playlistItemId = playlistItemId;
|
||||
|
@ -11,12 +11,12 @@ namespace osu.Game.Online.Rooms
|
||||
{
|
||||
public class SubmitRoomScoreRequest : APIRequest<MultiplayerScore>
|
||||
{
|
||||
private readonly int scoreId;
|
||||
private readonly int roomId;
|
||||
private readonly int playlistItemId;
|
||||
private readonly long scoreId;
|
||||
private readonly long roomId;
|
||||
private readonly long playlistItemId;
|
||||
private readonly ScoreInfo scoreInfo;
|
||||
|
||||
public SubmitRoomScoreRequest(int scoreId, int roomId, int playlistItemId, ScoreInfo scoreInfo)
|
||||
public SubmitRoomScoreRequest(long scoreId, long roomId, long playlistItemId, ScoreInfo scoreInfo)
|
||||
{
|
||||
this.scoreId = scoreId;
|
||||
this.roomId = roomId;
|
||||
|
@ -156,7 +156,12 @@ namespace osu.Game
|
||||
|
||||
protected override UserInputManager CreateUserInputManager() => new OsuUserInputManager();
|
||||
|
||||
private readonly BindableNumber<double> globalTrackVolumeAdjust = new BindableNumber<double>(0.5f);
|
||||
/// <summary>
|
||||
/// The maximum volume at which audio tracks should playback. This can be set lower than 1 to create some head-room for sound effects.
|
||||
/// </summary>
|
||||
internal const double GLOBAL_TRACK_VOLUME_ADJUST = 0.5;
|
||||
|
||||
private readonly BindableNumber<double> globalTrackVolumeAdjust = new BindableNumber<double>(GLOBAL_TRACK_VOLUME_ADJUST);
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Overlays
|
||||
protected List<APIUpdateStream> Streams;
|
||||
|
||||
public ChangelogOverlay()
|
||||
: base(OverlayColourScheme.Purple)
|
||||
: base(OverlayColourScheme.Purple, false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ using osu.Game.Overlays.Chat.Tabs;
|
||||
using osuTK.Input;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Online;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
@ -118,40 +119,47 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
currentChannelContainer = new Container<DrawableChannel>
|
||||
new OnlineViewContainer("Sign in to chat")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Bottom = textbox_height
|
||||
},
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = textbox_height,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = padding * 2,
|
||||
Bottom = padding * 2,
|
||||
Left = ChatLine.LEFT_PADDING + padding * 2,
|
||||
Right = padding * 2,
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
textbox = new FocusedTextBox
|
||||
currentChannelContainer = new Container<DrawableChannel>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 1,
|
||||
PlaceholderText = "type your message",
|
||||
ReleaseFocusOnCommit = false,
|
||||
HoldFocus = true,
|
||||
}
|
||||
}
|
||||
},
|
||||
loading = new LoadingSpinner(),
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Bottom = textbox_height
|
||||
},
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = textbox_height,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = padding * 2,
|
||||
Bottom = padding * 2,
|
||||
Left = ChatLine.LEFT_PADDING + padding * 2,
|
||||
Right = padding * 2,
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
textbox = new FocusedTextBox
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 1,
|
||||
PlaceholderText = "type your message",
|
||||
ReleaseFocusOnCommit = false,
|
||||
HoldFocus = true,
|
||||
}
|
||||
}
|
||||
},
|
||||
loading = new LoadingSpinner(),
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
tabsArea = new TabsArea
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Overlays
|
||||
private readonly Bindable<string> article = new Bindable<string>(null);
|
||||
|
||||
public NewsOverlay()
|
||||
: base(OverlayColourScheme.Purple)
|
||||
: base(OverlayColourScheme.Purple, false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
@ -16,10 +17,16 @@ namespace osu.Game.Overlays
|
||||
protected readonly LoadingLayer Loading;
|
||||
private readonly Container content;
|
||||
|
||||
protected OnlineOverlay(OverlayColourScheme colourScheme)
|
||||
protected OnlineOverlay(OverlayColourScheme colourScheme, bool requiresSignIn = true)
|
||||
: base(colourScheme)
|
||||
{
|
||||
base.Content.AddRange(new Drawable[]
|
||||
var mainContent = requiresSignIn
|
||||
? new OnlineViewContainer($"Sign in to view the {Header.Title.Title}")
|
||||
: new Container();
|
||||
|
||||
mainContent.RelativeSizeAxes = Axes.Both;
|
||||
|
||||
mainContent.AddRange(new Drawable[]
|
||||
{
|
||||
ScrollFlow = new OverlayScrollContainer
|
||||
{
|
||||
@ -43,6 +50,8 @@ namespace osu.Game.Overlays
|
||||
},
|
||||
Loading = new LoadingLayer(true)
|
||||
});
|
||||
|
||||
base.Content.Add(mainContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +61,7 @@ namespace osu.Game.Overlays
|
||||
|
||||
LoadComponentAsync(display, loaded =>
|
||||
{
|
||||
if (API.IsLoggedIn)
|
||||
Loading.Hide();
|
||||
Loading.Hide();
|
||||
|
||||
Child = loaded;
|
||||
}, (cancellationToken = new CancellationTokenSource()).Token);
|
||||
|
@ -111,12 +111,10 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == BeatmapHash);
|
||||
|
||||
if (setInfo != null)
|
||||
{
|
||||
initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]);
|
||||
}
|
||||
if (setInfo == null)
|
||||
return false;
|
||||
|
||||
return UsingThemedIntro;
|
||||
return (initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0])) != null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,7 +168,7 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu.
|
||||
if (UsingThemedIntro)
|
||||
Track.Restart();
|
||||
Track.Start();
|
||||
}
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
|
@ -179,14 +179,15 @@ namespace osu.Game.Screens.Menu
|
||||
base.OnEntering(last);
|
||||
buttons.FadeInFromZero(500);
|
||||
|
||||
var metadata = Beatmap.Value.Metadata;
|
||||
|
||||
if (last is IntroScreen && musicController.TrackLoaded)
|
||||
{
|
||||
if (!musicController.CurrentTrack.IsRunning)
|
||||
var track = musicController.CurrentTrack;
|
||||
|
||||
// presume the track is the current beatmap's track. not sure how correct this assumption is but it has worked until now.
|
||||
if (!track.IsRunning)
|
||||
{
|
||||
musicController.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.CurrentTrack.Length);
|
||||
musicController.CurrentTrack.Start();
|
||||
Beatmap.Value.PrepareTrackForPreviewLooping();
|
||||
track.Restart();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
joinedRoom.Value = null;
|
||||
}
|
||||
|
||||
private readonly HashSet<int> ignoredRooms = new HashSet<int>();
|
||||
private readonly HashSet<long> ignoredRooms = new HashSet<long>();
|
||||
|
||||
private void onRoomsReceived(List<Room> received)
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
|
||||
public class MatchChatDisplay : StandAloneChatDisplay
|
||||
{
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
private Bindable<long?> roomId { get; set; }
|
||||
|
||||
[Resolved(typeof(Room), nameof(Room.ChannelId))]
|
||||
private Bindable<int> channelId { get; set; }
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
|
||||
public class MatchLeaderboard : Leaderboard<MatchLeaderboardScope, APIUserScoreAggregate>
|
||||
{
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
private Bindable<long?> roomId { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
|
@ -78,7 +78,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy();
|
||||
managerUpdated.BindValueChanged(beatmapUpdated);
|
||||
|
||||
UserMods.BindValueChanged(_ => updateMods());
|
||||
UserMods.BindValueChanged(_ => Scheduler.AddOnce(UpdateMods));
|
||||
}
|
||||
|
||||
public override void OnEntering(IScreen last)
|
||||
@ -97,7 +97,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
{
|
||||
base.OnResuming(last);
|
||||
beginHandlingTrack();
|
||||
updateMods();
|
||||
Scheduler.AddOnce(UpdateMods);
|
||||
}
|
||||
|
||||
public override bool OnExiting(IScreen next)
|
||||
@ -128,7 +128,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
.Where(m => SelectedItem.Value.AllowedMods.Any(a => m.GetType() == a.GetType()))
|
||||
.ToList();
|
||||
|
||||
updateMods();
|
||||
UpdateMods();
|
||||
|
||||
Ruleset.Value = SelectedItem.Value.Ruleset.Value;
|
||||
}
|
||||
@ -145,7 +145,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
|
||||
}
|
||||
|
||||
private void updateMods()
|
||||
protected virtual void UpdateMods()
|
||||
{
|
||||
if (SelectedItem.Value == null)
|
||||
return;
|
||||
@ -173,9 +173,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
|
||||
if (track != null)
|
||||
{
|
||||
track.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
|
||||
track.Looping = true;
|
||||
|
||||
Beatmap.Value.PrepareTrackForPreviewLooping();
|
||||
music?.EnsurePlayingSomething();
|
||||
}
|
||||
}
|
||||
@ -185,10 +183,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
var track = Beatmap?.Value?.Track;
|
||||
|
||||
if (track != null)
|
||||
{
|
||||
track.Looping = false;
|
||||
track.RestartPoint = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
public class CreateOrUpdateButton : TriangleButton
|
||||
{
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
private Bindable<long?> roomId { get; set; }
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
|
@ -274,6 +274,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
UserMods.BindValueChanged(onUserModsChanged);
|
||||
|
||||
client.LoadRequested += onLoadRequested;
|
||||
client.RoomUpdated += onRoomUpdated;
|
||||
|
||||
isConnected = client.IsConnected.GetBoundCopy();
|
||||
isConnected.BindValueChanged(connected =>
|
||||
@ -283,6 +284,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override void UpdateMods()
|
||||
{
|
||||
if (SelectedItem.Value == null || client.LocalUser == null)
|
||||
return;
|
||||
|
||||
// update local mods based on room's reported status for the local user (omitting the base call implementation).
|
||||
// this makes the server authoritative, and avoids the local user potentially setting mods that the server is not aware of (ie. if the match was started during the selection being changed).
|
||||
var ruleset = Ruleset.Value.CreateInstance();
|
||||
Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList();
|
||||
}
|
||||
|
||||
public override bool OnBackButton()
|
||||
{
|
||||
if (client.Room != null && settingsOverlay.State.Value == Visibility.Visible)
|
||||
@ -391,6 +403,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
private void onRoomUpdated()
|
||||
{
|
||||
// user mods may have changed.
|
||||
Scheduler.AddOnce(UpdateMods);
|
||||
}
|
||||
|
||||
private void onLoadRequested()
|
||||
{
|
||||
Debug.Assert(client.Room != null);
|
||||
@ -408,7 +426,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
client.RoomUpdated -= onRoomUpdated;
|
||||
client.LoadRequested -= onLoadRequested;
|
||||
}
|
||||
|
||||
modSettingChangeTracker?.Dispose();
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
{
|
||||
public class MultiplayerResultsScreen : PlaylistsResultsScreen
|
||||
{
|
||||
public MultiplayerResultsScreen(ScoreInfo score, int roomId, PlaylistItem playlistItem)
|
||||
public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem)
|
||||
: base(score, roomId, playlistItem, false, false)
|
||||
{
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
public class OnlinePlayComposite : CompositeDrawable
|
||||
{
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<int?> RoomID { get; private set; }
|
||||
protected Bindable<long?> RoomID { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room), nameof(Room.Name))]
|
||||
protected Bindable<string> RoomName { get; private set; }
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
public Action Exited;
|
||||
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
protected Bindable<int?> RoomId { get; private set; }
|
||||
protected Bindable<long?> RoomId { get; private set; }
|
||||
|
||||
protected readonly PlaylistItem PlaylistItem;
|
||||
|
||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
{
|
||||
public class PlaylistsResultsScreen : ResultsScreen
|
||||
{
|
||||
private readonly int roomId;
|
||||
private readonly long roomId;
|
||||
private readonly PlaylistItem playlistItem;
|
||||
|
||||
protected LoadingSpinner LeftSpinner { get; private set; }
|
||||
@ -32,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
public PlaylistsResultsScreen(ScoreInfo score, int roomId, PlaylistItem playlistItem, bool allowRetry, bool allowWatchingReplay = true)
|
||||
public PlaylistsResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, bool allowRetry, bool allowWatchingReplay = true)
|
||||
: base(score, allowRetry, allowWatchingReplay)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
public override string ShortTitle => "playlist";
|
||||
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
private Bindable<long?> roomId { get; set; }
|
||||
|
||||
private MatchSettingsOverlay settingsOverlay;
|
||||
private MatchLeaderboard leaderboard;
|
||||
|
@ -72,19 +72,6 @@ namespace osu.Game.Screens.Play.HUD
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Current.ValueChanged += mods =>
|
||||
{
|
||||
iconsContainer.Clear();
|
||||
|
||||
foreach (Mod mod in mods.NewValue)
|
||||
{
|
||||
iconsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.6f) });
|
||||
}
|
||||
|
||||
if (IsLoaded)
|
||||
appearTransform();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
@ -97,7 +84,19 @@ namespace osu.Game.Screens.Play.HUD
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
appearTransform();
|
||||
Current.BindValueChanged(mods =>
|
||||
{
|
||||
iconsContainer.Clear();
|
||||
|
||||
if (mods.NewValue != null)
|
||||
{
|
||||
foreach (Mod mod in mods.NewValue)
|
||||
iconsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.6f) });
|
||||
|
||||
appearTransform();
|
||||
}
|
||||
}, true);
|
||||
|
||||
iconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,13 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
|
||||
public readonly Bindable<CarouselItemState> State = new Bindable<CarouselItemState>(CarouselItemState.NotSelected);
|
||||
|
||||
private readonly HoverLayer hoverLayer;
|
||||
|
||||
protected override Container<Drawable> Content { get; } = new Container { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
private const float corner_radius = 10;
|
||||
private const float border_thickness = 2.5f;
|
||||
|
||||
public CarouselHeader()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
@ -36,12 +41,12 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
CornerRadius = 10,
|
||||
CornerRadius = corner_radius,
|
||||
BorderColour = new Color4(221, 255, 255, 255),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Content,
|
||||
new HoverLayer()
|
||||
hoverLayer = new HoverLayer()
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -59,6 +64,8 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
case CarouselItemState.Collapsed:
|
||||
case CarouselItemState.NotSelected:
|
||||
hoverLayer.InsetForBorder = false;
|
||||
|
||||
BorderContainer.BorderThickness = 0;
|
||||
BorderContainer.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
@ -70,7 +77,9 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
break;
|
||||
|
||||
case CarouselItemState.Selected:
|
||||
BorderContainer.BorderThickness = 2.5f;
|
||||
hoverLayer.InsetForBorder = true;
|
||||
|
||||
BorderContainer.BorderThickness = border_thickness;
|
||||
BorderContainer.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
@ -107,6 +116,26 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
sampleHover = audio.Samples.Get("SongSelect/song-ping");
|
||||
}
|
||||
|
||||
public bool InsetForBorder
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
// apply same border as above to avoid applying additive overlay to it (and blowing out the colour).
|
||||
Masking = true;
|
||||
CornerRadius = corner_radius;
|
||||
BorderThickness = border_thickness;
|
||||
}
|
||||
else
|
||||
{
|
||||
BorderThickness = 0;
|
||||
CornerRadius = 0;
|
||||
Masking = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
box.FadeIn(100, Easing.OutQuint);
|
||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Screens.Select
|
||||
Sort = sortMode.Value,
|
||||
AllowConvertedBeatmaps = showConverted.Value,
|
||||
Ruleset = ruleset.Value,
|
||||
Collection = collectionDropdown?.Current.Value.Collection
|
||||
Collection = collectionDropdown?.Current.Value?.Collection
|
||||
};
|
||||
|
||||
if (!minimumStars.IsDefault)
|
||||
|
@ -648,8 +648,9 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
Debug.Assert(!isHandlingLooping);
|
||||
|
||||
music.CurrentTrack.Looping = isHandlingLooping = true;
|
||||
isHandlingLooping = true;
|
||||
|
||||
ensureTrackLooping(Beatmap.Value, TrackChangeDirection.None);
|
||||
music.TrackChanged += ensureTrackLooping;
|
||||
}
|
||||
|
||||
@ -665,7 +666,7 @@ namespace osu.Game.Screens.Select
|
||||
}
|
||||
|
||||
private void ensureTrackLooping(WorkingBeatmap beatmap, TrackChangeDirection changeDirection)
|
||||
=> music.CurrentTrack.Looping = true;
|
||||
=> beatmap.PrepareTrackForPreviewLooping();
|
||||
|
||||
public override bool OnBackButton()
|
||||
{
|
||||
@ -719,8 +720,6 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track;
|
||||
|
||||
track.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
|
||||
|
||||
if (!track.IsRunning && (music.UserPauseRequested != true || isNewTrack))
|
||||
music.Play(true);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user