Skip to content

Commit

Permalink
Merge pull request #2136 from andy840119/rewrite-romaji-edit-mode
Browse files Browse the repository at this point in the history
Rewrite romaji edit mode.
  • Loading branch information
andy840119 authored Sep 29, 2023
2 parents 2085cab + 5e662d5 commit 16f4592
Show file tree
Hide file tree
Showing 37 changed files with 706 additions and 788 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -184,24 +184,7 @@ public void TestGetRubyPosition()
{
AddStep($"Show ruby-tag position: {TextTagUtils.PositionFormattedString(rubyTag)}", () =>
{
var position = karaokeSpriteText.GetTextTagByPosition(rubyTag);
showPosition(position);
});
}
}

#endregion

#region Romaji tag

[Test]
public void TestGetRomajiTagPosition()
{
foreach (var romajiTag in lyric.RomajiTags)
{
AddStep($"Show romaji-tag position: {TextTagUtils.PositionFormattedString(romajiTag)}", () =>
{
var position = karaokeSpriteText.GetTextTagByPosition(romajiTag);
var position = karaokeSpriteText.GetRubyTagByPosition(rubyTag);
showPosition(position);
});
}
Expand Down
18 changes: 9 additions & 9 deletions osu.Game.Rulesets.Karaoke/KaraokeEditInputManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,18 @@ public enum KaraokeEditAction
[Description("Next edit mode")]
NextEditMode,

// Edit Ruby / romaji tag.
[Description("Reduce start index")]
EditTextTagReduceStartIndex,
// Edit Ruby tag.
[Description("Reduce ruby-tag start index")]
EditRubyTagReduceStartIndex,

[Description("Increase start index")]
EditTextTagIncreaseStartIndex,
[Description("Increase ruby-tag start index")]
EditRubyTagIncreaseStartIndex,

[Description("Reduce end index")]
EditTextTagReduceEndIndex,
[Description("Reduce ruby-tag end index")]
EditRubyTagReduceEndIndex,

[Description("Increase end index")]
EditTextTagIncreaseEndIndex,
[Description("Increase ruby-tag end index")]
EditRubyTagIncreaseEndIndex,

// Edit time-tag.
[Description("Create start time-tag")]
Expand Down
8 changes: 4 additions & 4 deletions osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) =
new KeyBinding(new[] { InputKey.Alt, InputKey.BracketRight }, KaraokeEditAction.NextEditMode),

// Edit Ruby / romaji tag.
new KeyBinding(new[] { InputKey.Z, InputKey.Left }, KaraokeEditAction.EditTextTagReduceStartIndex),
new KeyBinding(new[] { InputKey.Z, InputKey.Right }, KaraokeEditAction.EditTextTagIncreaseStartIndex),
new KeyBinding(new[] { InputKey.X, InputKey.Left }, KaraokeEditAction.EditTextTagReduceEndIndex),
new KeyBinding(new[] { InputKey.X, InputKey.Right }, KaraokeEditAction.EditTextTagIncreaseEndIndex),
new KeyBinding(new[] { InputKey.Z, InputKey.Left }, KaraokeEditAction.EditRubyTagReduceStartIndex),
new KeyBinding(new[] { InputKey.Z, InputKey.Right }, KaraokeEditAction.EditRubyTagIncreaseStartIndex),
new KeyBinding(new[] { InputKey.X, InputKey.Left }, KaraokeEditAction.EditRubyTagReduceEndIndex),
new KeyBinding(new[] { InputKey.X, InputKey.Right }, KaraokeEditAction.EditRubyTagIncreaseEndIndex),

// edit time-tag.
new KeyBinding(InputKey.Q, KaraokeEditAction.CreateStartTimeTag),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ protected void InitializeBlueprint()
{
LyricEditorMode.EditRuby => rubyTagEditMode == RubyTagEditMode.Create ? null : new RubyBlueprintContainer(lyric),
LyricEditorMode.EditTimeTag => modeWithEditStep.EditStep is TimeTagEditStep.Adjust ? new TimeTagBlueprintContainer(lyric) : null,
LyricEditorMode.EditRomaji => new RomajiBlueprintContainer(lyric),
_ => null,
};
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
// 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.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Logging;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Rulesets.Karaoke.Objects.Utils;
using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States.Modes;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;

namespace osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.Components.Lyrics.Blueprints;

