mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 09:42:54 +08:00
Merge branch 'master' into metronome-sound
This commit is contained in:
commit
c0001d7f00
2
.github/workflows/sentry-release.yml
vendored
2
.github/workflows/sentry-release.yml
vendored
@ -23,4 +23,4 @@ jobs:
|
||||
SENTRY_URL: https://sentry.ppy.sh/
|
||||
with:
|
||||
environment: production
|
||||
version: ${{ github.ref }}
|
||||
version: osu@${{ github.ref_name }}
|
||||
|
@ -77,6 +77,12 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
timingInfo.Text = $"offset: {selectedGroup.Value.Time:N2} bpm: {selectedGroup.Value.ControlPoints.OfType<TimingControlPoint>().First().BPM:N2}";
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoop()
|
||||
{
|
||||
AddStep("do nothing", () => { });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTapThenReset()
|
||||
{
|
||||
|
@ -2,13 +2,16 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Edit.Components;
|
||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Edit
|
||||
{
|
||||
@ -26,6 +29,14 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
Height = 60;
|
||||
|
||||
Masking = true;
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Colour = Color4.Black.Opacity(0.2f),
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Radius = 10f,
|
||||
};
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
|
@ -99,6 +99,15 @@ namespace osu.Game.Screens.Edit
|
||||
colourSelected = colours.Colour3;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
// Reduce flicker of rows when offset is being changed rapidly.
|
||||
// Probably need to reconsider this.
|
||||
FinishTransforms(true);
|
||||
}
|
||||
|
||||
private bool selected;
|
||||
|
||||
public bool Selected
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@ -18,6 +19,9 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
[Resolved]
|
||||
private EditorClock editorClock { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private EditorBeatmap beatmap { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private Bindable<ControlPointGroup> selectedGroup { get; set; }
|
||||
|
||||
@ -45,6 +49,7 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
{
|
||||
new Dimension(GridSizeMode.Absolute, 200),
|
||||
new Dimension(GridSizeMode.Absolute, 60),
|
||||
new Dimension(GridSizeMode.Absolute, 60),
|
||||
},
|
||||
Content = new[]
|
||||
{
|
||||
@ -77,7 +82,36 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(10),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TimingAdjustButton(1)
|
||||
{
|
||||
Text = "Offset",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 0.48f,
|
||||
Height = 50,
|
||||
Action = adjustOffset,
|
||||
},
|
||||
new TimingAdjustButton(0.1)
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Text = "BPM",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 0.48f,
|
||||
Height = 50,
|
||||
Action = adjustBpm,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
new Drawable[]
|
||||
{
|
||||
@ -113,6 +147,35 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
};
|
||||
}
|
||||
|
||||
private void adjustOffset(double adjust)
|
||||
{
|
||||
// VERY TEMPORARY
|
||||
var currentGroupItems = selectedGroup.Value.ControlPoints.ToArray();
|
||||
|
||||
beatmap.ControlPointInfo.RemoveGroup(selectedGroup.Value);
|
||||
|
||||
double newOffset = selectedGroup.Value.Time + adjust;
|
||||
|
||||
foreach (var cp in currentGroupItems)
|
||||
beatmap.ControlPointInfo.Add(newOffset, cp);
|
||||
|
||||
// the control point might not necessarily exist yet, if currentGroupItems was empty.
|
||||
selectedGroup.Value = beatmap.ControlPointInfo.GroupAt(newOffset, true);
|
||||
|
||||
if (!editorClock.IsRunning)
|
||||
editorClock.Seek(newOffset);
|
||||
}
|
||||
|
||||
private void adjustBpm(double adjust)
|
||||
{
|
||||
var timing = selectedGroup.Value.ControlPoints.OfType<TimingControlPoint>().FirstOrDefault();
|
||||
|
||||
if (timing == null)
|
||||
return;
|
||||
|
||||
timing.BeatLength = 60000 / (timing.BPM + adjust);
|
||||
}
|
||||
|
||||
private void tap()
|
||||
{
|
||||
editorClock.Seek(selectedGroup.Value.Time);
|
||||
|
254
osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs
Normal file
254
osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs
Normal file
@ -0,0 +1,254 @@
|
||||
// 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;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Timing
|
||||
{
|
||||
/// <summary>
|
||||
/// A button with variable constant output based on hold position and length.
|
||||
/// </summary>
|
||||
public class TimingAdjustButton : CompositeDrawable
|
||||
{
|
||||
public Action<double> Action;
|
||||
|
||||
private readonly double adjustAmount;
|
||||
private ScheduledDelegate adjustDelegate;
|
||||
|
||||
private const int max_multiplier = 10;
|
||||
|
||||
private const int adjust_levels = 4;
|
||||
|
||||
private const double initial_delay = 300;
|
||||
|
||||
private const double minimum_delay = 80;
|
||||
|
||||
public Container Content { get; set; }
|
||||
|
||||
private double adjustDelay = initial_delay;
|
||||
|
||||
private readonly Box background;
|
||||
|
||||
private readonly OsuSpriteText text;
|
||||
|
||||
private Sample sample;
|
||||
|
||||
public LocalisableString Text
|
||||
{
|
||||
get => text.Text;
|
||||
set => text.Text = value;
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private OverlayColourProvider colourProvider { get; set; }
|
||||
|
||||
public TimingAdjustButton(double adjustAmount)
|
||||
{
|
||||
this.adjustAmount = adjustAmount;
|
||||
|
||||
CornerRadius = 5;
|
||||
Masking = true;
|
||||
|
||||
AddInternal(Content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = float.MaxValue
|
||||
},
|
||||
text = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.Default.With(weight: FontWeight.SemiBold),
|
||||
Padding = new MarginPadding(5),
|
||||
Depth = float.MinValue
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sample = audio.Samples.Get(@"UI/notch-tick");
|
||||
|
||||
background.Colour = colourProvider.Background3;
|
||||
|
||||
for (int i = 1; i <= adjust_levels; i++)
|
||||
{
|
||||
Content.Add(new IncrementBox(i, adjustAmount));
|
||||
Content.Add(new IncrementBox(-i, adjustAmount));
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
beginRepeat();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
adjustDelegate?.Cancel();
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
private void beginRepeat()
|
||||
{
|
||||
adjustDelegate?.Cancel();
|
||||
|
||||
adjustDelay = initial_delay;
|
||||
adjustNext();
|
||||
|
||||
void adjustNext()
|
||||
{
|
||||
var hoveredBox = Content.OfType<IncrementBox>().FirstOrDefault(d => d.IsHovered);
|
||||
|
||||
if (hoveredBox != null)
|
||||
{
|
||||
Action(adjustAmount * hoveredBox.Multiplier);
|
||||
|
||||
adjustDelay = Math.Max(minimum_delay, adjustDelay * 0.9f);
|
||||
|
||||
hoveredBox.Flash();
|
||||
|
||||
var channel = sample?.GetChannel();
|
||||
|
||||
if (channel != null)
|
||||
{
|
||||
double repeatModifier = 0.05f * (Math.Abs(adjustDelay - initial_delay) / minimum_delay);
|
||||
double multiplierModifier = (hoveredBox.Multiplier / max_multiplier) * 0.2f;
|
||||
|
||||
channel.Frequency.Value = 1 + multiplierModifier + repeatModifier;
|
||||
channel.Play();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
adjustDelay = initial_delay;
|
||||
}
|
||||
|
||||
adjustDelegate = Scheduler.AddDelayed(adjustNext, adjustDelay);
|
||||
}
|
||||
}
|
||||
|
||||
private class IncrementBox : CompositeDrawable
|
||||
{
|
||||
public readonly float Multiplier;
|
||||
|
||||
private readonly Box box;
|
||||
private readonly OsuSpriteText text;
|
||||
|
||||
public IncrementBox(int index, double amount)
|
||||
{
|
||||
Multiplier = Math.Sign(index) * convertMultiplier(index);
|
||||
|
||||
float ratio = (float)index / adjust_levels;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Width = 0.5f * Math.Abs(ratio);
|
||||
|
||||
Anchor direction = index < 0 ? Anchor.x2 : Anchor.x0;
|
||||
|
||||
Origin |= direction;
|
||||
|
||||
Depth = Math.Abs(index);
|
||||
|
||||
Anchor = Anchor.TopCentre;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
box = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingParameters.Additive
|
||||
},
|
||||
text = new OsuSpriteText
|
||||
{
|
||||
Anchor = direction,
|
||||
Origin = direction,
|
||||
Font = OsuFont.Default.With(size: 10, weight: FontWeight.Bold),
|
||||
Text = $"{(index > 0 ? "+" : "-")}{Math.Abs(Multiplier * amount)}",
|
||||
Padding = new MarginPadding(5),
|
||||
Alpha = 0,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private OverlayColourProvider colourProvider { get; set; }
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
box.Colour = colourProvider.Background1;
|
||||
box.Alpha = 0.1f;
|
||||
}
|
||||
|
||||
private float convertMultiplier(int m)
|
||||
{
|
||||
switch (Math.Abs(m))
|
||||
{
|
||||
default: return 1;
|
||||
|
||||
case 2: return 2;
|
||||
|
||||
case 3: return 5;
|
||||
|
||||
case 4:
|
||||
return max_multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
box.Colour = colourProvider.Colour0;
|
||||
|
||||
box.FadeTo(0.2f, 100, Easing.OutQuint);
|
||||
text.FadeIn(100, Easing.OutQuint);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
box.Colour = colourProvider.Background1;
|
||||
|
||||
box.FadeTo(0.1f, 500, Easing.OutQuint);
|
||||
text.FadeOut(100, Easing.OutQuint);
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
public void Flash()
|
||||
{
|
||||
box
|
||||
.FadeTo(0.4f, 20, Easing.OutQuint)
|
||||
.Then()
|
||||
.FadeTo(0.2f, 400, Easing.OutQuint);
|
||||
|
||||
text
|
||||
.MoveToY(-5, 20, Easing.OutQuint)
|
||||
.Then()
|
||||
.MoveToY(0, 400, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -144,7 +144,27 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
|
||||
private void addNew()
|
||||
{
|
||||
selectedGroup.Value = Beatmap.ControlPointInfo.GroupAt(clock.CurrentTime, true);
|
||||
bool isFirstControlPoint = !Beatmap.ControlPointInfo.TimingPoints.Any();
|
||||
|
||||
var group = Beatmap.ControlPointInfo.GroupAt(clock.CurrentTime, true);
|
||||
|
||||
if (isFirstControlPoint)
|
||||
group.Add(new TimingControlPoint());
|
||||
else
|
||||
{
|
||||
// Try and create matching types from the currently selected control point.
|
||||
var selected = selectedGroup.Value;
|
||||
|
||||
if (selected != null)
|
||||
{
|
||||
foreach (var controlPoint in selected.ControlPoints)
|
||||
{
|
||||
group.Add(controlPoint.DeepClone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selectedGroup.Value = group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Overlays;
|
||||
@ -26,6 +27,8 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
{
|
||||
private const int total_waveforms = 8;
|
||||
|
||||
private const float corner_radius = LabelledDrawable<Drawable>.CORNER_RADIUS;
|
||||
|
||||
private readonly BindableNumber<double> beatLength = new BindableDouble();
|
||||
|
||||
[Resolved]
|
||||
@ -42,18 +45,22 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
|
||||
private TimingControlPoint timingPoint = TimingControlPoint.DEFAULT;
|
||||
|
||||
private int lastDisplayedBeatIndex;
|
||||
private double displayedTime;
|
||||
|
||||
private double selectedGroupStartTime;
|
||||
private double selectedGroupEndTime;
|
||||
|
||||
private readonly IBindableList<ControlPointGroup> controlPointGroups = new BindableList<ControlPointGroup>();
|
||||
|
||||
private readonly BindableBool displayLocked = new BindableBool();
|
||||
|
||||
private LockedOverlay lockedOverlay = null!;
|
||||
|
||||
public WaveformComparisonDisplay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
CornerRadius = LabelledDrawable<Drawable>.CORNER_RADIUS;
|
||||
CornerRadius = corner_radius;
|
||||
Masking = true;
|
||||
}
|
||||
|
||||
@ -81,72 +88,112 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
Width = 3,
|
||||
});
|
||||
|
||||
AddInternal(lockedOverlay = new LockedOverlay());
|
||||
|
||||
selectedGroup.BindValueChanged(_ => updateTimingGroup(), true);
|
||||
|
||||
controlPointGroups.BindTo(editorBeatmap.ControlPointInfo.Groups);
|
||||
controlPointGroups.BindCollectionChanged((_, __) => updateTimingGroup());
|
||||
|
||||
beatLength.BindValueChanged(_ => showFrom(lastDisplayedBeatIndex), true);
|
||||
beatLength.BindValueChanged(_ => regenerateDisplay(true), true);
|
||||
|
||||
displayLocked.BindValueChanged(locked =>
|
||||
{
|
||||
if (locked.NewValue)
|
||||
lockedOverlay.Show();
|
||||
else
|
||||
lockedOverlay.Hide();
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void updateTimingGroup()
|
||||
{
|
||||
beatLength.UnbindBindings();
|
||||
|
||||
selectedGroupStartTime = 0;
|
||||
selectedGroupEndTime = beatmap.Value.Track.Length;
|
||||
|
||||
var tcp = selectedGroup.Value?.ControlPoints.OfType<TimingControlPoint>().FirstOrDefault();
|
||||
|
||||
if (tcp == null)
|
||||
{
|
||||
timingPoint = new TimingControlPoint();
|
||||
// During movement of a control point's offset, this clause can be hit momentarily,
|
||||
// as moving a control point is implemented by removing it and inserting it at the new time.
|
||||
// We don't want to reset the `selectedGroupStartTime` here as we rely on having the
|
||||
// last value to update the waveform display below.
|
||||
selectedGroupEndTime = beatmap.Value.Track.Length;
|
||||
return;
|
||||
}
|
||||
|
||||
timingPoint = tcp;
|
||||
beatLength.BindTo(timingPoint.BeatLengthBindable);
|
||||
|
||||
selectedGroupStartTime = selectedGroup.Value?.Time ?? 0;
|
||||
double? newStartTime = selectedGroup.Value?.Time;
|
||||
double? offsetChange = newStartTime - selectedGroupStartTime;
|
||||
|
||||
var nextGroup = editorBeatmap.ControlPointInfo.TimingPoints
|
||||
.SkipWhile(g => g != tcp)
|
||||
.Skip(1)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (nextGroup != null)
|
||||
selectedGroupEndTime = nextGroup.Time;
|
||||
selectedGroupStartTime = newStartTime ?? 0;
|
||||
selectedGroupEndTime = nextGroup?.Time ?? beatmap.Value.Track.Length;
|
||||
|
||||
if (newStartTime.HasValue && offsetChange.HasValue)
|
||||
{
|
||||
// The offset of the selected point may have changed.
|
||||
// This handles the case the user has locked the view and expects the display to update with this change.
|
||||
showFromTime(displayedTime + offsetChange.Value, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e) => true;
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
float trackLength = (float)beatmap.Value.Track.Length;
|
||||
int totalBeatsAvailable = (int)(trackLength / timingPoint.BeatLength);
|
||||
if (!displayLocked.Value)
|
||||
{
|
||||
float trackLength = (float)beatmap.Value.Track.Length;
|
||||
int totalBeatsAvailable = (int)(trackLength / timingPoint.BeatLength);
|
||||
|
||||
Scheduler.AddOnce(showFrom, (int)(e.MousePosition.X / DrawWidth * totalBeatsAvailable));
|
||||
Scheduler.AddOnce(showFromBeat, (int)(e.MousePosition.X / DrawWidth * totalBeatsAvailable));
|
||||
}
|
||||
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
displayLocked.Toggle();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!IsHovered)
|
||||
if (!IsHovered && !displayLocked.Value)
|
||||
{
|
||||
int currentBeat = (int)Math.Floor((editorClock.CurrentTimeAccurate - selectedGroupStartTime) / timingPoint.BeatLength);
|
||||
|
||||
showFrom(currentBeat);
|
||||
showFromBeat(currentBeat);
|
||||
}
|
||||
}
|
||||
|
||||
private void showFrom(int beatIndex)
|
||||
private void showFromBeat(int beatIndex) =>
|
||||
showFromTime(selectedGroupStartTime + beatIndex * timingPoint.BeatLength, false);
|
||||
|
||||
private void showFromTime(double time, bool animated)
|
||||
{
|
||||
if (lastDisplayedBeatIndex == beatIndex)
|
||||
if (displayedTime == time)
|
||||
return;
|
||||
|
||||
displayedTime = time;
|
||||
regenerateDisplay(animated);
|
||||
}
|
||||
|
||||
private void regenerateDisplay(bool animated)
|
||||
{
|
||||
double index = (displayedTime - selectedGroupStartTime) / timingPoint.BeatLength;
|
||||
|
||||
// Chosen as a pretty usable number across all BPMs.
|
||||
// Optimally we'd want this to scale with the BPM in question, but performing
|
||||
// scaling of the display is both expensive in resampling, and decreases usability
|
||||
@ -156,23 +203,88 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
float trackLength = (float)beatmap.Value.Track.Length;
|
||||
float scale = trackLength / visible_width;
|
||||
|
||||
const int start_offset = total_waveforms / 2;
|
||||
|
||||
// Start displaying from before the current beat
|
||||
beatIndex -= total_waveforms / 2;
|
||||
index -= start_offset;
|
||||
|
||||
foreach (var row in InternalChildren.OfType<WaveformRow>())
|
||||
{
|
||||
// offset to the required beat index.
|
||||
double time = selectedGroupStartTime + beatIndex * timingPoint.BeatLength;
|
||||
double time = selectedGroupStartTime + index * timingPoint.BeatLength;
|
||||
|
||||
float offset = (float)(time - visible_width / 2) / trackLength * scale;
|
||||
|
||||
row.Alpha = time < selectedGroupStartTime || time > selectedGroupEndTime ? 0.2f : 1;
|
||||
row.WaveformOffset = -offset;
|
||||
row.WaveformOffsetTo(-offset, animated);
|
||||
row.WaveformScale = new Vector2(scale, 1);
|
||||
row.BeatIndex = beatIndex++;
|
||||
row.BeatIndex = (int)Math.Floor(index);
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
internal class LockedOverlay : CompositeDrawable
|
||||
{
|
||||
private OsuSpriteText text = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
CornerRadius = corner_radius;
|
||||
BorderColour = colours.Red;
|
||||
BorderThickness = 3;
|
||||
Alpha = 0;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colours.Red,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
text = new OsuSpriteText
|
||||
{
|
||||
Colour = colours.GrayF,
|
||||
Text = "Locked",
|
||||
Margin = new MarginPadding(5),
|
||||
Shadow = false,
|
||||
Font = OsuFont.Default.With(size: 12, weight: FontWeight.SemiBold),
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
lastDisplayedBeatIndex = beatIndex;
|
||||
public override void Show()
|
||||
{
|
||||
this.FadeIn(100, Easing.OutQuint);
|
||||
|
||||
text
|
||||
.FadeIn().Then().Delay(600)
|
||||
.FadeOut().Then().Delay(600)
|
||||
.Loop();
|
||||
}
|
||||
|
||||
public override void Hide()
|
||||
{
|
||||
this.FadeOut(100, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
internal class WaveformRow : CompositeDrawable
|
||||
@ -224,7 +336,15 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
|
||||
public int BeatIndex { set => beatIndexText.Text = value.ToString(); }
|
||||
public Vector2 WaveformScale { set => waveformGraph.Scale = value; }
|
||||
public float WaveformOffset { set => waveformGraph.X = value; }
|
||||
|
||||
public void WaveformOffsetTo(float value, bool animated) =>
|
||||
this.TransformTo(nameof(waveformOffset), value, animated ? 300 : 0, Easing.OutQuint);
|
||||
|
||||
private float waveformOffset
|
||||
{
|
||||
get => waveformGraph.X;
|
||||
set => waveformGraph.X = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,9 +48,8 @@ namespace osu.Game.Utils
|
||||
|
||||
options.AutoSessionTracking = true;
|
||||
options.IsEnvironmentUser = false;
|
||||
// The reported release needs to match release tags on github in order for sentry
|
||||
// to automatically associate and track against releases.
|
||||
options.Release = game.Version.Replace($@"-{OsuGameBase.BUILD_SUFFIX}", string.Empty);
|
||||
// The reported release needs to match version as reported to Sentry in .github/workflows/sentry-release.yml
|
||||
options.Release = $"osu@{game.Version.Replace($@"-{OsuGameBase.BUILD_SUFFIX}", string.Empty)}";
|
||||
});
|
||||
|
||||
Logger.NewEntry += processLogEntry;
|
||||
|
Loading…
Reference in New Issue
Block a user