1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-28 10:17:19 +08:00

Merge branch 'master' into fail-animation-update

This commit is contained in:
Dean Herbert 2021-10-15 23:32:10 +09:00 committed by GitHub
commit e9f50179ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 348 additions and 221 deletions

View File

@ -8,12 +8,14 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using osu.Game.Screens.Edit;
using osuTK; using osuTK;
using osuTK.Input; using osuTK.Input;
@ -67,6 +69,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
inputManager = GetContainingInputManager(); inputManager = GetContainingInputManager();
} }
[Resolved]
private EditorBeatmap editorBeatmap { get; set; }
public override void UpdateTimeAndPosition(SnapResult result) public override void UpdateTimeAndPosition(SnapResult result)
{ {
base.UpdateTimeAndPosition(result); base.UpdateTimeAndPosition(result);
@ -75,6 +80,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{ {
case SliderPlacementState.Initial: case SliderPlacementState.Initial:
BeginPlacement(); BeginPlacement();
var nearestDifficultyPoint = editorBeatmap.HitObjects.LastOrDefault(h => h.GetEndTime() < HitObject.StartTime)?.DifficultyControlPoint?.DeepClone() as DifficultyControlPoint;
HitObject.DifficultyControlPoint = nearestDifficultyPoint ?? new DifficultyControlPoint();
HitObject.Position = ToLocalSpace(result.ScreenSpacePosition); HitObject.Position = ToLocalSpace(result.ScreenSpacePosition);
break; break;

View File

@ -1,27 +1,106 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Edit.Timing;
namespace osu.Game.Screens.Edit.Compose.Components.Timeline namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{ {
public class DifficultyPointPiece : TopPointPiece public class DifficultyPointPiece : HitObjectPointPiece, IHasPopover
{ {
private readonly HitObject hitObject;
private readonly BindableNumber<double> speedMultiplier; private readonly BindableNumber<double> speedMultiplier;
public DifficultyPointPiece(DifficultyControlPoint point) public DifficultyPointPiece(HitObject hitObject)
: base(point) : base(hitObject.DifficultyControlPoint)
{ {
speedMultiplier = point.SliderVelocityBindable.GetBoundCopy(); this.hitObject = hitObject;
Y = Height; speedMultiplier = hitObject.DifficultyControlPoint.SliderVelocityBindable.GetBoundCopy();
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
speedMultiplier.BindValueChanged(multiplier => Label.Text = $"{multiplier.NewValue:n2}x", true); speedMultiplier.BindValueChanged(multiplier => Label.Text = $"{multiplier.NewValue:n2}x", true);
} }
protected override bool OnClick(ClickEvent e)
{
this.ShowPopover();
return true;
}
public Popover GetPopover() => new DifficultyEditPopover(hitObject);
public class DifficultyEditPopover : OsuPopover
{
private readonly HitObject hitObject;
private readonly DifficultyControlPoint point;
private SliderWithTextBoxInput<double> sliderVelocitySlider;
[Resolved(canBeNull: true)]
private EditorBeatmap beatmap { get; set; }
public DifficultyEditPopover(HitObject hitObject)
{
this.hitObject = hitObject;
point = hitObject.DifficultyControlPoint;
}
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
new FillFlowContainer
{
Width = 200,
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
sliderVelocitySlider = new SliderWithTextBoxInput<double>("Velocity")
{
Current = new DifficultyControlPoint().SliderVelocityBindable,
KeyboardStep = 0.1f
},
new OsuTextFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Text = "Hold shift while dragging the end of an object to adjust velocity while snapping."
}
}
}
};
var selectedPointBindable = point.SliderVelocityBindable;
// there may be legacy control points, which contain infinite precision for compatibility reasons (see LegacyDifficultyControlPoint).
// generally that level of precision could only be set by externally editing the .osu file, so at the point
// a user is looking to update this within the editor it should be safe to obliterate this additional precision.
double expectedPrecision = new DifficultyControlPoint().SliderVelocityBindable.Precision;
if (selectedPointBindable.Precision < expectedPrecision)
selectedPointBindable.Precision = expectedPrecision;
sliderVelocitySlider.Current = selectedPointBindable;
sliderVelocitySlider.Current.BindValueChanged(_ => beatmap?.Update(hitObject));
}
}
} }
} }

View File

