Skip to content

Commit

Permalink
Merge pull request #1846 from andy840119/implement-timing-info-section
Browse files Browse the repository at this point in the history
Implement timing info section.
  • Loading branch information
andy840119 authored Jan 18, 2023
2 parents 6afd1e0 + 795a490 commit 5c4325e
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,21 @@ public void TestClearLyricFromMapping()

#region Query

[Test]
public void TestGetTimingPointOrder()
{
var timingInfo = new ClassicLyricTimingInfo();
timingInfo.Timings.AddRange(new[] { new ClassicLyricTimingPoint { Time = 1000 } });

var existTimingPoint = timingInfo.Timings.First();
int? existTimingPointOrder = timingInfo.GetTimingPointOrder(existTimingPoint);
Assert.AreEqual(1, existTimingPointOrder);

var notExistTimingPoint = new ClassicLyricTimingPoint { Time = 1000 };
int? notExistTimingPointOrder = timingInfo.GetTimingPointOrder(notExistTimingPoint);
Assert.IsNull(notExistTimingPointOrder);
}

[Test]
public void TestGetLyricTimingPoints()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using osu.Game.Overlays;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Karaoke.Beatmaps;
using osu.Game.Rulesets.Karaoke.Beatmaps.Stages.Classic;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Stages.Classic;
using osu.Game.Rulesets.Karaoke.Tests.Beatmaps;
using osu.Game.Screens.Edit;
Expand Down Expand Up @@ -49,6 +50,9 @@ protected virtual KaraokeBeatmap CreateBeatmap()
if (new KaraokeBeatmapConverter(beatmap, new KaraokeRuleset()).Convert() is not KaraokeBeatmap karaokeBeatmap)
throw new ArgumentNullException(nameof(karaokeBeatmap));

// add classic stage info for testing purpose.
karaokeBeatmap.StageInfos.Add(new ClassicStageInfo());

return karaokeBeatmap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using osu.Game.Overlays;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Karaoke.Beatmaps;
using osu.Game.Rulesets.Karaoke.Beatmaps.Stages.Classic;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Stages.Classic;
using osu.Game.Rulesets.Karaoke.Tests.Beatmaps;
using osu.Game.Screens.Edit;
Expand All @@ -29,6 +30,10 @@ public TestSceneClassicStageEditor()
{
var beatmap = new TestKaraokeBeatmap(new KaraokeRuleset().RulesetInfo);
var karaokeBeatmap = new KaraokeBeatmapConverter(beatmap, new KaraokeRuleset()).Convert() as KaraokeBeatmap;

// add classic stage info for testing purpose.
karaokeBeatmap!.StageInfos.Add(new ClassicStageInfo());

editorBeatmap = new EditorBeatmap(karaokeBeatmap);
}

Expand Down
2 changes: 2 additions & 0 deletions osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class KaraokeBeatmap : Beatmap<KaraokeHitObject>

public int TotalColumns { get; set; } = 9;

public TStageInfo? GetStageInfo<TStageInfo>() => StageInfos.OfType<TStageInfo>().FirstOrDefault();

public override IEnumerable<BeatmapStatistic> GetStatistics()
{
int singers = SingerInfo.GetAllSingers().Count();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class ClassicLyricTimingInfo
private readonly Bindable<int> timingVersion = new();

// todo: should be readonly.
public BindableList<ClassicLyricTimingPoint> Timings = new BindableList<ClassicLyricTimingPoint>();
public BindableList<ClassicLyricTimingPoint> Timings = new();

[JsonIgnore]
public List<ClassicLyricTimingPoint> SortedTimings { get; private set; } = new();
Expand Down Expand Up @@ -55,12 +55,12 @@ public ClassicLyricTimingInfo()
break;
}

onPageChanged();
onTimingChanged();

void timeValueChanged(ValueChangedEvent<double> e) => onPageChanged();
void timeValueChanged(ValueChangedEvent<double> e) => onTimingChanged();
};

