mirror of
https://github.com/osukey/osukey.git
synced 2025-08-06 16:13:57 +09:00
Merge branch 'master' into beatmap-track-rework
This commit is contained in:
@ -9,7 +9,9 @@
|
|||||||
[](https://www.codefactor.io/repository/github/ppy/osu)
|
[](https://www.codefactor.io/repository/github/ppy/osu)
|
||||||
[](https://discord.gg/ppy)
|
[](https://discord.gg/ppy)
|
||||||
|
|
||||||
Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Commonly known by the codename *osu!lazer*. Pew pew.
|
A free-to-win rhythm game. Rhythm is just a *click* away!
|
||||||
|
|
||||||
|
The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Commonly known by the codename *osu!lazer*. Pew pew.
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
|
@ -52,6 +52,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.812.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.812.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.812.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.814.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>click the circles. to the beat.</Description>
|
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
||||||
<AssemblyName>osu!</AssemblyName>
|
<AssemblyName>osu!</AssemblyName>
|
||||||
<Title>osu!lazer</Title>
|
<Title>osu!lazer</Title>
|
||||||
<Product>osu!lazer</Product>
|
<Product>osu!lazer</Product>
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
<projectUrl>https://osu.ppy.sh/</projectUrl>
|
<projectUrl>https://osu.ppy.sh/</projectUrl>
|
||||||
<iconUrl>https://puu.sh/tYyXZ/9a01a5d1b0.ico</iconUrl>
|
<iconUrl>https://puu.sh/tYyXZ/9a01a5d1b0.ico</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<description>click the circles. to the beat.</description>
|
<description>A free-to-win rhythm game. Rhythm is just a *click* away!</description>
|
||||||
<summary>click the circles.</summary>
|
|
||||||
<releaseNotes>testing</releaseNotes>
|
<releaseNotes>testing</releaseNotes>
|
||||||
<copyright>Copyright (c) 2020 ppy Pty Ltd</copyright>
|
<copyright>Copyright (c) 2020 ppy Pty Ltd</copyright>
|
||||||
<language>en-AU</language>
|
<language>en-AU</language>
|
||||||
|
@ -83,8 +83,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
private SkinnableSound spinningSample;
|
private SkinnableSound spinningSample;
|
||||||
|
|
||||||
private const float minimum_volume = 0.0001f;
|
|
||||||
|
|
||||||
protected override void LoadSamples()
|
protected override void LoadSamples()
|
||||||
{
|
{
|
||||||
base.LoadSamples();
|
base.LoadSamples();
|
||||||
@ -101,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
AddInternal(spinningSample = new SkinnableSound(clone)
|
AddInternal(spinningSample = new SkinnableSound(clone)
|
||||||
{
|
{
|
||||||
Volume = { Value = minimum_volume },
|
Volume = { Value = 0 },
|
||||||
Looping = true,
|
Looping = true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -119,7 +117,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spinningSample?.VolumeTo(minimum_volume, 200).Finally(_ => spinningSample.Stop());
|
spinningSample?.VolumeTo(0, 200).Finally(_ => spinningSample.Stop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +272,21 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden);
|
AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSelectionResetOnVisibilityChange()
|
||||||
|
{
|
||||||
|
showOverlay();
|
||||||
|
AddStep("Select last button", () => InputManager.Key(Key.Up));
|
||||||
|
|
||||||
|
hideOverlay();
|
||||||
|
showOverlay();
|
||||||
|
|
||||||
|
AddAssert("No button selected",
|
||||||
|
() => pauseOverlay.Buttons.All(button => !button.Selected.Value));
|
||||||
|
}
|
||||||
|
|
||||||
private void showOverlay() => AddStep("Show overlay", () => pauseOverlay.Show());
|
private void showOverlay() => AddStep("Show overlay", () => pauseOverlay.Show());
|
||||||
|
private void hideOverlay() => AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||||
|
|
||||||
private DialogButton getButton(int index) => pauseOverlay.Buttons.Skip(index).First();
|
private DialogButton getButton(int index) => pauseOverlay.Buttons.Skip(index).First();
|
||||||
|
|
||||||
|
@ -67,19 +67,18 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
|
|
||||||
if (beatmapSet != null)
|
if (beatmapSet != null)
|
||||||
{
|
{
|
||||||
BeatmapSetCover cover;
|
Add(displayedCover = new DelayedLoadUnloadWrapper(() =>
|
||||||
|
{
|
||||||
Add(displayedCover = new DelayedLoadWrapper(
|
var cover = new BeatmapSetCover(beatmapSet, coverType)
|
||||||
cover = new BeatmapSetCover(beatmapSet, coverType)
|
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fill,
|
FillMode = FillMode.Fill,
|
||||||
})
|
};
|
||||||
);
|
|
||||||
|
|
||||||
cover.OnLoadComplete += d => d.FadeInFromZero(400, Easing.Out);
|
cover.OnLoadComplete += d => d.FadeInFromZero(400, Easing.Out);
|
||||||
|
return cover;
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
Sprite.Texture = Beatmap?.Background ?? textures.Get(fallbackTextureName);
|
Sprite.Texture = Beatmap?.Background ?? textures.Get(fallbackTextureName);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public abstract string Description { get; }
|
public abstract string Description { get; }
|
||||||
|
|
||||||
protected internal FillFlowContainer<DialogButton> InternalButtons;
|
protected ButtonContainer InternalButtons;
|
||||||
public IReadOnlyList<DialogButton> Buttons => InternalButtons;
|
public IReadOnlyList<DialogButton> Buttons => InternalButtons;
|
||||||
|
|
||||||
private FillFlowContainer retryCounterContainer;
|
private FillFlowContainer retryCounterContainer;
|
||||||
@ -59,7 +59,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
State.ValueChanged += s => selectionIndex = -1;
|
State.ValueChanged += s => InternalButtons.Deselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -114,7 +114,7 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InternalButtons = new FillFlowContainer<DialogButton>
|
InternalButtons = new ButtonContainer
|
||||||
{
|
{
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
@ -186,40 +186,16 @@ namespace osu.Game.Screens.Play
|
|||||||
InternalButtons.Add(button);
|
InternalButtons.Add(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int selectionIndex = -1;
|
|
||||||
|
|
||||||
private void setSelected(int value)
|
|
||||||
{
|
|
||||||
if (selectionIndex == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Deselect the previously-selected button
|
|
||||||
if (selectionIndex != -1)
|
|
||||||
InternalButtons[selectionIndex].Selected.Value = false;
|
|
||||||
|
|
||||||
selectionIndex = value;
|
|
||||||
|
|
||||||
// Select the newly-selected button
|
|
||||||
if (selectionIndex != -1)
|
|
||||||
InternalButtons[selectionIndex].Selected.Value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnPressed(GlobalAction action)
|
public bool OnPressed(GlobalAction action)
|
||||||
{
|
{
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case GlobalAction.SelectPrevious:
|
case GlobalAction.SelectPrevious:
|
||||||
if (selectionIndex == -1 || selectionIndex == 0)
|
InternalButtons.SelectPrevious();
|
||||||
setSelected(InternalButtons.Count - 1);
|
|
||||||
else
|
|
||||||
setSelected(selectionIndex - 1);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GlobalAction.SelectNext:
|
case GlobalAction.SelectNext:
|
||||||
if (selectionIndex == -1 || selectionIndex == InternalButtons.Count - 1)
|
InternalButtons.SelectNext();
|
||||||
setSelected(0);
|
|
||||||
else
|
|
||||||
setSelected(selectionIndex + 1);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GlobalAction.Back:
|
case GlobalAction.Back:
|
||||||
@ -241,9 +217,9 @@ namespace osu.Game.Screens.Play
|
|||||||
private void buttonSelectionChanged(DialogButton button, bool isSelected)
|
private void buttonSelectionChanged(DialogButton button, bool isSelected)
|
||||||
{
|
{
|
||||||
if (!isSelected)
|
if (!isSelected)
|
||||||
setSelected(-1);
|
InternalButtons.Deselect();
|
||||||
else
|
else
|
||||||
setSelected(InternalButtons.IndexOf(button));
|
InternalButtons.Select(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRetryCount()
|
private void updateRetryCount()
|
||||||
@ -277,6 +253,46 @@ namespace osu.Game.Screens.Play
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected class ButtonContainer : FillFlowContainer<DialogButton>
|
||||||
|
{
|
||||||
|
private int selectedIndex = -1;
|
||||||
|
|
||||||
|
private void setSelected(int value)
|
||||||
|
{
|
||||||
|
if (selectedIndex == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Deselect the previously-selected button
|
||||||
|
if (selectedIndex != -1)
|
||||||
|
this[selectedIndex].Selected.Value = false;
|
||||||
|
|
||||||
|
selectedIndex = value;
|
||||||
|
|
||||||
|
// Select the newly-selected button
|
||||||
|
if (selectedIndex != -1)
|
||||||
|
this[selectedIndex].Selected.Value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectNext()
|
||||||
|
{
|
||||||
|
if (selectedIndex == -1 || selectedIndex == Count - 1)
|
||||||
|
setSelected(0);
|
||||||
|
else
|
||||||
|
setSelected(selectedIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectPrevious()
|
||||||
|
{
|
||||||
|
if (selectedIndex == -1 || selectedIndex == 0)
|
||||||
|
setSelected(Count - 1);
|
||||||
|
else
|
||||||
|
setSelected(selectedIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Deselect() => setSelected(-1);
|
||||||
|
public void Select(DialogButton button) => setSelected(IndexOf(button));
|
||||||
|
}
|
||||||
|
|
||||||
private class Button : DialogButton
|
private class Button : DialogButton
|
||||||
{
|
{
|
||||||
// required to ensure keyboard navigation always starts from an extremity (unless the cursor is moved)
|
// required to ensure keyboard navigation always starts from an extremity (unless the cursor is moved)
|
||||||
|
@ -26,8 +26,6 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
protected override Action BackAction => () => InternalButtons.Children.First().Click();
|
protected override Action BackAction => () => InternalButtons.Children.First().Click();
|
||||||
|
|
||||||
private const float minimum_volume = 0.0001f;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
@ -38,10 +36,8 @@ namespace osu.Game.Screens.Play
|
|||||||
AddInternal(pauseLoop = new SkinnableSound(new SampleInfo("pause-loop"))
|
AddInternal(pauseLoop = new SkinnableSound(new SampleInfo("pause-loop"))
|
||||||
{
|
{
|
||||||
Looping = true,
|
Looping = true,
|
||||||
|
Volume = { Value = 0 }
|
||||||
});
|
});
|
||||||
|
|
||||||
// SkinnableSound only plays a sound if its aggregate volume is > 0, so the volume must be turned up before playing it
|
|
||||||
pauseLoop.VolumeTo(minimum_volume);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
@ -56,7 +52,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
base.PopOut();
|
base.PopOut();
|
||||||
|
|
||||||
pauseLoop.VolumeTo(minimum_volume, TRANSITION_DURATION, Easing.OutQuad).Finally(_ => pauseLoop.Stop());
|
pauseLoop.VolumeTo(0, TRANSITION_DURATION, Easing.OutQuad).Finally(_ => pauseLoop.Stop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,16 @@ namespace osu.Game.Skinning
|
|||||||
public override bool RemoveWhenNotAlive => false;
|
public override bool RemoveWhenNotAlive => false;
|
||||||
public override bool RemoveCompletedTransforms => false;
|
public override bool RemoveCompletedTransforms => false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to play the underlying sample when aggregate volume is zero.
|
||||||
|
/// Note that this is checked at the point of calling <see cref="Play"/>; changing the volume post-play will not begin playback.
|
||||||
|
/// Defaults to false unless <see cref="Looping"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Can serve as an optimisation if it is known ahead-of-time that this behaviour is allowed in a given use case.
|
||||||
|
/// </remarks>
|
||||||
|
protected bool PlayWhenZeroVolume => Looping;
|
||||||
|
|
||||||
private readonly AudioContainer<DrawableSample> samplesContainer;
|
private readonly AudioContainer<DrawableSample> samplesContainer;
|
||||||
|
|
||||||
public SkinnableSound(ISampleInfo hitSamples)
|
public SkinnableSound(ISampleInfo hitSamples)
|
||||||
@ -86,7 +96,7 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
samplesContainer.ForEach(c =>
|
samplesContainer.ForEach(c =>
|
||||||
{
|
{
|
||||||
if (c.AggregateVolume.Value > 0)
|
if (PlayWhenZeroVolume || c.AggregateVolume.Value > 0)
|
||||||
c.Play();
|
c.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.812.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.814.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.812.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.812.0" />
|
||||||
<PackageReference Include="Sentry" Version="2.1.5" />
|
<PackageReference Include="Sentry" Version="2.1.5" />
|
||||||
<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.812.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.814.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.812.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.812.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,7 +80,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.812.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.814.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" />
|
||||||
|
Reference in New Issue
Block a user