2020-01-27 15:00:51 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2019-01-24 16:43:03 +08:00
// See the LICENCE file in the repository root for full licence text.
2018-04-13 17:19:50 +08:00
2022-06-17 15:37:17 +08:00
#nullable disable
2018-03-20 19:09:55 +08:00
using System.Linq ;
2019-02-21 18:04:31 +08:00
using osu.Framework.Bindables ;
2019-08-30 16:34:02 +08:00
using osu.Game.Graphics ;
2022-02-13 22:50:40 +08:00
using osu.Game.Screens.Edit.Compose.Components ;
2022-05-24 16:02:19 +08:00
using osuTK ;
2019-08-30 16:34:02 +08:00
using osuTK.Graphics ;
2018-04-13 17:19:50 +08:00
2018-11-06 17:28:22 +08:00
namespace osu.Game.Screens.Edit
2018-03-19 19:30:07 +08:00
{
2019-10-23 13:04:06 +08:00
public class BindableBeatDivisor : BindableInt
2018-03-19 19:30:07 +08:00
{
2022-02-13 22:50:40 +08:00
public static readonly int [ ] PREDEFINED_DIVISORS = { 1 , 2 , 3 , 4 , 6 , 8 , 12 , 16 } ;
public Bindable < BeatDivisorPresetCollection > ValidDivisors { get ; } = new Bindable < BeatDivisorPresetCollection > ( BeatDivisorPresetCollection . COMMON ) ;
2018-04-13 17:19:50 +08:00
2018-03-19 19:42:06 +08:00
public BindableBeatDivisor ( int value = 1 )
: base ( value )
2018-03-19 19:30:07 +08:00
{
2022-02-13 22:50:40 +08:00
ValidDivisors . BindValueChanged ( _ = > updateBindableProperties ( ) , true ) ;
BindValueChanged ( _ = > ensureValidDivisor ( ) ) ;
2018-03-19 19:30:07 +08:00
}
2018-04-13 17:19:50 +08:00
2022-10-24 14:20:15 +08:00
/// <summary>
/// Set a divisor, updating the valid divisor range appropriately.
/// </summary>
/// <param name="divisor">The intended divisor.</param>
2024-01-25 18:12:54 +08:00
/// <param name="preferKnownPresets">Forces changing the valid divisors to a known preset.</param>
public void SetArbitraryDivisor ( int divisor , bool preferKnownPresets = false )
2022-10-24 14:20:15 +08:00
{
// If the current valid divisor range doesn't contain the proposed value, attempt to find one which does.
2024-01-25 18:12:54 +08:00
if ( preferKnownPresets | | ! ValidDivisors . Value . Presets . Contains ( divisor ) )
2022-10-24 14:20:15 +08:00
{
if ( BeatDivisorPresetCollection . COMMON . Presets . Contains ( divisor ) )
ValidDivisors . Value = BeatDivisorPresetCollection . COMMON ;
else if ( BeatDivisorPresetCollection . TRIPLETS . Presets . Contains ( divisor ) )
ValidDivisors . Value = BeatDivisorPresetCollection . TRIPLETS ;
else
ValidDivisors . Value = BeatDivisorPresetCollection . Custom ( divisor ) ;
}
Value = divisor ;
}
2022-02-13 22:50:40 +08:00
private void updateBindableProperties ( )
{
ensureValidDivisor ( ) ;
2018-04-13 17:19:50 +08:00
2022-02-13 22:50:40 +08:00
MinValue = ValidDivisors . Value . Presets . Min ( ) ;
MaxValue = ValidDivisors . Value . Presets . Max ( ) ;
}
2018-04-13 17:19:50 +08:00
2022-02-13 22:50:40 +08:00
private void ensureValidDivisor ( )
2018-03-20 19:09:55 +08:00
{
2022-02-13 22:50:40 +08:00
if ( ! ValidDivisors . Value . Presets . Contains ( Value ) )
Value = 1 ;
}
2018-04-13 17:19:50 +08:00
2023-06-07 23:53:58 +08:00
public void SelectNext ( )
2022-02-13 22:50:40 +08:00
{
var presets = ValidDivisors . Value . Presets ;
2023-06-07 23:53:58 +08:00
if ( presets . Cast < int? > ( ) . SkipWhile ( preset = > preset ! = Value ) . ElementAtOrDefault ( 1 ) is int newValue )
Value = newValue ;
2022-02-13 22:50:40 +08:00
}
2023-06-07 23:53:58 +08:00
public void SelectPrevious ( )
2022-02-13 22:50:40 +08:00
{
var presets = ValidDivisors . Value . Presets ;
2023-06-07 23:53:58 +08:00
if ( presets . Cast < int? > ( ) . TakeWhile ( preset = > preset ! = Value ) . LastOrDefault ( ) is int newValue )
Value = newValue ;
2018-03-20 19:09:55 +08:00
}
2018-04-13 17:19:50 +08:00
2018-03-20 19:09:55 +08:00
protected override int DefaultPrecision = > 1 ;
2019-08-30 16:34:02 +08:00
2022-02-13 22:50:40 +08:00
public override void BindTo ( Bindable < int > them )
{
2022-02-13 23:27:12 +08:00
// bind to valid divisors first (if applicable) to ensure correct transfer of the actual divisor.
2022-02-13 22:50:40 +08:00
if ( them is BindableBeatDivisor otherBeatDivisor )
ValidDivisors . BindTo ( otherBeatDivisor . ValidDivisors ) ;
2022-02-13 23:27:12 +08:00
base . BindTo ( them ) ;
2022-02-13 22:50:40 +08:00
}
2021-08-18 09:16:57 +08:00
protected override Bindable < int > CreateInstance ( ) = > new BindableBeatDivisor ( ) ;
2019-08-30 16:34:02 +08:00
/// <summary>
/// Retrieves the appropriate colour for a beat divisor.
/// </summary>
/// <param name="beatDivisor">The beat divisor.</param>
/// <param name="colours">The set of colours.</param>
/// <returns>The applicable colour from <paramref name="colours"/> for <paramref name="beatDivisor"/>.</returns>
2021-03-19 18:45:00 +08:00
public static Color4 GetColourFor ( int beatDivisor , OsuColour colours )
2019-08-30 16:34:02 +08:00
{
switch ( beatDivisor )
{
2020-01-27 14:57:55 +08:00
case 1 :
return Color4 . White ;
2019-08-30 16:34:02 +08:00
case 2 :
2020-01-27 14:57:55 +08:00
return colours . Red ;
2019-08-30 16:34:02 +08:00
case 4 :
return colours . Blue ;
case 8 :
2020-01-27 14:57:55 +08:00
return colours . Yellow ;
2019-08-30 16:34:02 +08:00
case 16 :
return colours . PurpleDark ;
case 3 :
2020-01-27 14:57:55 +08:00
return colours . Purple ;
2019-08-30 16:34:02 +08:00
case 6 :
2020-01-27 14:57:55 +08:00
return colours . YellowDark ;
2019-08-30 16:34:02 +08:00
case 12 :
return colours . YellowDarker ;
default :
2020-01-27 14:57:55 +08:00
return Color4 . Red ;
2019-08-30 16:34:02 +08:00
}
}
2020-01-27 15:00:51 +08:00
2022-05-24 16:02:19 +08:00
/// <summary>
/// Get a relative display size for the specified divisor.
/// </summary>
/// <param name="beatDivisor">The beat divisor.</param>
/// <returns>A relative size which can be used to display ticks.</returns>
public static Vector2 GetSize ( int beatDivisor )
{
switch ( beatDivisor )
{
case 1 :
case 2 :
return new Vector2 ( 0.6f , 0.9f ) ;
case 3 :
case 4 :
return new Vector2 ( 0.5f , 0.8f ) ;
case 6 :
case 8 :
return new Vector2 ( 0.4f , 0.7f ) ;
default :
return new Vector2 ( 0.3f , 0.6f ) ;
}
}
2020-01-27 15:00:51 +08:00
/// <summary>
/// Retrieves the applicable divisor for a specific beat index.
/// </summary>
/// <param name="index">The 0-based beat index.</param>
/// <param name="beatDivisor">The beat divisor.</param>
2023-05-25 04:17:51 +08:00
/// <param name="validDivisors">The list of valid divisors which can be chosen from. Assumes ordered from low to high. Defaults to <see cref="PREDEFINED_DIVISORS"/> if omitted.</param>
2020-01-27 15:00:51 +08:00
/// <returns>The applicable divisor.</returns>
2023-05-23 21:05:38 +08:00
public static int GetDivisorForBeatIndex ( int index , int beatDivisor , int [ ] validDivisors = null )
2020-01-27 15:00:51 +08:00
{
2023-05-23 21:05:38 +08:00
validDivisors ? ? = PREDEFINED_DIVISORS ;
2020-01-27 15:00:51 +08:00
int beat = index % beatDivisor ;
2023-05-23 21:05:38 +08:00
foreach ( int divisor in validDivisors )
2020-01-27 15:00:51 +08:00
{
if ( ( beat * divisor ) % beatDivisor = = 0 )
return divisor ;
}
return 0 ;
}
2018-03-19 19:30:07 +08:00
}
}