@ -0,0 +1,63 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osuTK.Graphics;
namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
public class HitObjectPointPiece : CircularContainer
{
private readonly ControlPoint point;
protected OsuSpriteText Label { get; private set; }
protected HitObjectPointPiece(ControlPoint point)
{
this.point = point;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
AutoSizeAxes = Axes.Both;
Color4 colour = point.GetRepresentingColour(colours);
InternalChildren = new Drawable[]
{
new Container
{
AutoSizeAxes = Axes.X,
Height = 16,
Masking = true,
CornerRadius = 8,
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Children = new Drawable[]
{
new Box
{
Colour = colour,
RelativeSizeAxes = Axes.Both,
},
Label = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Padding = new MarginPadding(5),
Font = OsuFont.Default.With(size: 12, weight: FontWeight.SemiBold),
Colour = colours.B5,
}
}
},
};
}
}
}

View File

@ -3,88 +3,102 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterfaceV2;
using osuTK.Graphics; using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Edit.Timing;
namespace osu.Game.Screens.Edit.Compose.Components.Timeline namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{ {
public class SamplePointPiece : CompositeDrawable public class SamplePointPiece : HitObjectPointPiece, IHasPopover
{ {
private readonly SampleControlPoint samplePoint; private readonly HitObject hitObject;
private readonly Bindable<string> bank; private readonly Bindable<string> bank;
private readonly BindableNumber<int> volume; private readonly BindableNumber<int> volume;
private OsuSpriteText text; public SamplePointPiece(HitObject hitObject)
private Container volumeBox; : base(hitObject.SampleControlPoint)
private const int max_volume_height = 22;
public SamplePointPiece(SampleControlPoint samplePoint)
{ {
this.samplePoint = samplePoint; this.hitObject = hitObject;
volume = samplePoint.SampleVolumeBindable.GetBoundCopy(); volume = hitObject.SampleControlPoint.SampleVolumeBindable.GetBoundCopy();
bank = samplePoint.SampleBankBindable.GetBoundCopy(); bank = hitObject.SampleControlPoint.SampleBankBindable.GetBoundCopy();
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
Margin = new MarginPadding { Vertical = 5 }; volume.BindValueChanged(volume => updateText());
bank.BindValueChanged(bank => updateText(), true);
}
Origin = Anchor.BottomCentre; protected override bool OnClick(ClickEvent e)
Anchor = Anchor.BottomCentre; {
this.ShowPopover();
return true;
}
AutoSizeAxes = Axes.X; private void updateText()
RelativeSizeAxes = Axes.Y; {
Label.Text = $"{bank.Value} {volume.Value}";
}
Color4 colour = samplePoint.GetRepresentingColour(colours); public Popover GetPopover() => new SampleEditPopover(hitObject);
InternalChildren = new Drawable[] public class SampleEditPopover : OsuPopover
{
private readonly HitObject hitObject;
private readonly SampleControlPoint point;
private LabelledTextBox bank;
private SliderWithTextBoxInput<int> volume;
[Resolved(canBeNull: true)]
private EditorBeatmap beatmap { get; set; }
public SampleEditPopover(HitObject hitObject)
{ {
volumeBox = new Circle this.hitObject = hitObject;
point = hitObject.SampleControlPoint;
}
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{ {
CornerRadius = 5, new FillFlowContainer
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Y = -20,
Width = 10,
Colour = colour,
},
new Container
{
AutoSizeAxes = Axes.X,
Height = 16,
Masking = true,
CornerRadius = 8,
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Children = new Drawable[]
{ {
new Box Width = 200,
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{ {
Colour = colour, bank = new LabelledTextBox
RelativeSizeAxes = Axes.Both, {
}, Label = "Bank Name",
text = new OsuSpriteText },
{ volume = new SliderWithTextBoxInput<int>("Volume")
Anchor = Anchor.Centre, {
Origin = Anchor.Centre, Current = new SampleControlPoint().SampleVolumeBindable,
Padding = new MarginPadding(5), }
Font = OsuFont.Default.With(size: 12, weight: FontWeight.SemiBold),
Colour = colours.B5,
} }
} }
}, };
};
volume.BindValueChanged(volume => volumeBox.Height = max_volume_height * volume.NewValue / 100f, true); bank.Current = point.SampleBankBindable;
bank.BindValueChanged(bank => text.Text = bank.NewValue, true); bank.Current.BindValueChanged(_ => beatmap.Update(hitObject));
volume.Current = point.SampleVolumeBindable;
volume.Current.BindValueChanged(_ => beatmap.Update(hitObject));
}
} }
} }
} }

View File

