Skip to content

Commit 7adb64f

Browse files
committed
Follow lazer to refactor the scale change.
see: https://github.com/ppy/osu/pull/26643/files
1 parent d1226a5 commit 7adb64f

File tree

1 file changed

+108
-36
lines changed

1 file changed

+108
-36
lines changed

osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Lyrics/Blueprints/RubyBlueprintContainer.cs

+108-36
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using osu.Framework.Allocation;
88
using osu.Framework.Bindables;
99
using osu.Framework.Graphics;
10+
using osu.Framework.Graphics.Primitives;
1011
using osu.Framework.Logging;
1112
using osu.Game.Rulesets.Edit;
1213
using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics;
@@ -45,18 +46,9 @@ protected partial class RubyTagSelectionHandler : LyricPropertySelectionHandler<
4546
[Resolved]
4647
private IPreviewLyricPositionProvider previewLyricPositionProvider { get; set; } = null!;
4748

48-
private float deltaScaleSize;
49-
50-
protected override void OnSelectionChanged()
51-
{
52-
base.OnSelectionChanged();
53-
54-
// only select one ruby tag can let user drag to change start and end index.
55-
ScaleHandler.CanScaleX.Value = SelectedItems.Count == 1;
56-
57-
// should clear delta size before change start/end index.
58-
deltaScaleSize = 0;
59-
}
49+
// need to implement this because blueprint container support change the x scale.
50+
public override SelectionScaleHandler CreateScaleHandler()
51+
=> new RubyTagSelectionScaleHandler();
6052

6153
#region User Input Handling
6254

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

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

103-
// this feature only works if only select one ruby tag.
104-
var selectedRubyTag = SelectedItems.FirstOrDefault();
105-
if (selectedRubyTag == null)
106-
return false;
96+
// todo: need to think about how to handle the case if the text-tag already out of the range of the text.
97+
if (rect == null)
98+
throw new InvalidOperationException($"{nameof(rubyTag)} not in the range of the text.");
10799

108100
switch (anchor)
109101
{
110102
case Anchor.CentreLeft:
111-
int? newStartIndex = calculateNewIndex(selectedRubyTag, deltaScaleSize, anchor);
112-
if (newStartIndex == null || !RubyTagUtils.ValidNewStartIndex(selectedRubyTag, newStartIndex.Value))
113-
return false;
114-
115-
setRubyTagIndex(selectedRubyTag, newStartIndex, null);
116-
return true;
103+
var leftPosition = rect.Value.BottomLeft + new Vector2(offset, 0);
104+
return previewLyricPositionProvider.GetCharIndexByPosition(leftPosition);
117105

118106
case Anchor.CentreRight:
119-
int? newEndIndex = calculateNewIndex(selectedRubyTag, deltaScaleSize, anchor);
120-
if (newEndIndex == null || !RubyTagUtils.ValidNewEndIndex(selectedRubyTag, newEndIndex.Value))
121-
return false;
122-
123-
setRubyTagIndex(selectedRubyTag, null, newEndIndex);
124-
return true;
107+
var rightPosition = rect.Value.BottomRight + new Vector2(offset, 0);
108+
return previewLyricPositionProvider.GetCharIndexByPosition(rightPosition);
125109

126110
default:
127-
return false;
111+
throw new ArgumentOutOfRangeException(nameof(anchor));
128112
}
113+
}
114+
115+
#endregion
116+
117+
protected override void DeleteItems(IEnumerable<RubyTag> items)
118+
=> rubyTagsChangeHandler.RemoveRange(items);
119+
}
120+
121+
private partial class RubyTagSelectionScaleHandler : SelectionScaleHandler
122+
{
123+
[Resolved]
124+
private IPreviewLyricPositionProvider previewLyricPositionProvider { get; set; } = null!;
125+
126+
[Resolved]
127+
private ILyricRubyTagsChangeHandler rubyTagsChangeHandler { get; set; } = null!;
128+
129+
private BindableList<RubyTag> selectedItems { get; } = new();
130+
131+
[BackgroundDependencyLoader]
132+
private void load(IEditRubyModeState editRubyModeState)
133+
{
134+
selectedItems.BindTo(editRubyModeState.SelectedItems);
135+
}
136+
137+
protected override void LoadComplete()
138+
{
139+
base.LoadComplete();
140+
141+
selectedItems.CollectionChanged += (_, __) => updateState();
142+
updateState();
143+
}
144+
145+
private void updateState()
146+
{
147+
// only select one ruby tag can let user drag to change start and end index.
148+
CanScaleX.Value = selectedItems.Count == 1;
149+
}
150+
151+
public override void Begin()
152+
{
153+
base.Begin();
154+
155+
var selectedItemsRect = selectedItems
156+
.Select(x => previewLyricPositionProvider.GetRubyTagByPosition(x))
157+
.Where(rect => rect != null)
158+
.OfType<RectangleF>();
159+
160+
var rect = selectedItemsRect.Aggregate(new RectangleF(), RectangleF.Union);
161+
162+
// Update the quad
163+
OriginalSurroundingQuad = Quad.FromRectangle(rect);
164+
}
165+
166+
public override void Update(Vector2 scale, Vector2? origin = null, Axes adjustAxis = Axes.Both, float axisRotation = 0)
167+
{
168+
// this feature only works if only select one ruby tag.
169+
var selectedRubyTag = selectedItems.FirstOrDefault();
170+
if (selectedRubyTag == null)
171+
return;
172+
173+
if (adjustAxis != Axes.X)
174+
throw new InvalidOperationException("Only can adjust x axes");
175+
176+
if (origin == null || OriginalSurroundingQuad == null)
177+
return;
178+
179+
float offset = OriginalSurroundingQuad.Value.Width * (scale.X - 1);
180+
181+
if (origin.Value.X > OriginalSurroundingQuad.Value.Centre.X)
182+
{
183+
int? newStartIndex = calculateNewIndex(selectedRubyTag, -offset, Anchor.CentreLeft);
184+
if (newStartIndex == null || !RubyTagUtils.ValidNewStartIndex(selectedRubyTag, newStartIndex.Value))
185+
return;
186+
187+
setRubyTagIndex(selectedRubyTag, newStartIndex, null);
188+
}
189+
else
190+
{
191+
int? newEndIndex = calculateNewIndex(selectedRubyTag, offset, Anchor.CentreRight);
192+
if (newEndIndex == null || !RubyTagUtils.ValidNewEndIndex(selectedRubyTag, newEndIndex.Value))
193+
return;
194+
195+
setRubyTagIndex(selectedRubyTag, null, newEndIndex);
196+
}
197+
198+
return;
129199

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

204+
public override void Commit()
205+
{
206+
base.Commit();
207+
208+
OriginalSurroundingQuad = null;
209+
}
210+
134211
private int? calculateNewIndex(RubyTag rubyTag, float offset, Anchor anchor)
135212
{
136213
// get real left-side and right-side position
@@ -154,10 +231,5 @@ void setRubyTagIndex(RubyTag rubyTag, int? startPosition, int? endPosition)
154231
throw new ArgumentOutOfRangeException(nameof(anchor));
155232
}
156233
}
157-
158-
#endregion
159-
160-
protected override void DeleteItems(IEnumerable<RubyTag> items)
161-
=> rubyTagsChangeHandler.RemoveRange(items);
162234
}
163235
}

0 commit comments

Comments
 (0)