1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 11:28:00 +08:00

Merge branch 'master' into wcd-length-fix

This commit is contained in:
Bartłomiej Dach 2023-01-08 19:44:12 +01:00 committed by GitHub
commit e08b7c615b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 256 additions and 22 deletions

View File

@ -6,6 +6,7 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Edit; using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Components.Timelines.Summary; using osu.Game.Screens.Edit.Components.Timelines.Summary;
@ -21,7 +22,13 @@ namespace osu.Game.Tests.Visual.Editing
public TestSceneEditorSummaryTimeline() public TestSceneEditorSummaryTimeline()
{ {
editorBeatmap = new EditorBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); var beatmap = CreateBeatmap(new OsuRuleset().RulesetInfo);
beatmap.ControlPointInfo.Add(100000, new TimingControlPoint { BeatLength = 100 });
beatmap.ControlPointInfo.Add(50000, new DifficultyControlPoint { SliderVelocity = 2 });
beatmap.BeatmapInfo.Bookmarks = new[] { 75000, 125000 };
editorBeatmap = new EditorBeatmap(beatmap);
} }
protected override void LoadComplete() protected override void LoadComplete()

View File

@ -0,0 +1,35 @@
// 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.Linq;
using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts;
namespace osu.Game.Tests.Visual.Editing
{
public partial class TestScenePreviewTime : EditorTestScene
{
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
[Test]
public void TestSceneSetPreviewTimingPoint()
{
AddStep("seek to 1000", () => EditorClock.Seek(1000));
AddAssert("time is 1000", () => EditorClock.CurrentTime == 1000);
AddStep("set current time as preview point", () => Editor.SetPreviewPointToCurrentTime());
AddAssert("preview time is 1000", () => EditorBeatmap.PreviewTime.Value == 1000);
}
[Test]
public void TestScenePreviewTimeline()
{
AddStep("set preview time to -1", () => EditorBeatmap.PreviewTime.Value = -1);
AddAssert("preview time line should not show", () => !Editor.ChildrenOfType<PreviewTimePart>().Single().Children.Any());
AddStep("set preview time to 1000", () => EditorBeatmap.PreviewTime.Value = 1000);
AddAssert("preview time line should show", () => Editor.ChildrenOfType<PreviewTimePart>().Single().Children.Single().Alpha == 1);
}
}
}

View File

@ -0,0 +1,22 @@
// 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 Newtonsoft.Json;
namespace osu.Game.Beatmaps
{
public struct BeatmapSetOnlineNomination
{
[JsonProperty(@"beatmapset_id")]
public int BeatmapsetId { get; set; }
[JsonProperty(@"reset")]
public bool Reset { get; set; }
[JsonProperty(@"rulesets")]
public string[]? Rulesets { get; set; }
[JsonProperty(@"user_id")]
public int UserId { get; set; }
}
}

View File