@ -59,7 +59,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
private Track track; private Track track;
private const float timeline_height = 72; private const float timeline_height = 72;
private const float timeline_expanded_height = 156; private const float timeline_expanded_height = 94;
public Timeline(Drawable userContent) public Timeline(Drawable userContent)
{ {
@ -159,7 +159,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
if (visible.NewValue) if (visible.NewValue)
{ {
this.ResizeHeightTo(timeline_expanded_height, 200, Easing.OutQuint); this.ResizeHeightTo(timeline_expanded_height, 200, Easing.OutQuint);
mainContent.MoveToY(36, 200, Easing.OutQuint); mainContent.MoveToY(20, 200, Easing.OutQuint);
// delay the fade in else masking looks weird. // delay the fade in else masking looks weird.
controlPoints.Delay(180).FadeIn(400, Easing.OutQuint); controlPoints.Delay(180).FadeIn(400, Easing.OutQuint);

View File

@ -45,17 +45,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{ {
switch (point) switch (point)
{ {
case DifficultyControlPoint difficultyPoint:
AddInternal(new DifficultyPointPiece(difficultyPoint) { Depth = -2 });
break;
case TimingControlPoint timingPoint: case TimingControlPoint timingPoint:
AddInternal(new TimingPointPiece(timingPoint)); AddInternal(new TimingPointPiece(timingPoint));
break; break;
case SampleControlPoint samplePoint:
AddInternal(new SamplePointPiece(samplePoint) { Depth = -1 });
break;
} }
} }
}, true); }, true);

View File

@ -13,7 +13,9 @@ using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Threading;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
@ -179,6 +181,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
colouredComponents.Colour = OsuColour.ForegroundTextColourFor(col); colouredComponents.Colour = OsuColour.ForegroundTextColourFor(col);
} }
private SamplePointPiece sampleOverrideDisplay;
private DifficultyPointPiece difficultyOverrideDisplay;
[Resolved]
private EditorBeatmap beatmap { get; set; }
private DifficultyControlPoint difficultyControlPoint;
private SampleControlPoint sampleControlPoint;
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
@ -194,6 +205,36 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
if (Item is IHasRepeats repeats) if (Item is IHasRepeats repeats)
updateRepeats(repeats); updateRepeats(repeats);
} }
if (difficultyControlPoint != Item.DifficultyControlPoint)
{
difficultyControlPoint = Item.DifficultyControlPoint;
difficultyOverrideDisplay?.Expire();
if (Item.DifficultyControlPoint != null && Item is IHasDistance)
{
AddInternal(difficultyOverrideDisplay = new DifficultyPointPiece(Item)
{
Anchor = Anchor.TopLeft,
Origin = Anchor.BottomCentre
});
}
}
if (sampleControlPoint != Item.SampleControlPoint)
{
sampleControlPoint = Item.SampleControlPoint;
sampleOverrideDisplay?.Expire();
if (Item.SampleControlPoint != null)
{
AddInternal(sampleOverrideDisplay = new SamplePointPiece(Item)
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.TopCentre
});
}
}
} }
private void updateRepeats(IHasRepeats repeats) private void updateRepeats(IHasRepeats repeats)
@ -331,39 +372,66 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
return true; return true;
} }
private ScheduledDelegate dragOperation;
protected override void OnDrag(DragEvent e) protected override void OnDrag(DragEvent e)
{ {
base.OnDrag(e); base.OnDrag(e);
OnDragHandled?.Invoke(e); // schedule is temporary to ensure we don't process multiple times on a single update frame. we need to find a better method of doing this.
// without it, a hitobject's endtime may not always be in a valid state (ie. sliders, which needs to recompute their path).
if (timeline.SnapScreenSpacePositionToValidTime(e.ScreenSpaceMousePosition).Time is double time) dragOperation?.Cancel();
dragOperation = Scheduler.Add(() =>
{ {
switch (hitObject) OnDragHandled?.Invoke(e);
if (timeline.SnapScreenSpacePositionToValidTime(e.ScreenSpaceMousePosition).Time is double time)
{ {
case IHasRepeats repeatHitObject: switch (hitObject)
// find the number of repeats which can fit in the requested time. {
var lengthOfOneRepeat = repeatHitObject.Duration / (repeatHitObject.RepeatCount + 1); case IHasRepeats repeatHitObject:
var proposedCount = Math.Max(0, (int)Math.Round((time - hitObject.StartTime) / lengthOfOneRepeat) - 1); double proposedDuration = time - hitObject.StartTime;
if (proposedCount == repeatHitObject.RepeatCount) if (e.CurrentState.Keyboard.ShiftPressed)
return; {
if (hitObject.DifficultyControlPoint == DifficultyControlPoint.DEFAULT)
hitObject.DifficultyControlPoint = new DifficultyControlPoint();
repeatHitObject.RepeatCount = proposedCount; var newVelocity = hitObject.DifficultyControlPoint.SliderVelocity * (repeatHitObject.Duration / proposedDuration);
beatmap.Update(hitObject);
break;
case IHasDuration endTimeHitObject: if (Precision.AlmostEquals(newVelocity, hitObject.DifficultyControlPoint.SliderVelocity))
var snappedTime = Math.Max(hitObject.StartTime, beatSnapProvider.SnapTime(time)); return;
if (endTimeHitObject.EndTime == snappedTime || Precision.AlmostEquals(snappedTime, hitObject.StartTime, beatmap.GetBeatLengthAtTime(snappedTime))) hitObject.DifficultyControlPoint.SliderVelocity = newVelocity;
return; beatmap.Update(hitObject);
}
else
{
// find the number of repeats which can fit in the requested time.
var lengthOfOneRepeat = repeatHitObject.Duration / (repeatHitObject.RepeatCount + 1);
var proposedCount = Math.Max(0, (int)Math.Round(proposedDuration / lengthOfOneRepeat) - 1);
endTimeHitObject.Duration = snappedTime - hitObject.StartTime; if (proposedCount == repeatHitObject.RepeatCount)
beatmap.Update(hitObject); return;
break;
repeatHitObject.RepeatCount = proposedCount;
beatmap.Update(hitObject);
}
break;
case IHasDuration endTimeHitObject:
var snappedTime = Math.Max(hitObject.StartTime, beatSnapProvider.SnapTime(time));
if (endTimeHitObject.EndTime == snappedTime || Precision.AlmostEquals(snappedTime, hitObject.StartTime, beatmap.GetBeatLengthAtTime(snappedTime)))
return;
endTimeHitObject.Duration = snappedTime - hitObject.StartTime;
beatmap.Update(hitObject);
break;
}
} }
} });
} }
protected override void OnDragEnd(DragEndEvent e) protected override void OnDragEnd(DragEndEvent e)

