Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Logging;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics;
Expand Down Expand Up @@ -45,18 +46,9 @@ protected partial class RubyTagSelectionHandler : LyricPropertySelectionHandler<
[Resolved]
private IPreviewLyricPositionProvider previewLyricPositionProvider { get; set; } = null!;

private float deltaScaleSize;

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

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

// should clear delta size before change start/end index.
deltaScaleSize = 0;
}
// need to implement this because blueprint container support change the x scale.
public override SelectionScaleHandler CreateScaleHandler()
=> new RubyTagSelectionScaleHandler();

#region User Input Handling

Expand Down Expand Up @@ -96,41 +88,126 @@ void setRubyTagShifting(IEnumerable<RubyTag> rubyTags, int offset)
=> rubyTagsChangeHandler.ShiftingIndex(rubyTags, offset);
}

public override bool HandleScale(Vector2 scale, Anchor anchor)
private int? calculateNewIndex(RubyTag rubyTag, float offset, Anchor anchor)
{
deltaScaleSize += scale.X;
// get real left-side and right-side position
var rect = previewLyricPositionProvider.GetRubyTagByPosition(rubyTag);

// this feature only works if only select one ruby tag.
var selectedRubyTag = SelectedItems.FirstOrDefault();
if (selectedRubyTag == null)
return false;
// 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:
int? newStartIndex = calculateNewIndex(selectedRubyTag, deltaScaleSize, anchor);
if (newStartIndex == null || !RubyTagUtils.ValidNewStartIndex(selectedRubyTag, newStartIndex.Value))
return false;

setRubyTagIndex(selectedRubyTag, newStartIndex, null);
return true;
var leftPosition = rect.Value.BottomLeft + new Vector2(offset, 0);
return previewLyricPositionProvider.GetCharIndexByPosition(leftPosition);

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

setRubyTagIndex(selectedRubyTag, null, newEndIndex);
return true;
var rightPosition = rect.Value.BottomRight + new Vector2(offset, 0);
return previewLyricPositionProvider.GetCharIndexByPosition(rightPosition);

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

#endregion

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

private partial class RubyTagSelectionScaleHandler : SelectionScaleHandler
{
[Resolved]
private IPreviewLyricPositionProvider previewLyricPositionProvider { get; set; } = null!;

[Resolved]
private ILyricRubyTagsChangeHandler rubyTagsChangeHandler { get; set; } = null!;

private BindableList<RubyTag> selectedItems { get; } = new();

[BackgroundDependencyLoader]
private void load(IEditRubyModeState editRubyModeState)
{
selectedItems.BindTo(editRubyModeState.SelectedItems);
}

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

selectedItems.CollectionChanged += (_, __) => updateState();
updateState();
}

private void updateState()
{
// only select one ruby tag can let user drag to change start and end index.
CanScaleX.Value = selectedItems.Count == 1;
}

public override void Begin()
{
base.Begin();

var selectedItemsRect = selectedItems
.Select(x => previewLyricPositionProvider.GetRubyTagByPosition(x))
.Where(rect => rect != null)
.OfType<RectangleF>();

var rect = selectedItemsRect.Aggregate(new RectangleF(), RectangleF.Union);

// Update the quad
OriginalSurroundingQuad = Quad.FromRectangle(rect);
}

public override void Update(Vector2 scale, Vector2? origin = null, Axes adjustAxis = Axes.Both, float axisRotation = 0)
{
// this feature only works if only select one ruby tag.
var selectedRubyTag = selectedItems.FirstOrDefault();
if (selectedRubyTag == null)
return;

if (adjustAxis != Axes.X)
throw new InvalidOperationException("Only can adjust x axes");

if (origin == null || OriginalSurroundingQuad == null)
return;

float offset = OriginalSurroundingQuad.Value.Width * (scale.X - 1);

if (origin.Value.X > OriginalSurroundingQuad.Value.Centre.X)
{
int? newStartIndex = calculateNewIndex(selectedRubyTag, -offset, Anchor.CentreLeft);
if (newStartIndex == null || !RubyTagUtils.ValidNewStartIndex(selectedRubyTag, newStartIndex.Value))
return;

setRubyTagIndex(selectedRubyTag, newStartIndex, null);
}
else
{
int? newEndIndex = calculateNewIndex(selectedRubyTag, offset, Anchor.CentreRight);
if (newEndIndex == null || !RubyTagUtils.ValidNewEndIndex(selectedRubyTag, newEndIndex.Value))
return;

setRubyTagIndex(selectedRubyTag, null, newEndIndex);
}

return;

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

public override void Commit()
{
base.Commit();

OriginalSurroundingQuad = null;
}

private int? calculateNewIndex(RubyTag rubyTag, float offset, Anchor anchor)
{
// get real left-side and right-side position
Expand All @@ -154,10 +231,5 @@ void setRubyTagIndex(RubyTag rubyTag, int? startPosition, int? endPosition)
throw new ArgumentOutOfRangeException(nameof(anchor));
}
}

#endregion

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