@ -259,7 +259,11 @@ namespace osu.Game.Online.API
var friendsReq = new GetFriendsRequest(); var friendsReq = new GetFriendsRequest();
friendsReq.Failure += _ => state.Value = APIState.Failing; friendsReq.Failure += _ => state.Value = APIState.Failing;
friendsReq.Success += res => friends.AddRange(res); friendsReq.Success += res =>
{
friends.Clear();
friends.AddRange(res);
};
if (!handleRequest(friendsReq)) if (!handleRequest(friendsReq))
{ {

View File

@ -111,6 +111,12 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty(@"language")] [JsonProperty(@"language")]
public BeatmapSetOnlineLanguage Language { get; set; } public BeatmapSetOnlineLanguage Language { get; set; }
[JsonProperty(@"current_nominations")]
public BeatmapSetOnlineNomination[]? CurrentNominations { get; set; }
[JsonProperty(@"related_users")]
public APIUser[]? RelatedUsers { get; set; }
public string Source { get; set; } = string.Empty; public string Source { get; set; } = string.Empty;
[JsonProperty(@"tags")] [JsonProperty(@"tags")]

View File

@ -103,8 +103,7 @@ namespace osu.Game.Overlays.BeatmapListing
{ {
private readonly Box selectedUnderline; private readonly Box selectedUnderline;
[Resolved] protected override bool HighlightOnHoverWhenActive => true;
private OverlayColourProvider colourProvider { get; set; }
public MultipleSelectionFilterTabItem(T value) public MultipleSelectionFilterTabItem(T value)
: base(value) : base(value)
@ -125,7 +124,7 @@ namespace osu.Game.Overlays.BeatmapListing
{ {
base.UpdateState(); base.UpdateState();
selectedUnderline.FadeTo(Active.Value ? 1 : 0, 200, Easing.OutQuint); selectedUnderline.FadeTo(Active.Value ? 1 : 0, 200, Easing.OutQuint);
selectedUnderline.FadeColour(IsHovered ? colourProvider.Light1 : GetStateColour(), 200, Easing.OutQuint); selectedUnderline.FadeColour(IsHovered ? ColourProvider.Content2 : GetStateColour(), 200, Easing.OutQuint);
} }
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)

View File

@ -20,7 +20,7 @@ namespace osu.Game.Overlays.BeatmapListing
public partial class FilterTabItem<T> : TabItem<T> public partial class FilterTabItem<T> : TabItem<T>
{ {
[Resolved] [Resolved]
private OverlayColourProvider colourProvider { get; set; } protected OverlayColourProvider ColourProvider { get; private set; }
private OsuSpriteText text; private OsuSpriteText text;
@ -78,12 +78,16 @@ namespace osu.Game.Overlays.BeatmapListing
/// </summary> /// </summary>
protected virtual LocalisableString LabelFor(T value) => (value as Enum)?.GetLocalisableDescription() ?? value.ToString(); protected virtual LocalisableString LabelFor(T value) => (value as Enum)?.GetLocalisableDescription() ?? value.ToString();
protected virtual bool HighlightOnHoverWhenActive => false;
protected virtual void UpdateState() protected virtual void UpdateState()
{ {
text.FadeColour(IsHovered ? colourProvider.Light1 : GetStateColour(), 200, Easing.OutQuint); bool highlightHover = IsHovered && (!Active.Value || HighlightOnHoverWhenActive);
text.FadeColour(highlightHover ? ColourProvider.Content2 : GetStateColour(), 200, Easing.OutQuint);
text.Font = text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Regular); text.Font = text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Regular);
} }
protected virtual Color4 GetStateColour() => Active.Value ? colourProvider.Content1 : colourProvider.Light2; protected virtual Color4 GetStateColour() => Active.Value ? ColourProvider.Content1 : ColourProvider.Light2;
} }
} }

View File

@ -3,6 +3,7 @@
#nullable disable #nullable disable
using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -36,6 +37,7 @@ namespace osu.Game.Overlays.BeatmapSet
public Info() public Info()
{ {
MetadataSectionNominators nominators;
MetadataSection source, tags; MetadataSection source, tags;
MetadataSectionGenre genre; MetadataSectionGenre genre;
MetadataSectionLanguage language; MetadataSectionLanguage language;
@ -82,6 +84,7 @@ namespace osu.Game.Overlays.BeatmapSet
Direction = FillDirection.Full, Direction = FillDirection.Full,
Children = new Drawable[] Children = new Drawable[]
{ {
nominators = new MetadataSectionNominators(),
source = new MetadataSectionSource(), source = new MetadataSectionSource(),
genre = new MetadataSectionGenre { Width = 0.5f }, genre = new MetadataSectionGenre { Width = 0.5f },
language = new MetadataSectionLanguage { Width = 0.5f }, language = new MetadataSectionLanguage { Width = 0.5f },
@ -122,6 +125,7 @@ namespace osu.Game.Overlays.BeatmapSet
BeatmapSet.ValueChanged += b => BeatmapSet.ValueChanged += b =>
{ {
nominators.Metadata = (b.NewValue?.CurrentNominations ?? Array.Empty<BeatmapSetOnlineNomination>(), b.NewValue?.RelatedUsers ?? Array.Empty<APIUser>());
source.Metadata = b.NewValue?.Source ?? string.Empty; source.Metadata = b.NewValue?.Source ?? string.Empty;
tags.Metadata = b.NewValue?.Tags ?? string.Empty; tags.Metadata = b.NewValue?.Tags ?? string.Empty;
genre.Metadata = b.NewValue?.Genre ?? new BeatmapSetOnlineGenre { Id = (int)SearchGenre.Unspecified }; genre.Metadata = b.NewValue?.Genre ?? new BeatmapSetOnlineGenre { Id = (int)SearchGenre.Unspecified };

View File

@ -0,0 +1,63 @@
// 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 System.Linq;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapSet
{
public partial class MetadataSectionNominators : MetadataSection<(BeatmapSetOnlineNomination[] CurrentNominations, APIUser[] RelatedUsers)>
{
public override (BeatmapSetOnlineNomination[] CurrentNominations, APIUser[] RelatedUsers) Metadata
{
set
{
if (value.CurrentNominations.Length == 0)
{
this.FadeOut(TRANSITION_DURATION);
return;
}
base.Metadata = value;
}
}
public MetadataSectionNominators(Action<(BeatmapSetOnlineNomination[] CurrentNominations, APIUser[] RelatedUsers)>? searchAction = null)
: base(MetadataType.Nominators, searchAction)
{
}
protected override void AddMetadata((BeatmapSetOnlineNomination[] CurrentNominations, APIUser[] RelatedUsers) metadata, LinkFlowContainer loaded)
{
int[] nominatorIds = metadata.CurrentNominations.Select(n => n.UserId).ToArray();
int nominatorsFound = 0;
foreach (int nominatorId in nominatorIds)
{
foreach (var user in metadata.RelatedUsers)
{
if (nominatorId != user.OnlineID) continue;
nominatorsFound++;
loaded.AddUserLink(new APIUser
{
Username = user.Username,
Id = nominatorId,
});
if (nominatorsFound < nominatorIds.Length)
loaded.AddText(CommonStrings.ArrayAndWordsConnector);
break;
}
}
}
}
}

View File

@ -23,6 +23,9 @@ namespace osu.Game.Overlays.BeatmapSet
Genre, Genre,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoLanguage))] [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoLanguage))]
Language Language,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoNominators))]
Nominators,
} }
} }