View File

@ -10,6 +10,7 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
@ -71,6 +72,31 @@ namespace osu.Game.Screens.Edit
{ {
PlayableBeatmap = playableBeatmap; PlayableBeatmap = playableBeatmap;
// ensure we are not working with legacy control points.
// if we leave the legacy points around they will be applied over any local changes on
// ApplyDefaults calls. this should eventually be removed once the default logic is moved to the decoder/converter.
if (PlayableBeatmap.ControlPointInfo is LegacyControlPointInfo)
{
var newControlPoints = new ControlPointInfo();
foreach (var controlPoint in PlayableBeatmap.ControlPointInfo.AllControlPoints)
{
switch (controlPoint)
{
case DifficultyControlPoint _:
case SampleControlPoint _:
// skip legacy types.
continue;
default:
newControlPoints.Add(controlPoint.Time, controlPoint);
break;
}
}
playableBeatmap.ControlPointInfo = newControlPoints;
}
this.beatmapInfo = beatmapInfo ?? playableBeatmap.BeatmapInfo; this.beatmapInfo = beatmapInfo ?? playableBeatmap.BeatmapInfo;
if (beatmapSkin is Skin skin) if (beatmapSkin is Skin skin)

View File

@ -25,7 +25,9 @@ namespace osu.Game.Screens.Edit
public double TrackLength => track.Value?.Length ?? 60000; public double TrackLength => track.Value?.Length ?? 60000;
public ControlPointInfo ControlPointInfo; public ControlPointInfo ControlPointInfo => Beatmap.ControlPointInfo;
public IBeatmap Beatmap { get; set; }
private readonly BindableBeatDivisor beatDivisor; private readonly BindableBeatDivisor beatDivisor;
@ -42,25 +44,15 @@ namespace osu.Game.Screens.Edit
/// </summary> /// </summary>
public bool IsSeeking { get; private set; } public bool IsSeeking { get; private set; }
public EditorClock(IBeatmap beatmap, BindableBeatDivisor beatDivisor) public EditorClock(IBeatmap beatmap = null, BindableBeatDivisor beatDivisor = null)
: this(beatmap.ControlPointInfo, beatDivisor)
{ {
} Beatmap = beatmap ?? new Beatmap();
public EditorClock(ControlPointInfo controlPointInfo, BindableBeatDivisor beatDivisor) this.beatDivisor = beatDivisor ?? new BindableBeatDivisor();
{
this.beatDivisor = beatDivisor;
ControlPointInfo = controlPointInfo;
underlyingClock = new DecoupleableInterpolatingFramedClock(); underlyingClock = new DecoupleableInterpolatingFramedClock();
} }
public EditorClock()
: this(new ControlPointInfo(), new BindableBeatDivisor())
{
}
/// <summary> /// <summary>
/// Seek to the closest snappable beat from a time. /// Seek to the closest snappable beat from a time.
/// </summary> /// </summary>

View File

@ -12,8 +12,6 @@ namespace osu.Game.Screens.Edit.Timing
{ {
new GroupSection(), new GroupSection(),
new TimingSection(), new TimingSection(),
new DifficultySection(),
new SampleSection(),
new EffectSection(), new EffectSection(),
}; };
} }

