1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 09:32:55 +08:00

Move value change logic to bindable

Also add drag support
This commit is contained in:
Dean Herbert 2018-03-20 20:09:55 +09:00
parent 786e6242e1
commit 6fd650777c
3 changed files with 106 additions and 52 deletions

View File

@ -1,6 +1,8 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Screens.Edit.Screens.Compose;
@ -10,6 +12,8 @@ namespace osu.Game.Tests.Visual
{
public class TestCaseDrawableBeatDivisor : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(BindableBeatDivisor) };
[BackgroundDependencyLoader]
private void load()
{

View File

@ -1,15 +1,55 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Linq;
using osu.Framework.Configuration;
namespace osu.Game.Screens.Edit.Screens.Compose
{
public class BindableBeatDivisor : Bindable<int>
public class BindableBeatDivisor : BindableNumber<int>
{
public static readonly int[] VALID_DIVISORS = { 1, 2, 3, 4, 6, 8, 12, 16 };
public BindableBeatDivisor(int value = 1)
: base(value)
{
}
public void Next() => Value = VALID_DIVISORS[Math.Min(VALID_DIVISORS.Length - 1, Array.IndexOf(VALID_DIVISORS, Value) + 1)];
public void Previous() => Value = VALID_DIVISORS[Math.Max(0, Array.IndexOf(VALID_DIVISORS, Value) - 1)];
public override int Value
{
get { return base.Value; }
set
{
int snapped = 1;
for (int i = 1; i < VALID_DIVISORS.Length; i++)
{
var curr = VALID_DIVISORS[i];
var prev = VALID_DIVISORS[i - 1];
if (value < prev + (curr - prev) / 2f)
{
snapped = prev;
break;
}
snapped = curr;
}
if (snapped == Value)
// it may be that we are already at the snapped value, but we want bound components to still be made aware that we possibly modified an incoming ValueChanged.
TriggerValueChange();
else
base.Value = snapped;
}
}
protected override int DefaultMinValue => VALID_DIVISORS.First();
protected override int DefaultMaxValue => VALID_DIVISORS.Last();
protected override int DefaultPrecision => 1;
}
}

View File

@ -1,13 +1,14 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using OpenTK;
@ -17,10 +18,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose
{
public class DrawableBeatDivisor : CompositeDrawable
{
private static readonly int[] available_divisors = { 1, 2, 3, 4, 6, 8, 12, 16 };
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor();
private int currentDivisorIndex;
private TickSliderBar slider;
public DrawableBeatDivisor(BindableBeatDivisor beatDivisor)
{
@ -48,7 +48,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose
{
new Drawable[]
{
new TickContainer(beatDivisor, 1, 2, 3, 4, 6, 8, 12, 16)
slider = new TickSliderBar(beatDivisor, 1, 2, 3, 4, 6, 8, 12, 16)
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Horizontal = 5 }
@ -80,13 +80,13 @@ namespace osu.Game.Screens.Edit.Screens.Compose
new DivisorButton
{
Icon = FontAwesome.fa_chevron_left,
Action = selectPrevious
Action = beatDivisor.Previous
},
new DivisorText(beatDivisor),
new DivisorButton
{
Icon = FontAwesome.fa_chevron_right,
Action = selectNext
Action = beatDivisor.Next
}
},
new Drawable[]
@ -118,20 +118,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose
}
}
};
}
private void selectPrevious()
{
if (currentDivisorIndex == 0)
return;
beatDivisor.Value = available_divisors[--currentDivisorIndex];
}
private void selectNext()
{
if (currentDivisorIndex == available_divisors.Length - 1)
return;
beatDivisor.Value = available_divisors[++currentDivisorIndex];
slider.Current.BindTo(beatDivisor);
}
private class DivisorText : SpriteText
@ -186,61 +174,46 @@ namespace osu.Game.Screens.Edit.Screens.Compose
}
}
private class TickContainer : CompositeDrawable
private class TickSliderBar : SliderBar<int>
{
private readonly Bindable<int> beatDivisor = new Bindable<int>();
public new MarginPadding Padding
{
set => base.Padding = value;
}
public new MarginPadding Padding { set => base.Padding = value; }
private EquilateralTriangle marker;
private Drawable marker;
private readonly int[] availableDivisors;
private readonly float tickSpacing;
public TickContainer(BindableBeatDivisor beatDivisor, params int[] divisors)
public TickSliderBar(params int[] divisors)
{
this.beatDivisor.BindTo(beatDivisor);
availableDivisors = divisors;
tickSpacing = 1f / (availableDivisors.Length + 1);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
private void load()
{
InternalChild = marker = new EquilateralTriangle
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomCentre,
RelativePositionAxes = Axes.X,
Height = 7,
EdgeSmoothness = new Vector2(1),
Colour = colours.Gray4,
};
InternalChild = marker = new Marker();
for (int i = 0; i < availableDivisors.Length; i++)
foreach (var t in availableDivisors)
{
AddInternal(new Tick(availableDivisors[i])
AddInternal(new Tick(t)
{
Anchor = Anchor.TopLeft,
Origin = Anchor.TopCentre,
RelativePositionAxes = Axes.X,
X = getTickPosition(i)
X = getTickPosition(t)
});
}
CurrentNumber.ValueChanged += v => marker.MoveToX(getTickPosition(v), 100, Easing.OutQuint);
}
protected override void LoadComplete()
protected override void UpdateValue(float value)
{
base.LoadComplete();
beatDivisor.ValueChanged += v => updatePosition();
updatePosition();
}
private void updatePosition() => marker.MoveToX(getTickPosition(Array.IndexOf(availableDivisors, beatDivisor.Value)), 100, Easing.OutQuint);
private float getTickPosition(int index) => (index + 1) * tickSpacing;
private float getTickPosition(float divisor) => (divisor - 1) / availableDivisors.Last();
private class Tick : Box
{
@ -249,7 +222,6 @@ namespace osu.Game.Screens.Edit.Screens.Compose
public Tick(int divisor)
{
this.divisor = divisor;
Size = new Vector2(2, 10);
}
@ -264,6 +236,44 @@ namespace osu.Game.Screens.Edit.Screens.Compose
Colour = colours.Gray4;
}
}
private class Marker : CompositeDrawable
{
private const float size = 7;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Colour = colours.Gray4;
Anchor = Anchor.TopLeft;
Origin = Anchor.TopCentre;
Width = size;
RelativeSizeAxes = Axes.Y;
RelativePositionAxes = Axes.X;
InternalChildren = new Drawable[]
{
new Box
{
Width = 1,
RelativeSizeAxes = Axes.Y,
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
Colour = Color4.White,
},
new EquilateralTriangle
{
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
Height = size,
EdgeSmoothness = new Vector2(1),
Colour = Color4.White,
}
};
}
}
}
}
}