mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 10:02:59 +08:00
Merge remote-tracking branch 'upstream/master' into improve-song-select-uiscale
This commit is contained in:
commit
f5a3de3187
@ -19,18 +19,22 @@ using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
|||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
public class TestSceneBarHitErrorMeter : OsuTestScene
|
public class TestSceneHitErrorMeter : OsuTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(HitErrorMeter),
|
typeof(HitErrorMeter),
|
||||||
|
typeof(BarHitErrorMeter),
|
||||||
|
typeof(ColourHitErrorMeter)
|
||||||
};
|
};
|
||||||
|
|
||||||
private HitErrorMeter meter;
|
private BarHitErrorMeter barMeter;
|
||||||
private HitErrorMeter meter2;
|
private BarHitErrorMeter barMeter2;
|
||||||
|
private ColourHitErrorMeter colourMeter;
|
||||||
|
private ColourHitErrorMeter colourMeter2;
|
||||||
private HitWindows hitWindows;
|
private HitWindows hitWindows;
|
||||||
|
|
||||||
public TestSceneBarHitErrorMeter()
|
public TestSceneHitErrorMeter()
|
||||||
{
|
{
|
||||||
recreateDisplay(new OsuHitWindows(), 5);
|
recreateDisplay(new OsuHitWindows(), 5);
|
||||||
|
|
||||||
@ -91,17 +95,31 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(meter = new BarHitErrorMeter(hitWindows, true)
|
Add(barMeter = new BarHitErrorMeter(hitWindows, true)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreRight,
|
Anchor = Anchor.CentreRight,
|
||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.CentreRight,
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(meter2 = new BarHitErrorMeter(hitWindows, false)
|
Add(barMeter2 = new BarHitErrorMeter(hitWindows, false)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Add(colourMeter = new ColourHitErrorMeter(hitWindows)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Margin = new MarginPadding { Right = 50 }
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(colourMeter2 = new ColourHitErrorMeter(hitWindows)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Margin = new MarginPadding { Left = 50 }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void newJudgement(double offset = 0)
|
private void newJudgement(double offset = 0)
|
||||||
@ -112,8 +130,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
Type = HitResult.Perfect,
|
Type = HitResult.Perfect,
|
||||||
};
|
};
|
||||||
|
|
||||||
meter.OnNewJudgement(judgement);
|
barMeter.OnNewJudgement(judgement);
|
||||||
meter2.OnNewJudgement(judgement);
|
barMeter2.OnNewJudgement(judgement);
|
||||||
|
colourMeter.OnNewJudgement(judgement);
|
||||||
|
colourMeter2.OnNewJudgement(judgement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,17 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
@ -15,63 +20,125 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneSongProgress : OsuTestScene
|
public class TestSceneSongProgress : OsuTestScene
|
||||||
{
|
{
|
||||||
private readonly SongProgress progress;
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
private readonly TestSongProgressGraph graph;
|
{
|
||||||
|
typeof(SongProgressBar),
|
||||||
|
};
|
||||||
|
|
||||||
|
private SongProgress progress;
|
||||||
|
private TestSongProgressGraph graph;
|
||||||
|
private readonly Container progressContainer;
|
||||||
|
|
||||||
private readonly StopwatchClock clock;
|
private readonly StopwatchClock clock;
|
||||||
|
private readonly FramedClock framedClock;
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly GameplayClock gameplayClock;
|
private readonly GameplayClock gameplayClock;
|
||||||
|
|
||||||
private readonly FramedClock framedClock;
|
|
||||||
|
|
||||||
public TestSceneSongProgress()
|
public TestSceneSongProgress()
|
||||||
{
|
{
|
||||||
clock = new StopwatchClock(true);
|
clock = new StopwatchClock();
|
||||||
|
|
||||||
gameplayClock = new GameplayClock(framedClock = new FramedClock(clock));
|
gameplayClock = new GameplayClock(framedClock = new FramedClock(clock));
|
||||||
|
|
||||||
Add(progress = new SongProgress
|
Add(progressContainer = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomCentre,
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomCentre,
|
||||||
|
Height = 100,
|
||||||
|
Y = -100,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = OsuColour.Gray(1),
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(graph = new TestSongProgressGraph
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = 200,
|
|
||||||
Anchor = Anchor.TopLeft,
|
|
||||||
Origin = Anchor.TopLeft,
|
|
||||||
});
|
|
||||||
|
|
||||||
AddWaitStep("wait some", 5);
|
|
||||||
AddAssert("ensure not created", () => graph.CreationCount == 0);
|
|
||||||
|
|
||||||
AddStep("display values", displayNewValues);
|
|
||||||
AddWaitStep("wait some", 5);
|
|
||||||
AddUntilStep("wait for creation count", () => graph.CreationCount == 1);
|
|
||||||
|
|
||||||
AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking);
|
|
||||||
AddWaitStep("wait some", 5);
|
|
||||||
AddUntilStep("wait for creation count", () => graph.CreationCount == 1);
|
|
||||||
|
|
||||||
AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking);
|
|
||||||
AddWaitStep("wait some", 5);
|
|
||||||
AddUntilStep("wait for creation count", () => graph.CreationCount == 1);
|
|
||||||
AddRepeatStep("New Values", displayNewValues, 5);
|
|
||||||
|
|
||||||
AddWaitStep("wait some", 5);
|
|
||||||
AddAssert("ensure debounced", () => graph.CreationCount == 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayNewValues()
|
[SetUpSteps]
|
||||||
|
public void SetupSteps()
|
||||||
{
|
{
|
||||||
List<HitObject> objects = new List<HitObject>();
|
AddStep("add new song progress", () =>
|
||||||
|
{
|
||||||
|
if (progress != null)
|
||||||
|
{
|
||||||
|
progress.Expire();
|
||||||
|
progress = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
progressContainer.Add(progress = new SongProgress
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("add new big graph", () =>
|
||||||
|
{
|
||||||
|
if (graph != null)
|
||||||
|
{
|
||||||
|
graph.Expire();
|
||||||
|
graph = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Add(graph = new TestSongProgressGraph
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 200,
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("reset clock", clock.Reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGraphRecreation()
|
||||||
|
{
|
||||||
|
AddAssert("ensure not created", () => graph.CreationCount == 0);
|
||||||
|
AddStep("display values", displayRandomValues);
|
||||||
|
AddUntilStep("wait for creation count", () => graph.CreationCount == 1);
|
||||||
|
AddRepeatStep("new values", displayRandomValues, 5);
|
||||||
|
AddWaitStep("wait some", 5);
|
||||||
|
AddAssert("ensure recreation debounced", () => graph.CreationCount == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDisplay()
|
||||||
|
{
|
||||||
|
AddStep("display max values", displayMaxValues);
|
||||||
|
AddUntilStep("wait for graph", () => graph.CreationCount == 1);
|
||||||
|
AddStep("start", clock.Start);
|
||||||
|
AddStep("allow seeking", () => progress.AllowSeeking.Value = true);
|
||||||
|
AddStep("hide graph", () => progress.ShowGraph.Value = false);
|
||||||
|
AddStep("disallow seeking", () => progress.AllowSeeking.Value = false);
|
||||||
|
AddStep("allow seeking", () => progress.AllowSeeking.Value = true);
|
||||||
|
AddStep("show graph", () => progress.ShowGraph.Value = true);
|
||||||
|
AddStep("stop", clock.Stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayRandomValues()
|
||||||
|
{
|
||||||
|
var objects = new List<HitObject>();
|
||||||
for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000)
|
for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000)
|
||||||
objects.Add(new HitObject { StartTime = i });
|
objects.Add(new HitObject { StartTime = i });
|
||||||
|
|
||||||
|
replaceObjects(objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayMaxValues()
|
||||||
|
{
|
||||||
|
var objects = new List<HitObject>();
|
||||||
|
for (double i = 0; i < 5000; i++)
|
||||||
|
objects.Add(new HitObject { StartTime = i });
|
||||||
|
|
||||||
|
replaceObjects(objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void replaceObjects(List<HitObject> objects)
|
||||||
|
{
|
||||||
progress.Objects = objects;
|
progress.Objects = objects;
|
||||||
graph.Objects = objects;
|
graph.Objects = objects;
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ namespace osu.Game.Configuration
|
|||||||
Set(OsuSetting.HitLighting, true);
|
Set(OsuSetting.HitLighting, true);
|
||||||
|
|
||||||
Set(OsuSetting.ShowInterface, true);
|
Set(OsuSetting.ShowInterface, true);
|
||||||
|
Set(OsuSetting.ShowProgressGraph, true);
|
||||||
Set(OsuSetting.ShowHealthDisplayWhenCantFail, true);
|
Set(OsuSetting.ShowHealthDisplayWhenCantFail, true);
|
||||||
Set(OsuSetting.KeyOverlay, false);
|
Set(OsuSetting.KeyOverlay, false);
|
||||||
Set(OsuSetting.ScoreMeter, ScoreMeterType.HitErrorBoth);
|
Set(OsuSetting.ScoreMeter, ScoreMeterType.HitErrorBoth);
|
||||||
@ -150,6 +151,7 @@ namespace osu.Game.Configuration
|
|||||||
ScoreMeter,
|
ScoreMeter,
|
||||||
FloatingComments,
|
FloatingComments,
|
||||||
ShowInterface,
|
ShowInterface,
|
||||||
|
ShowProgressGraph,
|
||||||
ShowHealthDisplayWhenCantFail,
|
ShowHealthDisplayWhenCantFail,
|
||||||
MouseDisableButtons,
|
MouseDisableButtons,
|
||||||
MouseDisableWheel,
|
MouseDisableWheel,
|
||||||
|
@ -18,5 +18,14 @@ namespace osu.Game.Configuration
|
|||||||
|
|
||||||
[Description("Hit Error (both)")]
|
[Description("Hit Error (both)")]
|
||||||
HitErrorBoth,
|
HitErrorBoth,
|
||||||
|
|
||||||
|
[Description("Colour (left)")]
|
||||||
|
ColourLeft,
|
||||||
|
|
||||||
|
[Description("Colour (right)")]
|
||||||
|
ColourRight,
|
||||||
|
|
||||||
|
[Description("Colour (both)")]
|
||||||
|
ColourBoth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ namespace osu.Game.Overlays.Comments
|
|||||||
private readonly FillFlowContainer content;
|
private readonly FillFlowContainer content;
|
||||||
private readonly DeletedChildrenPlaceholder deletedChildrenPlaceholder;
|
private readonly DeletedChildrenPlaceholder deletedChildrenPlaceholder;
|
||||||
private readonly CommentsShowMoreButton moreButton;
|
private readonly CommentsShowMoreButton moreButton;
|
||||||
|
private readonly TotalCommentsCounter commentCounter;
|
||||||
|
|
||||||
public CommentsContainer()
|
public CommentsContainer()
|
||||||
{
|
{
|
||||||
@ -56,6 +57,7 @@ namespace osu.Game.Overlays.Comments
|
|||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
|
commentCounter = new TotalCommentsCounter(),
|
||||||
new CommentsHeader
|
new CommentsHeader
|
||||||
{
|
{
|
||||||
Sort = { BindTarget = Sort },
|
Sort = { BindTarget = Sort },
|
||||||
@ -133,6 +135,9 @@ namespace osu.Game.Overlays.Comments
|
|||||||
if (!IsLoaded)
|
if (!IsLoaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// only reset when changing ID/type. other refetch ops are generally just changing sort order.
|
||||||
|
commentCounter.Current.Value = 0;
|
||||||
|
|
||||||
refetchComments();
|
refetchComments();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +204,8 @@ namespace osu.Game.Overlays.Comments
|
|||||||
moreButton.IsLoading = false;
|
moreButton.IsLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commentCounter.Current.Value = response.Total;
|
||||||
|
|
||||||
moreButton.FadeTo(response.HasMore ? 1 : 0);
|
moreButton.FadeTo(response.HasMore ? 1 : 0);
|
||||||
}, loadCancellation.Token);
|
}, loadCancellation.Token);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
|||||||
Bindable = config.GetBindable<bool>(OsuSetting.ShowInterface)
|
Bindable = config.GetBindable<bool>(OsuSetting.ShowInterface)
|
||||||
},
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
|
{
|
||||||
|
LabelText = "Show difficulty graph on progress bar",
|
||||||
|
Bindable = config.GetBindable<bool>(OsuSetting.ShowProgressGraph)
|
||||||
|
},
|
||||||
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
LabelText = "Show health display even when you can't fail",
|
LabelText = "Show health display even when you can't fail",
|
||||||
Bindable = config.GetBindable<bool>(OsuSetting.ShowHealthDisplayWhenCantFail),
|
Bindable = config.GetBindable<bool>(OsuSetting.ShowHealthDisplayWhenCantFail),
|
||||||
|
@ -5,6 +5,8 @@ using System.Linq;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -25,13 +27,13 @@ namespace osu.Game.Screens.Edit.Components
|
|||||||
|
|
||||||
private IAdjustableClock adjustableClock;
|
private IAdjustableClock adjustableClock;
|
||||||
|
|
||||||
|
private readonly BindableNumber<double> tempo = new BindableDouble(1);
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IAdjustableClock adjustableClock)
|
private void load(IAdjustableClock adjustableClock)
|
||||||
{
|
{
|
||||||
this.adjustableClock = adjustableClock;
|
this.adjustableClock = adjustableClock;
|
||||||
|
|
||||||
PlaybackTabControl tabs;
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
playButton = new IconButton
|
playButton = new IconButton
|
||||||
@ -58,11 +60,18 @@ namespace osu.Game.Screens.Edit.Components
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Height = 0.5f,
|
Height = 0.5f,
|
||||||
Padding = new MarginPadding { Left = 45 },
|
Padding = new MarginPadding { Left = 45 },
|
||||||
Child = tabs = new PlaybackTabControl(),
|
Child = new PlaybackTabControl { Current = tempo },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tabs.Current.ValueChanged += tempo => Beatmap.Value.Track.Tempo.Value = tempo.NewValue;
|
Track?.AddAdjustment(AdjustableProperty.Tempo, tempo);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
Track?.RemoveAdjustment(AdjustableProperty.Tempo, tempo);
|
||||||
|
|
||||||
|
base.Dispose(isDisposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnKeyDown(KeyDownEvent e)
|
protected override bool OnKeyDown(KeyDownEvent e)
|
||||||
|
@ -46,6 +46,8 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
||||||
|
|
||||||
|
public override bool AllowRateAdjustments => false;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private BeatmapManager beatmapManager { get; set; }
|
private BeatmapManager beatmapManager { get; set; }
|
||||||
|
|
||||||
@ -262,12 +264,6 @@ namespace osu.Game.Screens.Edit
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnResuming(IScreen last)
|
|
||||||
{
|
|
||||||
base.OnResuming(last);
|
|
||||||
Beatmap.Value.Track?.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnEntering(IScreen last)
|
public override void OnEntering(IScreen last)
|
||||||
{
|
{
|
||||||
base.OnEntering(last);
|
base.OnEntering(last);
|
||||||
@ -291,7 +287,6 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
private void resetTrack(bool seekToStart = false)
|
private void resetTrack(bool seekToStart = false)
|
||||||
{
|
{
|
||||||
Beatmap.Value.Track?.ResetSpeedAdjustments();
|
|
||||||
Beatmap.Value.Track?.Stop();
|
Beatmap.Value.Track?.Stop();
|
||||||
|
|
||||||
if (seekToStart)
|
if (seekToStart)
|
||||||
|
@ -77,6 +77,19 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
case ScoreMeterType.HitErrorRight:
|
case ScoreMeterType.HitErrorRight:
|
||||||
createBar(true);
|
createBar(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ScoreMeterType.ColourBoth:
|
||||||
|
createColour(false);
|
||||||
|
createColour(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ScoreMeterType.ColourLeft:
|
||||||
|
createColour(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ScoreMeterType.ColourRight:
|
||||||
|
createColour(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +103,24 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
completeDisplayLoading(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createColour(bool rightAligned)
|
||||||
|
{
|
||||||
|
var display = new ColourHitErrorMeter(hitWindows)
|
||||||
|
{
|
||||||
|
Margin = new MarginPadding(margin),
|
||||||
|
Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft,
|
||||||
|
Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft,
|
||||||
|
Alpha = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
completeDisplayLoading(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void completeDisplayLoading(HitErrorMeter display)
|
||||||
|
{
|
||||||
Add(display);
|
Add(display);
|
||||||
display.FadeInFromZero(fade_duration, Easing.OutQuint);
|
display.FadeInFromZero(fade_duration, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
@ -163,30 +163,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
centre.Width = 2.5f;
|
centre.Width = 2.5f;
|
||||||
colourBars.Add(centre);
|
colourBars.Add(centre);
|
||||||
|
|
||||||
Color4 getColour(HitResult result)
|
|
||||||
{
|
|
||||||
switch (result)
|
|
||||||
{
|
|
||||||
case HitResult.Meh:
|
|
||||||
return colours.Yellow;
|
|
||||||
|
|
||||||
case HitResult.Ok:
|
|
||||||
return colours.Green;
|
|
||||||
|
|
||||||
case HitResult.Good:
|
|
||||||
return colours.GreenLight;
|
|
||||||
|
|
||||||
case HitResult.Great:
|
|
||||||
return colours.Blue;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return colours.BlueLight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Drawable createColourBar(HitResult result, float height, bool first = false)
|
Drawable createColourBar(HitResult result, float height, bool first = false)
|
||||||
{
|
{
|
||||||
var colour = getColour(result);
|
var colour = GetColourForHitResult(result);
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
@ -201,7 +180,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = getColour(result),
|
Colour = colour,
|
||||||
Height = height * gradient_start
|
Height = height * gradient_start
|
||||||
},
|
},
|
||||||
new Box
|
new Box
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
||||||
|
{
|
||||||
|
public class ColourHitErrorMeter : HitErrorMeter
|
||||||
|
{
|
||||||
|
private const int animation_duration = 200;
|
||||||
|
|
||||||
|
private readonly JudgementFlow judgementsFlow;
|
||||||
|
|
||||||
|
public ColourHitErrorMeter(HitWindows hitWindows)
|
||||||
|
: base(hitWindows)
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
InternalChild = judgementsFlow = new JudgementFlow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNewJudgement(JudgementResult judgement) => judgementsFlow.Push(GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset)));
|
||||||
|
|
||||||
|
private class JudgementFlow : FillFlowContainer<HitErrorCircle>
|
||||||
|
{
|
||||||
|
private const int max_available_judgements = 20;
|
||||||
|
private const int drawable_judgement_size = 8;
|
||||||
|
private const int spacing = 2;
|
||||||
|
|
||||||
|
public override IEnumerable<Drawable> FlowingChildren => base.FlowingChildren.Reverse();
|
||||||
|
|
||||||
|
public JudgementFlow()
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.X;
|
||||||
|
Height = max_available_judgements * (drawable_judgement_size + spacing) - spacing;
|
||||||
|
Spacing = new Vector2(0, spacing);
|
||||||
|
Direction = FillDirection.Vertical;
|
||||||
|
LayoutDuration = animation_duration;
|
||||||
|
LayoutEasing = Easing.OutQuint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Push(Color4 colour)
|
||||||
|
{
|
||||||
|
Add(new HitErrorCircle(colour, drawable_judgement_size));
|
||||||
|
|
||||||
|
if (Children.Count > max_available_judgements)
|
||||||
|
Children.FirstOrDefault(c => !c.IsRemoved)?.Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HitErrorCircle : Container
|
||||||
|
{
|
||||||
|
public bool IsRemoved { get; private set; }
|
||||||
|
|
||||||
|
private readonly Circle circle;
|
||||||
|
|
||||||
|
public HitErrorCircle(Color4 colour, int size)
|
||||||
|
{
|
||||||
|
Size = new Vector2(size);
|
||||||
|
Child = circle = new Circle
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
Colour = colour
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
circle.FadeInFromZero(animation_duration, Easing.OutQuint);
|
||||||
|
circle.MoveToY(-DrawSize.Y);
|
||||||
|
circle.MoveToY(0, animation_duration, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove()
|
||||||
|
{
|
||||||
|
IsRemoved = true;
|
||||||
|
|
||||||
|
this.FadeOut(animation_duration, Easing.OutQuint).Expire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,12 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
||||||
{
|
{
|
||||||
@ -11,11 +14,38 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
|
|||||||
{
|
{
|
||||||
protected readonly HitWindows HitWindows;
|
protected readonly HitWindows HitWindows;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
protected HitErrorMeter(HitWindows hitWindows)
|
protected HitErrorMeter(HitWindows hitWindows)
|
||||||
{
|
{
|
||||||
HitWindows = hitWindows;
|
HitWindows = hitWindows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void OnNewJudgement(JudgementResult judgement);
|
public abstract void OnNewJudgement(JudgementResult judgement);
|
||||||
|
|
||||||
|
protected Color4 GetColourForHitResult(HitResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case HitResult.Miss:
|
||||||
|
return colours.Red;
|
||||||
|
|
||||||
|
case HitResult.Meh:
|
||||||
|
return colours.Yellow;
|
||||||
|
|
||||||
|
case HitResult.Ok:
|
||||||
|
return colours.Green;
|
||||||
|
|
||||||
|
case HitResult.Good:
|
||||||
|
return colours.GreenLight;
|
||||||
|
|
||||||
|
case HitResult.Great:
|
||||||
|
return colours.Blue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return colours.BlueLight;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,6 @@ namespace osu.Game.Screens.Play
|
|||||||
BindDrawableRuleset(drawableRuleset);
|
BindDrawableRuleset(drawableRuleset);
|
||||||
|
|
||||||
Progress.Objects = drawableRuleset.Objects;
|
Progress.Objects = drawableRuleset.Objects;
|
||||||
Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value;
|
|
||||||
Progress.RequestSeek = time => RequestSeek(time);
|
Progress.RequestSeek = time => RequestSeek(time);
|
||||||
Progress.ReferenceClock = drawableRuleset.FrameStableClock;
|
Progress.ReferenceClock = drawableRuleset.FrameStableClock;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ using osu.Framework.Allocation;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
|
|
||||||
@ -18,8 +19,9 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
public class SongProgress : OverlayContainer
|
public class SongProgress : OverlayContainer
|
||||||
{
|
{
|
||||||
|
private const int info_height = 20;
|
||||||
private const int bottom_bar_height = 5;
|
private const int bottom_bar_height = 5;
|
||||||
|
private const float graph_height = SquareGraph.Column.WIDTH * 6;
|
||||||
private static readonly Vector2 handle_size = new Vector2(10, 18);
|
private static readonly Vector2 handle_size = new Vector2(10, 18);
|
||||||
|
|
||||||
private const float transition_duration = 200;
|
private const float transition_duration = 200;
|
||||||
@ -30,12 +32,19 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public Action<double> RequestSeek;
|
public Action<double> RequestSeek;
|
||||||
|
|
||||||
public override bool HandleNonPositionalInput => AllowSeeking;
|
/// <summary>
|
||||||
public override bool HandlePositionalInput => AllowSeeking;
|
/// Whether seeking is allowed and the progress bar should be shown.
|
||||||
|
/// </summary>
|
||||||
|
public readonly Bindable<bool> AllowSeeking = new Bindable<bool>();
|
||||||
|
|
||||||
|
public readonly Bindable<bool> ShowGraph = new Bindable<bool>();
|
||||||
|
|
||||||
//TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list).
|
//TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list).
|
||||||
private double lastHitTime => objects.Last().GetEndTime() + 1;
|
private double lastHitTime => objects.Last().GetEndTime() + 1;
|
||||||
|
|
||||||
|
public override bool HandleNonPositionalInput => AllowSeeking.Value;
|
||||||
|
public override bool HandlePositionalInput => AllowSeeking.Value;
|
||||||
|
|
||||||
private double firstHitTime => objects.First().StartTime;
|
private double firstHitTime => objects.First().StartTime;
|
||||||
|
|
||||||
private IEnumerable<HitObject> objects;
|
private IEnumerable<HitObject> objects;
|
||||||
@ -54,27 +63,14 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly BindableBool replayLoaded = new BindableBool();
|
|
||||||
|
|
||||||
public IClock ReferenceClock;
|
public IClock ReferenceClock;
|
||||||
|
|
||||||
private IClock gameplayClock;
|
private IClock gameplayClock;
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
|
||||||
private void load(OsuColour colours, GameplayClock clock)
|
|
||||||
{
|
|
||||||
if (clock != null)
|
|
||||||
gameplayClock = clock;
|
|
||||||
|
|
||||||
graph.FillColour = bar.FillColour = colours.BlueLighter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SongProgress()
|
public SongProgress()
|
||||||
{
|
{
|
||||||
const float graph_height = SquareGraph.Column.WIDTH * 6;
|
Masking = true;
|
||||||
|
Height = bottom_bar_height + graph_height + handle_size.Y + info_height;
|
||||||
Height = bottom_bar_height + graph_height + handle_size.Y;
|
|
||||||
Y = bottom_bar_height;
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -83,8 +79,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
Height = info_height,
|
||||||
Margin = new MarginPadding { Bottom = bottom_bar_height + graph_height },
|
|
||||||
},
|
},
|
||||||
graph = new SongProgressGraph
|
graph = new SongProgressGraph
|
||||||
{
|
{
|
||||||
@ -96,7 +91,6 @@ namespace osu.Game.Screens.Play
|
|||||||
},
|
},
|
||||||
bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size)
|
bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size)
|
||||||
{
|
{
|
||||||
Alpha = 0,
|
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
OnSeek = time => RequestSeek?.Invoke(time),
|
OnSeek = time => RequestSeek?.Invoke(time),
|
||||||
@ -104,46 +98,34 @@ namespace osu.Game.Screens.Play
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(OsuColour colours, GameplayClock clock, OsuConfigManager config)
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
|
if (clock != null)
|
||||||
|
gameplayClock = clock;
|
||||||
|
|
||||||
|
config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph);
|
||||||
|
|
||||||
|
graph.FillColour = bar.FillColour = colours.BlueLighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
Show();
|
Show();
|
||||||
|
|
||||||
replayLoaded.ValueChanged += loaded => AllowSeeking = loaded.NewValue;
|
AllowSeeking.BindValueChanged(_ => updateBarVisibility(), true);
|
||||||
replayLoaded.TriggerChange();
|
ShowGraph.BindValueChanged(_ => updateGraphVisibility(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindDrawableRuleset(DrawableRuleset drawableRuleset)
|
public void BindDrawableRuleset(DrawableRuleset drawableRuleset)
|
||||||
{
|
{
|
||||||
replayLoaded.BindTo(drawableRuleset.HasReplayLoaded);
|
AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded);
|
||||||
}
|
|
||||||
|
|
||||||
private bool allowSeeking;
|
|
||||||
|
|
||||||
public bool AllowSeeking
|
|
||||||
{
|
|
||||||
get => allowSeeking;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (allowSeeking == value) return;
|
|
||||||
|
|
||||||
allowSeeking = value;
|
|
||||||
updateBarVisibility();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateBarVisibility()
|
|
||||||
{
|
|
||||||
bar.FadeTo(allowSeeking ? 1 : 0, transition_duration, Easing.In);
|
|
||||||
this.MoveTo(new Vector2(0, allowSeeking ? 0 : bottom_bar_height), transition_duration, Easing.In);
|
|
||||||
|
|
||||||
info.Margin = new MarginPadding { Bottom = Height - (allowSeeking ? 0 : handle_size.Y) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
updateBarVisibility();
|
|
||||||
this.FadeIn(500, Easing.OutQuint);
|
this.FadeIn(500, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,5 +149,28 @@ namespace osu.Game.Screens.Play
|
|||||||
bar.CurrentTime = gameplayTime;
|
bar.CurrentTime = gameplayTime;
|
||||||
graph.Progress = (int)(graph.ColumnCount * progress);
|
graph.Progress = (int)(graph.ColumnCount * progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateBarVisibility()
|
||||||
|
{
|
||||||
|
bar.ShowHandle = AllowSeeking.Value;
|
||||||
|
|
||||||
|
updateInfoMargin();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGraphVisibility()
|
||||||
|
{
|
||||||
|
float barHeight = bottom_bar_height + handle_size.Y;
|
||||||
|
|
||||||
|
bar.ResizeHeightTo(ShowGraph.Value ? barHeight + graph_height : barHeight, transition_duration, Easing.In);
|
||||||
|
graph.MoveToY(ShowGraph.Value ? 0 : bottom_bar_height + graph_height, transition_duration, Easing.In);
|
||||||
|
|
||||||
|
updateInfoMargin();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateInfoMargin()
|
||||||
|
{
|
||||||
|
float finalMargin = bottom_bar_height + (AllowSeeking.Value ? handle_size.Y : 0) + (ShowGraph.Value ? graph_height : 0);
|
||||||
|
info.TransformTo(nameof(info.Margin), new MarginPadding { Bottom = finalMargin }, transition_duration, Easing.In);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,23 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private readonly Box fill;
|
private readonly Box fill;
|
||||||
private readonly Container handleBase;
|
private readonly Container handleBase;
|
||||||
|
private readonly Container handleContainer;
|
||||||
|
|
||||||
|
private bool showHandle;
|
||||||
|
|
||||||
|
public bool ShowHandle
|
||||||
|
{
|
||||||
|
get => showHandle;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == showHandle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
showHandle = value;
|
||||||
|
|
||||||
|
handleBase.FadeTo(showHandle ? 1 : 0, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Color4 FillColour
|
public Color4 FillColour
|
||||||
{
|
{
|
||||||
@ -74,7 +91,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Width = 2,
|
Width = 2,
|
||||||
Height = barHeight + handleBarHeight,
|
Alpha = 0,
|
||||||
Colour = Color4.White,
|
Colour = Color4.White,
|
||||||
Position = new Vector2(2, 0),
|
Position = new Vector2(2, 0),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -84,7 +101,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Name = "HandleBar box",
|
Name = "HandleBar box",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
new Container
|
handleContainer = new Container
|
||||||
{
|
{
|
||||||
Name = "Handle container",
|
Name = "Handle container",
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
@ -116,6 +133,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
|
handleBase.Height = Height - handleContainer.Height;
|
||||||
float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1));
|
float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1));
|
||||||
|
|
||||||
fill.Width = newX;
|
fill.Width = newX;
|
||||||
@ -127,7 +145,11 @@ namespace osu.Game.Screens.Play
|
|||||||
protected override void OnUserChange(double value)
|
protected override void OnUserChange(double value)
|
||||||
{
|
{
|
||||||
scheduledSeek?.Cancel();
|
scheduledSeek?.Cancel();
|
||||||
scheduledSeek = Schedule(() => OnSeek?.Invoke(value));
|
scheduledSeek = Schedule(() =>
|
||||||
|
{
|
||||||
|
if (showHandle)
|
||||||
|
OnSeek?.Invoke(value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user