diff --git a/osu.Game.Rulesets.Karaoke/Edit/Lyrics/Compose/SpecialActionToolbar.cs b/osu.Game.Rulesets.Karaoke/Edit/Lyrics/Compose/SpecialActionToolbar.cs index 9982c3454..c78b8e877 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Lyrics/Compose/SpecialActionToolbar.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Lyrics/Compose/SpecialActionToolbar.cs @@ -11,6 +11,7 @@ using osu.Game.Rulesets.Karaoke.Edit.Lyrics.Compose.Toolbar; using osu.Game.Rulesets.Karaoke.Edit.Lyrics.Compose.Toolbar.Carets; using osu.Game.Rulesets.Karaoke.Edit.Lyrics.Compose.Toolbar.Panels; +using osu.Game.Rulesets.Karaoke.Edit.Lyrics.Compose.Toolbar.Playback; using osu.Game.Rulesets.Karaoke.Edit.Lyrics.Compose.Toolbar.TimeTags; using osu.Game.Rulesets.Karaoke.Edit.Lyrics.States.Modes; using osu.Game.Rulesets.Karaoke.Edit.Utils; @@ -21,8 +22,10 @@ namespace osu.Game.Rulesets.Karaoke.Edit.Lyrics.Compose public class SpecialActionToolbar : CompositeDrawable { public const int HEIGHT = 26; - public const int ICON_SPACING = 2; - public const int ICON_SIZE = HEIGHT - ICON_SPACING * 2; + public const int PADDING = 2; + public const int ICON_SIZE = HEIGHT - PADDING * 2; + + public const int SPACING = 5; private readonly IBindable bindableModeAndSubMode = new Bindable(); @@ -44,7 +47,7 @@ public SpecialActionToolbar() { AutoSizeAxes = Axes.Both, Padding = new MarginPadding(5), - Spacing = new Vector2(5), + Spacing = new Vector2(SPACING), Children = new Drawable[] { new TogglePropertyPanelButton(), @@ -129,6 +132,8 @@ static IEnumerable createItemsForEditTimeTagMode(TimeTagEditMode timeT }, TimeTagEditMode.Recording => new Drawable[] { + new PlaybackSwitchButton(), + new Separator(), new MoveToFirstIndexButton(), new MoveToPreviousIndexButton(), new MoveToNextIndexButton(), @@ -137,7 +142,10 @@ static IEnumerable createItemsForEditTimeTagMode(TimeTagEditMode timeT new ClearTimeTagTimeButton(), new ClearAllTimeTagTimeButton(), }, - TimeTagEditMode.Adjust => Array.Empty(), + TimeTagEditMode.Adjust => new Drawable[] + { + new PlaybackSwitchButton(), + }, _ => throw new ArgumentOutOfRangeException(nameof(timeTagEditMode), timeTagEditMode, null) }; diff --git a/osu.Game.Rulesets.Karaoke/Edit/Lyrics/Compose/Toolbar/Playback/PlaybackSwitchButton.cs b/osu.Game.Rulesets.Karaoke/Edit/Lyrics/Compose/Toolbar/Playback/PlaybackSwitchButton.cs new file mode 100644 index 000000000..8eff315ff --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Lyrics/Compose/Toolbar/Playback/PlaybackSwitchButton.cs @@ -0,0 +1,118 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osuTK; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Track; +using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Edit; + +namespace osu.Game.Rulesets.Karaoke.Edit.Lyrics.Compose.Toolbar.Playback +{ + public class PlaybackSwitchButton : CompositeDrawable + { + private readonly IBindable track = new Bindable(); + private readonly BindableNumber freqAdjust = new BindableDouble(1); + + public PlaybackSwitchButton() + { + Height = SpecialActionToolbar.HEIGHT; + AutoSizeAxes = Axes.X; + InternalChild = new PlaybackTabControl + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = freqAdjust + }; + + track.BindValueChanged(tr => + { + tr.OldValue?.RemoveAdjustment(AdjustableProperty.Frequency, freqAdjust); + + // notice that it's not the same bindable as PlaybackControl because track can accept many bindable at the same time. + // should have the better way to get the overall playback speed in the editor but it's OK for now. + tr.NewValue?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + }); + } + + [BackgroundDependencyLoader] + private void load(EditorClock clock) + { + track.BindTo(clock.Track); + } + + protected override void Dispose(bool isDisposing) + { + track.Value?.RemoveAdjustment(AdjustableProperty.Frequency, freqAdjust); + + base.Dispose(isDisposing); + } + + private class PlaybackTabControl : OsuTabControl + { + private static readonly double[] tempo_values = { 0.25, 0.5, 0.75, 1 }; + + protected override Dropdown? CreateDropdown() => null; + + protected override TabItem CreateTabItem(double value) => new PlaybackTabItem(value); + + protected override TabFillFlowContainer CreateTabFlow() => new() + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(SpecialActionToolbar.SPACING), + Direction = FillDirection.Horizontal, + }; + + public PlaybackTabControl() + { + AutoSizeAxes = Axes.Both; + + tempo_values.ForEach(AddItem); + } + + public class PlaybackTabItem : TabItem + { + private const float fade_duration = 200; + + private readonly OsuSpriteText text; + + public PlaybackTabItem(double value) + : base(value) + { + Size = new Vector2(SpecialActionToolbar.ICON_SIZE); + + Children = new Drawable[] + { + text = new OsuSpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = $"{value:0%}", + }, + }; + + updateState(); + } + + protected override void OnActivated() => updateState(); + protected override void OnDeactivated() => updateState(); + + private void updateState() + { + bool active = Active.Value; + + text.Alpha = active ? 1 : 0.5f; + text.Font = OsuFont.GetFont(size: 14, weight: active ? FontWeight.Bold : FontWeight.Medium); + } + } + } + } +}