View File

@ -1,56 +0,0 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Legacy;
namespace osu.Game.Screens.Edit.Timing
{
internal class DifficultySection : Section<DifficultyControlPoint>
{
private SliderWithTextBoxInput<double> sliderVelocitySlider;
[BackgroundDependencyLoader]
private void load()
{
Flow.AddRange(new[]
{
sliderVelocitySlider = new SliderWithTextBoxInput<double>("Slider Velocity")
{
Current = new DifficultyControlPoint().SliderVelocityBindable,
KeyboardStep = 0.1f
}
});
}
protected override void OnControlPointChanged(ValueChangedEvent<DifficultyControlPoint> point)
{
if (point.NewValue != null)
{
var selectedPointBindable = point.NewValue.SliderVelocityBindable;
// there may be legacy control points, which contain infinite precision for compatibility reasons (see LegacyDifficultyControlPoint).
// generally that level of precision could only be set by externally editing the .osu file, so at the point
// a user is looking to update this within the editor it should be safe to obliterate this additional precision.
double expectedPrecision = new DifficultyControlPoint().SliderVelocityBindable.Precision;
if (selectedPointBindable.Precision < expectedPrecision)
selectedPointBindable.Precision = expectedPrecision;
sliderVelocitySlider.Current = selectedPointBindable;
sliderVelocitySlider.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
}
}
protected override DifficultyControlPoint CreatePoint()
{
var reference = (Beatmap.ControlPointInfo as LegacyControlPointInfo)?.DifficultyPointAt(SelectedGroup.Value.Time) ?? DifficultyControlPoint.DEFAULT;
return new DifficultyControlPoint
{
SliderVelocity = reference.SliderVelocity,
};
}
}
}

View File

@ -1,57 +0,0 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Graphics.UserInterfaceV2;
namespace osu.Game.Screens.Edit.Timing
{
internal class SampleSection : Section<SampleControlPoint>
{
private LabelledTextBox bank;
private SliderWithTextBoxInput<int> volume;
[BackgroundDependencyLoader]
private void load()
{
Flow.AddRange(new Drawable[]
{
bank = new LabelledTextBox
{
Label = "Bank Name",
},
volume = new SliderWithTextBoxInput<int>("Volume")
{
Current = new SampleControlPoint().SampleVolumeBindable,
}
});
}
protected override void OnControlPointChanged(ValueChangedEvent<SampleControlPoint> point)
{
if (point.NewValue != null)
{
bank.Current = point.NewValue.SampleBankBindable;
bank.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
volume.Current = point.NewValue.SampleVolumeBindable;
volume.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
}
}
protected override SampleControlPoint CreatePoint()
{
var reference = (Beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePointAt(SelectedGroup.Value.Time) ?? SampleControlPoint.DEFAULT;
return new SampleControlPoint
{
SampleBank = reference.SampleBank,
SampleVolume = reference.SampleVolume,
};
}
}
}

View File

@ -5,7 +5,6 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Screens.Edit; using osu.Game.Screens.Edit;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
@ -23,7 +22,7 @@ namespace osu.Game.Tests.Visual
protected EditorClockTestScene() protected EditorClockTestScene()
{ {
Clock = new EditorClock(new ControlPointInfo(), BeatDivisor) { IsCoupled = false }; Clock = new EditorClock(new Beatmap(), BeatDivisor) { IsCoupled = false };
} }
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@ -44,7 +43,7 @@ namespace osu.Game.Tests.Visual
private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> e) private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> e)
{ {
Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; Clock.Beatmap = e.NewValue.Beatmap;
Clock.ChangeSource(e.NewValue.Track); Clock.ChangeSource(e.NewValue.Track);
Clock.ProcessFrame(); Clock.ProcessFrame();
} }