2024-01-26 09:49:23 +08:00
|
|
|
// 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 osu.Framework.Bindables;
|
2024-01-28 23:06:09 +08:00
|
|
|
using osu.Framework.Graphics.Containers;
|
|
|
|
using osu.Framework.Input.Events;
|
2024-01-26 09:49:23 +08:00
|
|
|
using osu.Framework.Threading;
|
2024-01-28 23:06:09 +08:00
|
|
|
using osuTK;
|
2024-01-26 09:49:23 +08:00
|
|
|
|
|
|
|
namespace osu.Game.Screens.Play.HUD
|
|
|
|
{
|
2024-01-28 23:06:09 +08:00
|
|
|
public abstract partial class SongProgressBar : Container
|
2024-01-26 09:49:23 +08:00
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation.
|
|
|
|
/// </summary>
|
|
|
|
public Action<double>? OnSeek { get; set; }
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Whether the progress bar should allow interaction, ie. to perform seek operations.
|
|
|
|
/// </summary>
|
|
|
|
public bool Interactive
|
|
|
|
{
|
|
|
|
get => InteractiveBindable.Value;
|
|
|
|
set => InteractiveBindable.Value = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected readonly BindableBool InteractiveBindable = new BindableBool();
|
|
|
|
|
2024-01-28 23:06:09 +08:00
|
|
|
public double StartTime { get; set; }
|
|
|
|
|
|
|
|
public double EndTime { get; set; } = 1.0;
|
|
|
|
|
|
|
|
public double CurrentTime { get; set; }
|
|
|
|
|
|
|
|
private double length => EndTime - StartTime;
|
|
|
|
|
|
|
|
protected double NormalizedValue => length == 0 ? 1 : Math.Clamp(CurrentTime - StartTime, 0.0, length) / length;
|
|
|
|
|
|
|
|
private bool handleClick;
|
|
|
|
|
|
|
|
protected override bool OnMouseDown(MouseDownEvent e)
|
2024-01-26 09:49:23 +08:00
|
|
|
{
|
2024-01-28 23:06:09 +08:00
|
|
|
handleClick = true;
|
|
|
|
return base.OnMouseDown(e);
|
2024-01-26 09:49:23 +08:00
|
|
|
}
|
|
|
|
|
2024-01-28 23:06:09 +08:00
|
|
|
protected override bool OnClick(ClickEvent e)
|
2024-01-26 09:49:23 +08:00
|
|
|
{
|
2024-01-28 23:06:09 +08:00
|
|
|
if (handleClick)
|
|
|
|
handleMouseInput(e);
|
|
|
|
|
|
|
|
return true;
|
2024-01-26 09:49:23 +08:00
|
|
|
}
|
|
|
|
|
2024-01-28 23:06:09 +08:00
|
|
|
protected override void OnDrag(DragEvent e)
|
2024-01-26 09:49:23 +08:00
|
|
|
{
|
2024-01-28 23:06:09 +08:00
|
|
|
handleMouseInput(e);
|
2024-01-26 09:49:23 +08:00
|
|
|
}
|
|
|
|
|
2024-01-28 23:06:09 +08:00
|
|
|
protected override bool OnDragStart(DragStartEvent e)
|
2024-01-26 09:49:23 +08:00
|
|
|
{
|
2024-01-28 23:06:09 +08:00
|
|
|
Vector2 posDiff = e.MouseDownPosition - e.MousePosition;
|
|
|
|
|
|
|
|
if (Math.Abs(posDiff.X) < Math.Abs(posDiff.Y))
|
|
|
|
{
|
|
|
|
handleClick = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
handleMouseInput(e);
|
|
|
|
return true;
|
2024-01-26 09:49:23 +08:00
|
|
|
}
|
|
|
|
|
2024-01-28 23:06:09 +08:00
|
|
|
private void handleMouseInput(UIEvent e)
|
2024-01-26 09:49:23 +08:00
|
|
|
{
|
2024-01-28 23:06:09 +08:00
|
|
|
if (!Interactive)
|
|
|
|
return;
|
|
|
|
|
|
|
|
double relativeX = Math.Clamp(ToLocalSpace(e.ScreenSpaceMousePosition).X / DrawWidth, 0, 1);
|
|
|
|
onUserChange(StartTime + (EndTime - StartTime) * relativeX);
|
2024-01-26 09:49:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private ScheduledDelegate? scheduledSeek;
|
|
|
|
|
2024-01-28 23:06:09 +08:00
|
|
|
private void onUserChange(double value)
|
2024-01-26 09:49:23 +08:00
|
|
|
{
|
|
|
|
scheduledSeek?.Cancel();
|
2024-01-28 23:06:09 +08:00
|
|
|
scheduledSeek = Schedule(() => OnSeek?.Invoke(value));
|
2024-01-26 09:49:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|