public partial class RubyBlueprintContainer : TextTagBlueprintContainer<RubyTag>
public partial class RubyBlueprintContainer : LyricPropertyBlueprintContainer<RubyTag>
{
public RubyBlueprintContainer(Lyric lyric)
: base(lyric)
Expand All @@ -28,18 +34,127 @@ protected override SelectionHandler<RubyTag> CreateSelectionHandler()
protected override SelectionBlueprint<RubyTag> CreateBlueprintFor(RubyTag item)
=> new RubyTagSelectionBlueprint(item);

protected partial class RubyTagSelectionHandler : TextTagSelectionHandler<IEditRubyModeState>
protected partial class RubyTagSelectionHandler : LyricPropertySelectionHandler<IEditRubyModeState>
{
[Resolved]
private ILyricRubyTagsChangeHandler rubyTagsChangeHandler { get; set; } = null!;

protected override void DeleteItems(IEnumerable<RubyTag> items)
=> rubyTagsChangeHandler.RemoveRange(items);
[Resolved]
private IPreviewLyricPositionProvider previewLyricPositionProvider { get; set; } = null!;

private float deltaScaleSize;

protected override void OnSelectionChanged()
{
base.OnSelectionChanged();

// only select one ruby / romaji tag can let user drag to change start and end index.
SelectionBox.CanScaleX = SelectedItems.Count == 1;

// should clear delta size before change start/end index.
deltaScaleSize = 0;
}

#region User Input Handling

// for now we always allow movement. snapping is provided by the Timeline's "distance" snap implementation
public override bool HandleMovement(MoveSelectionEvent<RubyTag> moveEvent)
{
if (!SelectedItems.Any())
throw new InvalidOperationException("Should have at least one selected item.");

float deltaXPosition = moveEvent.ScreenSpaceDelta.X;
Logger.LogPrint($"position: {deltaXPosition}", LoggingTarget.Information);

if (deltaXPosition < 0)
{
var firstTimeTag = SelectedItems.MinBy(x => x.StartIndex) ?? throw new InvalidOperationException();
int? newStartIndex = calculateNewIndex(firstTimeTag, deltaXPosition, Anchor.CentreLeft);
int? offset = newStartIndex - firstTimeTag.StartIndex;
if (offset is null or 0)
return false;

setRubyTagShifting(SelectedItems, -1);
}
else
{
var lastTimeTag = SelectedItems.MaxBy(x => x.EndIndex) ?? throw new InvalidOperationException();
int? newEndIndex = calculateNewIndex(lastTimeTag, deltaXPosition, Anchor.CentreRight);
int? offset = newEndIndex - lastTimeTag.EndIndex;
if (offset is null or 0)
return false;

setRubyTagShifting(SelectedItems, 1);
}

return true;

void setRubyTagShifting(IEnumerable<RubyTag> rubyTags, int offset)
=> rubyTagsChangeHandler.ShiftingIndex(rubyTags, offset);
}

protected override void SetTextTagShifting(IEnumerable<RubyTag> textTags, int offset)
=> rubyTagsChangeHandler.ShiftingIndex(textTags, offset);
public override bool HandleScale(Vector2 scale, Anchor anchor)
{
deltaScaleSize += scale.X;

protected override void SetTextTagIndex(RubyTag textTag, int? startPosition, int? endPosition)
=> rubyTagsChangeHandler.SetIndex(textTag, startPosition, endPosition);
// this feature only works if only select one ruby / romaji tag.
var selectedRubyTag = SelectedItems.FirstOrDefault();
if (selectedRubyTag == null)
return false;

switch (anchor)
{
case Anchor.CentreLeft:
int? newStartIndex = calculateNewIndex(selectedRubyTag, deltaScaleSize, anchor);
if (newStartIndex == null || !TextTagUtils.ValidNewStartIndex(selectedRubyTag, newStartIndex.Value))
return false;

setRubyTagIndex(selectedRubyTag, newStartIndex, null);
return true;

case Anchor.CentreRight:
int? newEndIndex = calculateNewIndex(selectedRubyTag, deltaScaleSize, anchor);
if (newEndIndex == null || !TextTagUtils.ValidNewEndIndex(selectedRubyTag, newEndIndex.Value))
return false;

setRubyTagIndex(selectedRubyTag, null, newEndIndex);
return true;

default:
return false;
}

void setRubyTagIndex(RubyTag rubyTag, int? startPosition, int? endPosition)
=> rubyTagsChangeHandler.SetIndex(rubyTag, startPosition, endPosition);
}

private int? calculateNewIndex(RubyTag rubyTag, float offset, Anchor anchor)
{
// get real left-side and right-side position
var rect = previewLyricPositionProvider.GetRubyTagByPosition(rubyTag);

// todo: need to think about how to handle the case if the text-tag already out of the range of the text.
if (rect == null)
throw new InvalidOperationException($"{nameof(rubyTag)} not in the range of the text.");

switch (anchor)
{
case Anchor.CentreLeft:
float leftPosition = rect.Value.Left + offset;
return previewLyricPositionProvider.GetCharIndexByPosition(leftPosition);

case Anchor.CentreRight:
float rightPosition = rect.Value.Right + offset;
return previewLyricPositionProvider.GetCharIndexByPosition(rightPosition);

default:
throw new ArgumentOutOfRangeException(nameof(anchor));
}
}

#endregion

protected override void DeleteItems(IEnumerable<RubyTag> items)
=> rubyTagsChangeHandler.RemoveRange(items);
}
}
Loading

0 comments on commit 16f4592

Please sign in to comment.