void onPageChanged()
void onTimingChanged()
{
SortedTimings = Timings.OrderBy(x => x.Time).ToList();
timingVersion.Value++;
Expand Down Expand Up @@ -175,6 +175,12 @@ public void ClearLyricFromMapping(Lyric lyric)

#region Query

public int? GetTimingPointOrder(ClassicLyricTimingPoint point)
{
int index = SortedTimings.IndexOf(point);
return index == -1 ? null : index + 1;
}

public IEnumerable<ClassicLyricTimingPoint> GetLyricTimingPoints(Lyric lyric)
{
if (!Mappings.TryGetValue(lyric.ID, out int[]? ids))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Bindables;
using osu.Game.Rulesets.Karaoke.Beatmaps.Stages.Classic;

namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Stages.Classic.Stage;

Expand All @@ -18,4 +19,6 @@ public interface IStageEditorStateProvider
StageEditorEditMode EditMode => BindableEditMode.Value;

void ChangeEditMode(StageEditorEditMode mode);

ClassicStageInfo StageInfo { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ private void load(OverlayColourProvider colourProvider, IStageEditorStateProvide
StageEditorEditMode.Edit => new Drawable[]
{
new StageEditorEditModeSection(StageEditorEditCategory.Timing),
new TimingPointsSection(),
},
StageEditorEditMode.Verify => new Drawable[]
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using System.Diagnostics.CodeAnalysis;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Localisation;
using osu.Game.Extensions;
using osu.Game.Rulesets.Karaoke.Beatmaps.Stages.Classic;
using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps;
using osu.Game.Screens.Edit;

namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Stages.Classic.Stage.Settings;

public partial class TimingPointsSection : EditorSection
{
protected override LocalisableString Title => "Timings";

public TimingPointsSection()
{
Add(new SectionPageInfoEditor());
}

private partial class SectionPageInfoEditor : SectionTimingInfoItemsEditor<ClassicLyricTimingPoint>
{
[BackgroundDependencyLoader]
private void load(IStageEditorStateProvider stageEditorStateProvider)
{
Items.BindTo(stageEditorStateProvider.StageInfo.LyricTimingInfo.Timings);
}

protected override DrawableTimingInfoItem CreateTimingInfoDrawable(ClassicLyricTimingPoint item) => new DrawableTimingPoint(item);

protected override EditorSectionButton? CreateCreateNewItemButton() => new CreateNewTimingPointButton();

private partial class DrawableTimingPoint : DrawableTimingInfoItem
{
private readonly IBindable<int> timingPointsVersion = new Bindable<int>();

[Resolved, AllowNull]
private IBeatmapClassicStageChangeHandler beatmapClassicStageChangeHandler { get; set; }

public DrawableTimingPoint(ClassicLyricTimingPoint item)
: base(item)
{
}

protected override void RemoveItem(ClassicLyricTimingPoint item)
{
beatmapClassicStageChangeHandler.RemoveTimingPoint(item);
}

[BackgroundDependencyLoader]
private void load(IStageEditorStateProvider stageEditorStateProvider)
{
timingPointsVersion.BindTo(stageEditorStateProvider.StageInfo.LyricTimingInfo.TimingVersion);
timingPointsVersion.BindValueChanged(_ =>
{
int? order = stageEditorStateProvider.StageInfo.LyricTimingInfo.GetTimingPointOrder(Item);
double time = Item.Time;

ChangeDisplayOrder((int)time);
Text = $"#{order} {time.ToEditorFormattedString()}";
}, true);
}
}

private partial class CreateNewTimingPointButton : EditorSectionButton
{
[Resolved, AllowNull]
private IBeatmapClassicStageChangeHandler beatmapClassicStageChangeHandler { get; set; }

[Resolved, AllowNull]
private EditorClock clock { get; set; }

public CreateNewTimingPointButton()
{
Text = "Create new timing";
Action = () =>
{
double currentTime = clock.CurrentTime;
beatmapClassicStageChangeHandler.AddTimingPoint(x => x.Time = currentTime);
};
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Diagnostics.CodeAnalysis;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Karaoke.Beatmaps;
using osu.Game.Rulesets.Karaoke.Beatmaps.Stages.Classic;
using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Stages.Classic.Stage.Settings;
using osu.Game.Screens.Edit;

namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Stages.Classic.Stage;

Expand All @@ -18,12 +24,22 @@ public partial class StageScreen : ClassicStageScreen, IStageEditorStateProvider
private readonly Bindable<StageEditorEditCategory> bindableCategory = new();
private readonly Bindable<StageEditorEditMode> bindableEditMode = new();

[Cached(typeof(IBeatmapClassicStageChangeHandler))]
private readonly BeatmapClassicStageChangeHandler beatmapClassicStageChangeHandler;

[Cached(typeof(IStageEditorVerifier))]
private readonly StageEditorVerifier stageEditorVerifier;

[Resolved, AllowNull]
private EditorBeatmap editorBeatmap { get; set; }

public ClassicStageInfo StageInfo => (editorBeatmap.PlayableBeatmap as KaraokeBeatmap)!.GetStageInfo<ClassicStageInfo>()
?? throw new InvalidOperationException();

public StageScreen()
: base(ClassicStageEditorScreenMode.Stage)
{
AddInternal(beatmapClassicStageChangeHandler = new BeatmapClassicStageChangeHandler());
AddInternal(stageEditorVerifier = new StageEditorVerifier());

Child = new GridContainer
Expand Down

0 comments on commit 5c4325e

Please sign in to comment.