mirror of
https://github.com/osukey/osukey.git
synced 2025-06-20 18:58:05 +09:00
Merge branch 'master' into control-point-timeline-representation
This commit is contained in:
commit
2f15d558a3
@ -52,6 +52,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.904.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.904.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.930.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.1001.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -164,7 +164,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
{
|
{
|
||||||
var slider = new Slider
|
var slider = new Slider
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + 1000,
|
StartTime = Time.Current + time_offset,
|
||||||
Position = new Vector2(239, 176),
|
Position = new Vector2(239, 176),
|
||||||
Path = new SliderPath(PathType.PerfectCurve, new[]
|
Path = new SliderPath(PathType.PerfectCurve, new[]
|
||||||
{
|
{
|
||||||
@ -185,22 +185,26 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
private Drawable testSlowSpeed() => createSlider(speedMultiplier: 0.5);
|
private Drawable testSlowSpeed() => createSlider(speedMultiplier: 0.5);
|
||||||
|
|
||||||
private Drawable testShortSlowSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 0.5);
|
private Drawable testShortSlowSpeed(int repeats = 0) => createSlider(distance: max_length / 4, repeats: repeats, speedMultiplier: 0.5);
|
||||||
|
|
||||||
private Drawable testHighSpeed(int repeats = 0) => createSlider(repeats: repeats, speedMultiplier: 15);
|
private Drawable testHighSpeed(int repeats = 0) => createSlider(repeats: repeats, speedMultiplier: 15);
|
||||||
|
|
||||||
private Drawable testShortHighSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 15);
|
private Drawable testShortHighSpeed(int repeats = 0) => createSlider(distance: max_length / 4, repeats: repeats, speedMultiplier: 15);
|
||||||
|
|
||||||
private Drawable createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2, int stackHeight = 0)
|
private const double time_offset = 1500;
|
||||||
|
|
||||||
|
private const float max_length = 200;
|
||||||
|
|
||||||
|
private Drawable createSlider(float circleSize = 2, float distance = max_length, int repeats = 0, double speedMultiplier = 2, int stackHeight = 0)
|
||||||
{
|
{
|
||||||
var slider = new Slider
|
var slider = new Slider
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + 1000,
|
StartTime = Time.Current + time_offset,
|
||||||
Position = new Vector2(-(distance / 2), 0),
|
Position = new Vector2(0, -(distance / 2)),
|
||||||
Path = new SliderPath(PathType.PerfectCurve, new[]
|
Path = new SliderPath(PathType.PerfectCurve, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
new Vector2(distance, 0),
|
new Vector2(0, distance),
|
||||||
}, distance),
|
}, distance),
|
||||||
RepeatCount = repeats,
|
RepeatCount = repeats,
|
||||||
StackHeight = stackHeight
|
StackHeight = stackHeight
|
||||||
@ -213,14 +217,14 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
{
|
{
|
||||||
var slider = new Slider
|
var slider = new Slider
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + 1000,
|
StartTime = Time.Current + time_offset,
|
||||||
Position = new Vector2(-200, 0),
|
Position = new Vector2(-max_length / 2, 0),
|
||||||
Path = new SliderPath(PathType.PerfectCurve, new[]
|
Path = new SliderPath(PathType.PerfectCurve, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
new Vector2(200, 200),
|
new Vector2(max_length / 2, max_length / 2),
|
||||||
new Vector2(400, 0)
|
new Vector2(max_length, 0)
|
||||||
}, 600),
|
}, max_length * 1.5f),
|
||||||
RepeatCount = repeats,
|
RepeatCount = repeats,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -233,16 +237,16 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
{
|
{
|
||||||
var slider = new Slider
|
var slider = new Slider
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + 1000,
|
StartTime = Time.Current + time_offset,
|
||||||
Position = new Vector2(-200, 0),
|
Position = new Vector2(-max_length / 2, 0),
|
||||||
Path = new SliderPath(PathType.Linear, new[]
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
new Vector2(150, 75),
|
new Vector2(max_length * 0.375f, max_length * 0.18f),
|
||||||
new Vector2(200, 0),
|
new Vector2(max_length / 2, 0),
|
||||||
new Vector2(300, -200),
|
new Vector2(max_length * 0.75f, -max_length / 2),
|
||||||
new Vector2(400, 0),
|
new Vector2(max_length * 0.95f, 0),
|
||||||
new Vector2(430, 0)
|
new Vector2(max_length, 0)
|
||||||
}),
|
}),
|
||||||
RepeatCount = repeats,
|
RepeatCount = repeats,
|
||||||
};
|
};
|
||||||
@ -256,15 +260,15 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
{
|
{
|
||||||
var slider = new Slider
|
var slider = new Slider
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + 1000,
|
StartTime = Time.Current + time_offset,
|
||||||
Position = new Vector2(-200, 0),
|
Position = new Vector2(-max_length / 2, 0),
|
||||||
Path = new SliderPath(PathType.Bezier, new[]
|
Path = new SliderPath(PathType.Bezier, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
new Vector2(150, 75),
|
new Vector2(max_length * 0.375f, max_length * 0.18f),
|
||||||
new Vector2(200, 100),
|
new Vector2(max_length / 2, max_length / 4),
|
||||||
new Vector2(300, -200),
|
new Vector2(max_length * 0.75f, -max_length / 2),
|
||||||
new Vector2(430, 0)
|
new Vector2(max_length, 0)
|
||||||
}),
|
}),
|
||||||
RepeatCount = repeats,
|
RepeatCount = repeats,
|
||||||
};
|
};
|
||||||
@ -278,16 +282,16 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
{
|
{
|
||||||
var slider = new Slider
|
var slider = new Slider
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + 1000,
|
StartTime = Time.Current + time_offset,
|
||||||
Position = new Vector2(0, 0),
|
Position = new Vector2(0, 0),
|
||||||
Path = new SliderPath(PathType.Linear, new[]
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
new Vector2(-200, 0),
|
new Vector2(-max_length / 2, 0),
|
||||||
new Vector2(0, 0),
|
new Vector2(0, 0),
|
||||||
new Vector2(0, -200),
|
new Vector2(0, -max_length / 2),
|
||||||
new Vector2(-200, -200),
|
new Vector2(-max_length / 2, -max_length / 2),
|
||||||
new Vector2(0, -200)
|
new Vector2(0, -max_length / 2)
|
||||||
}),
|
}),
|
||||||
RepeatCount = repeats,
|
RepeatCount = repeats,
|
||||||
};
|
};
|
||||||
@ -305,14 +309,14 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
var slider = new Slider
|
var slider = new Slider
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + 1000,
|
StartTime = Time.Current + time_offset,
|
||||||
Position = new Vector2(-100, 0),
|
Position = new Vector2(-max_length / 4, 0),
|
||||||
Path = new SliderPath(PathType.Catmull, new[]
|
Path = new SliderPath(PathType.Catmull, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
new Vector2(50, -50),
|
new Vector2(max_length * 0.125f, max_length * 0.125f),
|
||||||
new Vector2(150, 50),
|
new Vector2(max_length * 0.375f, max_length * 0.125f),
|
||||||
new Vector2(200, 0)
|
new Vector2(max_length / 2, 0)
|
||||||
}),
|
}),
|
||||||
RepeatCount = repeats,
|
RepeatCount = repeats,
|
||||||
NodeSamples = repeatSamples
|
NodeSamples = repeatSamples
|
||||||
|
@ -110,6 +110,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void StopAllSamples()
|
||||||
|
{
|
||||||
|
base.StopAllSamples();
|
||||||
|
slidingSample?.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
|
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
|
||||||
{
|
{
|
||||||
if (tracking.NewValue)
|
if (tracking.NewValue)
|
||||||
|
@ -124,6 +124,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void StopAllSamples()
|
||||||
|
{
|
||||||
|
base.StopAllSamples();
|
||||||
|
spinningSample?.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
||||||
{
|
{
|
||||||
base.AddNestedHitObject(hitObject);
|
base.AddNestedHitObject(hitObject);
|
||||||
|
@ -93,6 +93,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
drawableSpinner.RotationTracker.Complete.BindValueChanged(complete => updateComplete(complete.NewValue, 200));
|
drawableSpinner.RotationTracker.Complete.BindValueChanged(complete => updateComplete(complete.NewValue, 200));
|
||||||
drawableSpinner.ApplyCustomUpdateState += updateStateTransforms;
|
drawableSpinner.ApplyCustomUpdateState += updateStateTransforms;
|
||||||
|
|
||||||
|
updateStateTransforms(drawableSpinner, drawableSpinner.State.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
@ -124,6 +126,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
|
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
|
||||||
{
|
{
|
||||||
|
if (!(drawableHitObject is DrawableSpinner))
|
||||||
|
return;
|
||||||
|
|
||||||
centre.ScaleTo(0);
|
centre.ScaleTo(0);
|
||||||
mainContainer.ScaleTo(0);
|
mainContainer.ScaleTo(0);
|
||||||
|
|
||||||
|
@ -72,10 +72,15 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
|
|
||||||
this.FadeOut();
|
this.FadeOut();
|
||||||
drawableSpinner.ApplyCustomUpdateState += updateStateTransforms;
|
drawableSpinner.ApplyCustomUpdateState += updateStateTransforms;
|
||||||
|
|
||||||
|
updateStateTransforms(drawableSpinner, drawableSpinner.State.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
|
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
|
||||||
{
|
{
|
||||||
|
if (!(drawableHitObject is DrawableSpinner))
|
||||||
|
return;
|
||||||
|
|
||||||
var spinner = (Spinner)drawableSpinner.HitObject;
|
var spinner = (Spinner)drawableSpinner.HitObject;
|
||||||
|
|
||||||
using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimeFadeIn / 2, true))
|
using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimeFadeIn / 2, true))
|
||||||
|
@ -24,12 +24,16 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
private Sprite metreSprite;
|
private Sprite metreSprite;
|
||||||
private Container metre;
|
private Container metre;
|
||||||
|
|
||||||
|
private bool spinnerBlink;
|
||||||
|
|
||||||
private const float sprite_scale = 1 / 1.6f;
|
private const float sprite_scale = 1 / 1.6f;
|
||||||
private const float final_metre_height = 692 * sprite_scale;
|
private const float final_metre_height = 692 * sprite_scale;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ISkinSource source, DrawableHitObject drawableObject)
|
private void load(ISkinSource source, DrawableHitObject drawableObject)
|
||||||
{
|
{
|
||||||
|
spinnerBlink = source.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.SpinnerNoBlink)?.Value != true;
|
||||||
|
|
||||||
drawableSpinner = (DrawableSpinner)drawableObject;
|
drawableSpinner = (DrawableSpinner)drawableObject;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
@ -86,10 +90,15 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
|
|
||||||
this.FadeOut();
|
this.FadeOut();
|
||||||
drawableSpinner.ApplyCustomUpdateState += updateStateTransforms;
|
drawableSpinner.ApplyCustomUpdateState += updateStateTransforms;
|
||||||
|
|
||||||
|
updateStateTransforms(drawableSpinner, drawableSpinner.State.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
|
private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state)
|
||||||
{
|
{
|
||||||
|
if (!(drawableHitObject is DrawableSpinner))
|
||||||
|
return;
|
||||||
|
|
||||||
var spinner = drawableSpinner.HitObject;
|
var spinner = drawableSpinner.HitObject;
|
||||||
|
|
||||||
using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimeFadeIn / 2, true))
|
using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimeFadeIn / 2, true))
|
||||||
@ -116,12 +125,15 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
|
|
||||||
private float getMetreHeight(float progress)
|
private float getMetreHeight(float progress)
|
||||||
{
|
{
|
||||||
progress = Math.Min(99, progress * 100);
|
progress *= 100;
|
||||||
|
|
||||||
|
// the spinner should still blink at 100% progress.
|
||||||
|
if (spinnerBlink)
|
||||||
|
progress = Math.Min(99, progress);
|
||||||
|
|
||||||
int barCount = (int)progress / 10;
|
int barCount = (int)progress / 10;
|
||||||
|
|
||||||
// todo: add SpinnerNoBlink support
|
if (spinnerBlink && RNG.NextBool(((int)progress % 10) / 10f))
|
||||||
if (RNG.NextBool(((int)progress % 10) / 10f))
|
|
||||||
barCount++;
|
barCount++;
|
||||||
|
|
||||||
return (float)barCount / total_bars * final_metre_height;
|
return (float)barCount / total_bars * final_metre_height;
|
||||||
|
@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
CursorRotate,
|
CursorRotate,
|
||||||
HitCircleOverlayAboveNumber,
|
HitCircleOverlayAboveNumber,
|
||||||
HitCircleOverlayAboveNumer, // Some old skins will have this typo
|
HitCircleOverlayAboveNumer, // Some old skins will have this typo
|
||||||
SpinnerFrequencyModulate
|
SpinnerFrequencyModulate,
|
||||||
|
SpinnerNoBlink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,22 @@ namespace osu.Game.Tests.NonVisual
|
|||||||
Assert.That(cpi.Groups.Count, Is.EqualTo(0));
|
Assert.That(cpi.Groups.Count, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestRemoveGroupAlsoRemovedControlPoints()
|
||||||
|
{
|
||||||
|
var cpi = new ControlPointInfo();
|
||||||
|
|
||||||
|
var group = cpi.GroupAt(1000, true);
|
||||||
|
|
||||||
|
group.Add(new SampleControlPoint());
|
||||||
|
|
||||||
|
Assert.That(cpi.SamplePoints.Count, Is.EqualTo(1));
|
||||||
|
|
||||||
|
cpi.RemoveGroup(group);
|
||||||
|
|
||||||
|
Assert.That(cpi.SamplePoints.Count, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAddControlPointToGroup()
|
public void TestAddControlPointToGroup()
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics.Audio;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
|
{
|
||||||
|
public class TestSceneEditorSamplePlayback : EditorTestScene
|
||||||
|
{
|
||||||
|
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSlidingSampleStopsOnSeek()
|
||||||
|
{
|
||||||
|
DrawableSlider slider = null;
|
||||||
|
DrawableSample[] samples = null;
|
||||||
|
|
||||||
|
AddStep("get first slider", () =>
|
||||||
|
{
|
||||||
|
slider = Editor.ChildrenOfType<DrawableSlider>().OrderBy(s => s.HitObject.StartTime).First();
|
||||||
|
samples = slider.ChildrenOfType<DrawableSample>().ToArray();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("start playback", () => EditorClock.Start());
|
||||||
|
|
||||||
|
AddUntilStep("wait for slider sliding then seek", () =>
|
||||||
|
{
|
||||||
|
if (!slider.Tracking.Value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!samples.Any(s => s.Playing))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EditorClock.Seek(20000);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("slider samples are not playing", () => samples.Length == 5 && samples.All(s => s.Played && !s.Playing));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,7 +28,7 @@ namespace osu.Game.Tournament.Components
|
|||||||
{
|
{
|
||||||
base.Bindable = new Bindable<string>();
|
base.Bindable = new Bindable<string>();
|
||||||
|
|
||||||
((OsuTextBox)Control).OnCommit = (sender, newText) =>
|
((OsuTextBox)Control).OnCommit += (sender, newText) =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -158,6 +158,9 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
|
|
||||||
public void RemoveGroup(ControlPointGroup group)
|
public void RemoveGroup(ControlPointGroup group)
|
||||||
{
|
{
|
||||||
|
foreach (var item in group.ControlPoints.ToArray())
|
||||||
|
group.Remove(item);
|
||||||
|
|
||||||
group.ItemAdded -= groupItemAdded;
|
group.ItemAdded -= groupItemAdded;
|
||||||
group.ItemRemoved -= groupItemRemoved;
|
group.ItemRemoved -= groupItemRemoved;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
Rank = Rank,
|
Rank = Rank,
|
||||||
Ruleset = ruleset,
|
Ruleset = ruleset,
|
||||||
Mods = mods,
|
Mods = mods,
|
||||||
|
IsLegacyScore = true
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Statistics != null)
|
if (Statistics != null)
|
||||||
|
@ -59,12 +59,13 @@ namespace osu.Game.Online.Chat
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = textbox_height,
|
Height = textbox_height,
|
||||||
PlaceholderText = "type your message",
|
PlaceholderText = "type your message",
|
||||||
OnCommit = postMessage,
|
|
||||||
ReleaseFocusOnCommit = false,
|
ReleaseFocusOnCommit = false,
|
||||||
HoldFocus = true,
|
HoldFocus = true,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
textbox.OnCommit += postMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.BindValueChanged(channelChanged);
|
Channel.BindValueChanged(channelChanged);
|
||||||
|
@ -146,7 +146,6 @@ namespace osu.Game.Overlays
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Height = 1,
|
Height = 1,
|
||||||
PlaceholderText = "type your message",
|
PlaceholderText = "type your message",
|
||||||
OnCommit = postMessage,
|
|
||||||
ReleaseFocusOnCommit = false,
|
ReleaseFocusOnCommit = false,
|
||||||
HoldFocus = true,
|
HoldFocus = true,
|
||||||
}
|
}
|
||||||
@ -186,6 +185,8 @@ namespace osu.Game.Overlays
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
textbox.OnCommit += postMessage;
|
||||||
|
|
||||||
ChannelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue;
|
ChannelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue;
|
||||||
ChannelTabControl.ChannelSelectorActive.ValueChanged += active => ChannelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden;
|
ChannelTabControl.ChannelSelectorActive.ValueChanged += active => ChannelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden;
|
||||||
ChannelSelectionOverlay.State.ValueChanged += state =>
|
ChannelSelectionOverlay.State.ValueChanged += state =>
|
||||||
|
@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
filter.Search.OnCommit = (sender, newText) =>
|
filter.Search.OnCommit += (sender, newText) =>
|
||||||
{
|
{
|
||||||
BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
|
BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
|
||||||
|
|
||||||
|
@ -236,7 +236,6 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
PlaceholderText = "password",
|
PlaceholderText = "password",
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
TabbableContentContainer = this,
|
TabbableContentContainer = this,
|
||||||
OnCommit = (sender, newText) => performLogin()
|
|
||||||
},
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
@ -276,6 +275,8 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
password.OnCommit += (sender, newText) => performLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool AcceptsFocus => true;
|
public override bool AcceptsFocus => true;
|
||||||
|
@ -124,19 +124,19 @@ namespace osu.Game.Rulesets.Judgements
|
|||||||
return -DEFAULT_MAX_HEALTH_INCREASE;
|
return -DEFAULT_MAX_HEALTH_INCREASE;
|
||||||
|
|
||||||
case HitResult.Meh:
|
case HitResult.Meh:
|
||||||
return -DEFAULT_MAX_HEALTH_INCREASE * 0.05;
|
return -DEFAULT_MAX_HEALTH_INCREASE * 0.5;
|
||||||
|
|
||||||
case HitResult.Ok:
|
case HitResult.Ok:
|
||||||
return -DEFAULT_MAX_HEALTH_INCREASE * 0.01;
|
return -DEFAULT_MAX_HEALTH_INCREASE * 0.3;
|
||||||
|
|
||||||
case HitResult.Good:
|
case HitResult.Good:
|
||||||
return DEFAULT_MAX_HEALTH_INCREASE * 0.5;
|
return DEFAULT_MAX_HEALTH_INCREASE * 0.1;
|
||||||
|
|
||||||
case HitResult.Great:
|
case HitResult.Great:
|
||||||
return DEFAULT_MAX_HEALTH_INCREASE;
|
return DEFAULT_MAX_HEALTH_INCREASE * 0.8;
|
||||||
|
|
||||||
case HitResult.Perfect:
|
case HitResult.Perfect:
|
||||||
return DEFAULT_MAX_HEALTH_INCREASE * 1.05;
|
return DEFAULT_MAX_HEALTH_INCREASE;
|
||||||
|
|
||||||
case HitResult.SmallBonus:
|
case HitResult.SmallBonus:
|
||||||
return DEFAULT_MAX_HEALTH_INCREASE * 0.1;
|
return DEFAULT_MAX_HEALTH_INCREASE * 0.1;
|
||||||
|
@ -51,12 +51,12 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
public override bool PropagateNonPositionalInputSubTree => HandleUserInput;
|
public override bool PropagateNonPositionalInputSubTree => HandleUserInput;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when a <see cref="JudgementResult"/> has been applied by this <see cref="DrawableHitObject"/> or a nested <see cref="DrawableHitObject"/>.
|
/// Invoked by this or a nested <see cref="DrawableHitObject"/> after a <see cref="JudgementResult"/> has been applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<DrawableHitObject, JudgementResult> OnNewResult;
|
public event Action<DrawableHitObject, JudgementResult> OnNewResult;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when a <see cref="JudgementResult"/> is being reverted by this <see cref="DrawableHitObject"/> or a nested <see cref="DrawableHitObject"/>.
|
/// Invoked by this or a nested <see cref="DrawableHitObject"/> prior to a <see cref="JudgementResult"/> being reverted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<DrawableHitObject, JudgementResult> OnRevertResult;
|
public event Action<DrawableHitObject, JudgementResult> OnRevertResult;
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
#region State / Transform Management
|
#region State / Transform Management
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bind to apply a custom state which can override the default implementation.
|
/// Invoked by this or a nested <see cref="DrawableHitObject"/> to apply a custom state that can override the default implementation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<DrawableHitObject, ArmedState> ApplyCustomUpdateState;
|
public event Action<DrawableHitObject, ArmedState> ApplyCustomUpdateState;
|
||||||
|
|
||||||
@ -384,6 +384,11 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stops playback of all samples. Automatically called when <see cref="DrawableHitObject{TObject}"/>'s lifetime has been exceeded.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void StopAllSamples() => Samples?.Stop();
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
@ -452,6 +457,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
foreach (var nested in NestedHitObjects)
|
foreach (var nested in NestedHitObjects)
|
||||||
nested.OnKilled();
|
nested.OnKilled();
|
||||||
|
|
||||||
|
StopAllSamples();
|
||||||
|
|
||||||
UpdateResult(false);
|
UpdateResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,6 +469,9 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
/// <param name="application">The callback that applies changes to the <see cref="JudgementResult"/>.</param>
|
/// <param name="application">The callback that applies changes to the <see cref="JudgementResult"/>.</param>
|
||||||
protected void ApplyResult(Action<JudgementResult> application)
|
protected void ApplyResult(Action<JudgementResult> application)
|
||||||
{
|
{
|
||||||
|
if (Result.HasResult)
|
||||||
|
throw new InvalidOperationException("Cannot apply result on a hitobject that already has a result.");
|
||||||
|
|
||||||
application?.Invoke(Result);
|
application?.Invoke(Result);
|
||||||
|
|
||||||
if (!Result.HasResult)
|
if (!Result.HasResult)
|
||||||
|
@ -185,6 +185,34 @@ namespace osu.Game.Scoring
|
|||||||
[JsonProperty("position")]
|
[JsonProperty("position")]
|
||||||
public int? Position { get; set; }
|
public int? Position { get; set; }
|
||||||
|
|
||||||
|
private bool isLegacyScore;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this <see cref="ScoreInfo"/> represents a legacy (osu!stable) score.
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
[NotMapped]
|
||||||
|
public bool IsLegacyScore
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (isLegacyScore)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// The above check will catch legacy online scores that have an appropriate UserString + UserId.
|
||||||
|
// For non-online scores such as those imported in, a heuristic is used based on the following table:
|
||||||
|
//
|
||||||
|
// Mode | UserString | UserId
|
||||||
|
// --------------- | ---------- | ---------
|
||||||
|
// stable | <username> | 1
|
||||||
|
// lazer | <username> | <userid>
|
||||||
|
// lazer (offline) | Guest | 1
|
||||||
|
|
||||||
|
return ID > 0 && UserID == 1 && UserString != "Guest";
|
||||||
|
}
|
||||||
|
set => isLegacyScore = value;
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<(HitResult result, int count, int? maxCount)> GetStatisticsForDisplay()
|
public IEnumerable<(HitResult result, int count, int? maxCount)> GetStatisticsForDisplay()
|
||||||
{
|
{
|
||||||
foreach (var key in OrderAttributeUtils.GetValuesInOrder<HitResult>())
|
foreach (var key in OrderAttributeUtils.GetValuesInOrder<HitResult>())
|
||||||
|
@ -10,6 +10,7 @@ using System.Threading;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -149,23 +150,38 @@ namespace osu.Game.Scoring
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int? beatmapMaxCombo = score.Beatmap.MaxCombo;
|
int beatmapMaxCombo;
|
||||||
|
|
||||||
if (beatmapMaxCombo == null)
|
if (score.IsLegacyScore)
|
||||||
{
|
{
|
||||||
if (score.Beatmap.ID == 0 || difficulties == null)
|
// This score is guaranteed to be an osu!stable score.
|
||||||
|
// The combo must be determined through either the beatmap's max combo value or the difficulty calculator, as lazer's scoring has changed and the score statistics cannot be used.
|
||||||
|
if (score.Beatmap.MaxCombo == null)
|
||||||
{
|
{
|
||||||
// We don't have enough information (max combo) to compute the score, so let's use the provided score.
|
if (score.Beatmap.ID == 0 || difficulties == null)
|
||||||
Value = score.TotalScore;
|
{
|
||||||
|
// We don't have enough information (max combo) to compute the score, so use the provided score.
|
||||||
|
Value = score.TotalScore;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can compute the max combo locally after the async beatmap difficulty computation.
|
||||||
|
difficultyBindable = difficulties().GetBindableDifficulty(score.Beatmap, score.Ruleset, score.Mods, (difficultyCancellationSource = new CancellationTokenSource()).Token);
|
||||||
|
difficultyBindable.BindValueChanged(d => updateScore(d.NewValue.MaxCombo), true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can compute the max combo locally after the async beatmap difficulty computation.
|
beatmapMaxCombo = score.Beatmap.MaxCombo.Value;
|
||||||
difficultyBindable = difficulties().GetBindableDifficulty(score.Beatmap, score.Ruleset, score.Mods, (difficultyCancellationSource = new CancellationTokenSource()).Token);
|
|
||||||
difficultyBindable.BindValueChanged(d => updateScore(d.NewValue.MaxCombo), true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
updateScore(beatmapMaxCombo.Value);
|
{
|
||||||
|
// This score is guaranteed to be an osu!lazer score.
|
||||||
|
// The combo must be determined through the score's statistics, as both the beatmap's max combo and the difficulty calculator will provide osu!stable combo values.
|
||||||
|
beatmapMaxCombo = Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r.AffectsCombo()).Select(r => score.Statistics.GetOrDefault(r)).Sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScore(beatmapMaxCombo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateScore(int beatmapMaxCombo)
|
private void updateScore(int beatmapMaxCombo)
|
||||||
|
@ -2,27 +2,23 @@
|
|||||||
// 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.Allocation;
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Overlays.Settings;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Timing
|
namespace osu.Game.Screens.Edit.Timing
|
||||||
{
|
{
|
||||||
internal class DifficultySection : Section<DifficultyControlPoint>
|
internal class DifficultySection : Section<DifficultyControlPoint>
|
||||||
{
|
{
|
||||||
private SettingsSlider<double> multiplier;
|
private SliderWithTextBoxInput<double> multiplierSlider;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
Flow.AddRange(new[]
|
Flow.AddRange(new[]
|
||||||
{
|
{
|
||||||
multiplier = new SettingsSlider<double>
|
multiplierSlider = new SliderWithTextBoxInput<double>("Speed Multiplier")
|
||||||
{
|
{
|
||||||
LabelText = "Speed Multiplier",
|
Current = new DifficultyControlPoint().SpeedMultiplierBindable
|
||||||
Bindable = new DifficultyControlPoint().SpeedMultiplierBindable,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -31,7 +27,7 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
{
|
{
|
||||||
if (point.NewValue != null)
|
if (point.NewValue != null)
|
||||||
{
|
{
|
||||||
multiplier.Bindable = point.NewValue.SpeedMultiplierBindable;
|
multiplierSlider.Current = point.NewValue.SpeedMultiplierBindable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,18 +2,17 @@
|
|||||||
// 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.Allocation;
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
using osu.Game.Overlays.Settings;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Timing
|
namespace osu.Game.Screens.Edit.Timing
|
||||||
{
|
{
|
||||||
internal class SampleSection : Section<SampleControlPoint>
|
internal class SampleSection : Section<SampleControlPoint>
|
||||||
{
|
{
|
||||||
private LabelledTextBox bank;
|
private LabelledTextBox bank;
|
||||||
private SettingsSlider<int> volume;
|
private SliderWithTextBoxInput<int> volume;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
@ -24,10 +23,9 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
{
|
{
|
||||||
Label = "Bank Name",
|
Label = "Bank Name",
|
||||||
},
|
},
|
||||||
volume = new SettingsSlider<int>
|
volume = new SliderWithTextBoxInput<int>("Volume")
|
||||||
{
|
{
|
||||||
Bindable = new SampleControlPoint().SampleVolumeBindable,
|
Current = new SampleControlPoint().SampleVolumeBindable,
|
||||||
LabelText = "Volume",
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -37,7 +35,7 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
if (point.NewValue != null)
|
if (point.NewValue != null)
|
||||||
{
|
{
|
||||||
bank.Current = point.NewValue.SampleBankBindable;
|
bank.Current = point.NewValue.SampleBankBindable;
|
||||||
volume.Bindable = point.NewValue.SampleVolumeBindable;
|
volume.Current = point.NewValue.SampleVolumeBindable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
77
osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs
Normal file
77
osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
|
using osu.Game.Overlays.Settings;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Timing
|
||||||
|
{
|
||||||
|
internal class SliderWithTextBoxInput<T> : CompositeDrawable, IHasCurrentValue<T>
|
||||||
|
where T : struct, IEquatable<T>, IComparable<T>, IConvertible
|
||||||
|
{
|
||||||
|
private readonly SettingsSlider<T> slider;
|
||||||
|
|
||||||
|
public SliderWithTextBoxInput(string labelText)
|
||||||
|
{
|
||||||
|
LabelledTextBox textbox;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
textbox = new LabelledTextBox
|
||||||
|
{
|
||||||
|
Label = labelText,
|
||||||
|
},
|
||||||
|
slider = new SettingsSlider<T>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
textbox.OnCommit += (t, isNew) =>
|
||||||
|
{
|
||||||
|
if (!isNew) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
slider.Bindable.Parse(t.Text);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// TriggerChange below will restore the previous text value on failure.
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is run regardless of parsing success as the parsed number may not actually trigger a change
|
||||||
|
// due to bindable clamping. Even in such a case we want to update the textbox to a sane visual state.
|
||||||
|
Current.TriggerChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
Current.BindValueChanged(val =>
|
||||||
|
{
|
||||||
|
textbox.Text = val.NewValue.ToString();
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bindable<T> Current
|
||||||
|
{
|
||||||
|
get => slider.Bindable;
|
||||||
|
set => slider.Bindable = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -65,18 +65,19 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
{
|
{
|
||||||
if (!isNew) return;
|
if (!isNew) return;
|
||||||
|
|
||||||
if (double.TryParse(Current.Value, out double doubleVal))
|
try
|
||||||
{
|
{
|
||||||
try
|
if (double.TryParse(Current.Value, out double doubleVal) && doubleVal > 0)
|
||||||
{
|
|
||||||
beatLengthBindable.Value = beatLengthToBpm(doubleVal);
|
beatLengthBindable.Value = beatLengthToBpm(doubleVal);
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// will restore the previous text value on failure.
|
|
||||||
beatLengthBindable.TriggerChange();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// TriggerChange below will restore the previous text value on failure.
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is run regardless of parsing success as the parsed number may not actually trigger a change
|
||||||
|
// due to bindable clamping. Even in such a case we want to update the textbox to a sane visual state.
|
||||||
|
beatLengthBindable.TriggerChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
beatLengthBindable.BindValueChanged(val =>
|
beatLengthBindable.BindValueChanged(val =>
|
||||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Skinning
|
|||||||
ComboPrefix,
|
ComboPrefix,
|
||||||
ComboOverlap,
|
ComboOverlap,
|
||||||
AnimationFramerate,
|
AnimationFramerate,
|
||||||
LayeredHitSounds,
|
LayeredHitSounds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,14 @@ namespace osu.Game.Skinning
|
|||||||
// it's not easy to know if a sample has finished playing (to end).
|
// it's not easy to know if a sample has finished playing (to end).
|
||||||
// to keep things simple only resume playing looping samples.
|
// to keep things simple only resume playing looping samples.
|
||||||
else if (Looping)
|
else if (Looping)
|
||||||
base.Play();
|
{
|
||||||
|
// schedule so we don't start playing a sample which is no longer alive.
|
||||||
|
Schedule(() =>
|
||||||
|
{
|
||||||
|
if (RequestedPlaying)
|
||||||
|
base.Play();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2020.930.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.1001.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.904.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.904.0" />
|
||||||
<PackageReference Include="Sentry" Version="2.1.6" />
|
<PackageReference Include="Sentry" Version="2.1.6" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.26.0" />
|
<PackageReference Include="SharpCompress" Version="0.26.0" />
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.930.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.1001.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.904.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.904.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
||||||
@ -80,11 +80,11 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2020.930.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.1001.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.26.0" />
|
<PackageReference Include="SharpCompress" Version="0.26.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2020.213.0" ExcludeAssets="all" />
|
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2020.923.0" ExcludeAssets="all" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user