View File

@ -99,6 +99,18 @@ namespace osu.Game.Screens.Backgrounds
} }
} }
/// <summary>
/// Reloads beatmap's background.
/// </summary>
public void RefreshBackground()
{
Schedule(() =>
{
cancellationSource?.Cancel();
LoadComponentAsync(new BeatmapBackground(beatmap), switchBackground, (cancellationSource = new CancellationTokenSource()).Token);
});
}
private void switchBackground(BeatmapBackground b) private void switchBackground(BeatmapBackground b)
{ {
float newDepth = 0; float newDepth = 0;

View File

@ -0,0 +1,41 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Graphics;
using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
{
public partial class PreviewTimePart : TimelinePart
{
private readonly BindableInt previewTime = new BindableInt();
protected override void LoadBeatmap(EditorBeatmap beatmap)
{
base.LoadBeatmap(beatmap);
previewTime.UnbindAll();
previewTime.BindTo(beatmap.PreviewTime);
previewTime.BindValueChanged(t =>
{
Clear();
if (t.NewValue >= 0)
Add(new PreviewTimeVisualisation(t.NewValue));
}, true);
}
private partial class PreviewTimeVisualisation : PointVisualisation
{
public PreviewTimeVisualisation(double time)
: base(time)
{
}
[BackgroundDependencyLoader]
private void load(OsuColour colours) => Colour = colours.Green1;
}
}
}

View File

@ -41,6 +41,13 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Height = 0.35f Height = 0.35f
}, },
new PreviewTimePart
{
Anchor = Anchor.Centre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Both,
Height = 0.35f
},
new Container new Container
{ {
Name = "centre line", Name = "centre line",

View File

@ -322,6 +322,13 @@ namespace osu.Game.Screens.Edit
State = { BindTarget = editorHitMarkers }, State = { BindTarget = editorHitMarkers },
} }
} }
},
new MenuItem("Timing")
{
Items = new MenuItem[]
{
new EditorMenuItem("Set preview point to current time", MenuItemType.Standard, SetPreviewPointToCurrentTime)
}
} }
} }
}, },
@ -801,6 +808,11 @@ namespace osu.Game.Screens.Edit
protected void Redo() => changeHandler?.RestoreState(1); protected void Redo() => changeHandler?.RestoreState(1);
protected void SetPreviewPointToCurrentTime()
{
editorBeatmap.PreviewTime.Value = (int)clock.CurrentTime;
}
private void resetTrack(bool seekToStart = false) private void resetTrack(bool seekToStart = false)
{ {
Beatmap.Value.Track.Stop(); Beatmap.Value.Track.Stop();

View File

@ -86,6 +86,8 @@ namespace osu.Game.Screens.Edit
[Resolved] [Resolved]
private EditorClock editorClock { get; set; } private EditorClock editorClock { get; set; }
public BindableInt PreviewTime { get; }
private readonly IBeatmapProcessor beatmapProcessor; private readonly IBeatmapProcessor beatmapProcessor;
private readonly Dictionary<HitObject, Bindable<double>> startTimeBindables = new Dictionary<HitObject, Bindable<double>>(); private readonly Dictionary<HitObject, Bindable<double>> startTimeBindables = new Dictionary<HitObject, Bindable<double>>();
@ -107,6 +109,14 @@ namespace osu.Game.Screens.Edit
foreach (var obj in HitObjects) foreach (var obj in HitObjects)
trackStartTime(obj); trackStartTime(obj);
PreviewTime = new BindableInt(BeatmapInfo.Metadata.PreviewTime);
PreviewTime.BindValueChanged(s =>
{
BeginChange();
BeatmapInfo.Metadata.PreviewTime = s.NewValue;
EndChange();
});
} }
/// <summary> /// <summary>

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.IO; using System.IO;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
@ -16,25 +14,28 @@ namespace osu.Game.Screens.Edit.Setup
{ {
internal partial class ResourcesSection : SetupSection internal partial class ResourcesSection : SetupSection
{ {
private LabelledFileChooser audioTrackChooser; private LabelledFileChooser audioTrackChooser = null!;
private LabelledFileChooser backgroundChooser; private LabelledFileChooser backgroundChooser = null!;
public override LocalisableString Title => EditorSetupStrings.ResourcesHeader; public override LocalisableString Title => EditorSetupStrings.ResourcesHeader;
[Resolved] [Resolved]
private MusicController music { get; set; } private MusicController music { get; set; } = null!;
[Resolved] [Resolved]
private BeatmapManager beatmaps { get; set; } private BeatmapManager beatmaps { get; set; } = null!;
[Resolved] [Resolved]
private IBindable<WorkingBeatmap> working { get; set; } private IBindable<WorkingBeatmap> working { get; set; } = null!;
[Resolved] [Resolved]
private EditorBeatmap editorBeatmap { get; set; } private EditorBeatmap editorBeatmap { get; set; } = null!;
[Resolved] [Resolved]
private SetupScreenHeader header { get; set; } private Editor? editor { get; set; }
[Resolved]
private SetupScreenHeader header { get; set; } = null!;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
@ -93,6 +94,8 @@ namespace osu.Game.Screens.Edit.Setup
working.Value.Metadata.BackgroundFile = destination.Name; working.Value.Metadata.BackgroundFile = destination.Name;
header.Background.UpdateBackground(); header.Background.UpdateBackground();
editor?.ApplyToBackground(bg => bg.RefreshBackground());
return true; return true;
} }
@ -125,17 +128,17 @@ namespace osu.Game.Screens.Edit.Setup
return true; return true;
} }
private void backgroundChanged(ValueChangedEvent<FileInfo> file) private void backgroundChanged(ValueChangedEvent<FileInfo?> file)
{ {
if (!ChangeBackgroundImage(file.NewValue)) if (file.NewValue == null || !ChangeBackgroundImage(file.NewValue))
backgroundChooser.Current.Value = file.OldValue; backgroundChooser.Current.Value = file.OldValue;
updatePlaceholderText(); updatePlaceholderText();
} }
private void audioTrackChanged(ValueChangedEvent<FileInfo> file) private void audioTrackChanged(ValueChangedEvent<FileInfo?> file)
{ {
if (!ChangeAudioTrack(file.NewValue)) if (file.NewValue == null || !ChangeAudioTrack(file.NewValue))
audioTrackChooser.Current.Value = file.OldValue; audioTrackChooser.Current.Value = file.OldValue;
updatePlaceholderText(); updatePlaceholderText();

View File

@ -102,6 +102,8 @@ namespace osu.Game.Tests.Visual
public new void Redo() => base.Redo(); public new void Redo() => base.Redo();
public new void SetPreviewPointToCurrentTime() => base.SetPreviewPointToCurrentTime();
public new bool Save() => base.Save(); public new bool Save() => base.Save();
public new void Cut() => base.Cut(); public new void Cut() => base.Cut();