mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 15:33:05 +08:00
Merge branch 'master' into JSON-format-fix
This commit is contained in:
commit
56196885e6
@ -230,5 +230,23 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
|
|
||||||
SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(new SampleInfo { Name = "hitnormal" });
|
SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(new SampleInfo { Name = "hitnormal" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDecodeCustomHitObjectSamples()
|
||||||
|
{
|
||||||
|
var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false };
|
||||||
|
using (var resStream = Resource.OpenResource("custom-hitobject-samples.osu"))
|
||||||
|
using (var stream = new StreamReader(resStream))
|
||||||
|
{
|
||||||
|
var hitObjects = decoder.Decode(stream).HitObjects;
|
||||||
|
|
||||||
|
Assert.AreEqual("hit_1.wav", hitObjects[0].Samples[0].LookupNames.First());
|
||||||
|
Assert.AreEqual("hit_2.wav", hitObjects[1].Samples[0].LookupNames.First());
|
||||||
|
Assert.AreEqual("hitnormal2", getTestableSampleInfo(hitObjects[2]).Name);
|
||||||
|
Assert.AreEqual("hit_1.wav", hitObjects[3].Samples[0].LookupNames.First());
|
||||||
|
}
|
||||||
|
|
||||||
|
SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(new SampleInfo { Name = "hitnormal" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
osu.Game.Tests/Resources/custom-hitobject-samples.osu
Normal file
16
osu.Game.Tests/Resources/custom-hitobject-samples.osu
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
SampleSet: Normal
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
2170,468.75,4,1,0,40,1,0
|
||||||
|
2638,-100,4,1,1,40,0,0
|
||||||
|
3107,-100,4,1,2,40,0,0
|
||||||
|
3576,-100,4,1,0,40,0,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
255,193,2170,1,0,0:0:0:0:hit_1.wav
|
||||||
|
256,191,2638,5,0,0:0:0:0:hit_2.wav
|
||||||
|
255,193,3107,1,0,0:0:0:0:
|
||||||
|
256,191,3576,1,0,0:0:0:0:hit_1.wav
|
@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace osu.Game.Audio
|
namespace osu.Game.Audio
|
||||||
{
|
{
|
||||||
@ -33,6 +34,20 @@ namespace osu.Game.Audio
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int Volume;
|
public int Volume;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first).
|
||||||
|
/// </summary>
|
||||||
|
public virtual IEnumerable<string> LookupNames
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Namespace))
|
||||||
|
yield return $"{Namespace}/{Bank}-{Name}";
|
||||||
|
|
||||||
|
yield return $"{Bank}-{Name}"; // Without namespace as a fallback even when we have a namespace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public SampleInfo Clone() => (SampleInfo)MemberwiseClone();
|
public SampleInfo Clone() => (SampleInfo)MemberwiseClone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,8 @@ namespace osu.Game
|
|||||||
new VolumeControlReceptor
|
new VolumeControlReceptor
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
ActionRequested = action => volume.Adjust(action)
|
ActionRequested = action => volume.Adjust(action),
|
||||||
|
ScrollActionRequested = (action, amount, isPrecise) => volume.Adjust(action, amount, isPrecise),
|
||||||
},
|
},
|
||||||
mainContent = new Container { RelativeSizeAxes = Axes.Both },
|
mainContent = new Container { RelativeSizeAxes = Axes.Both },
|
||||||
overlayContent = new Container { RelativeSizeAxes = Axes.Both, Depth = float.MinValue },
|
overlayContent = new Container { RelativeSizeAxes = Axes.Both, Depth = float.MinValue },
|
||||||
|
@ -186,7 +186,7 @@ namespace osu.Game.Overlays.KeyBinding
|
|||||||
{
|
{
|
||||||
if (bindTarget.IsHovered)
|
if (bindTarget.IsHovered)
|
||||||
{
|
{
|
||||||
bindTarget.UpdateKeyCombination(new KeyCombination(KeyCombination.FromInputState(state).Keys.Append(state.Mouse.ScrollDelta.Y > 0 ? InputKey.MouseWheelUp : InputKey.MouseWheelDown)));
|
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state, state.Mouse.ScrollDelta));
|
||||||
finalise();
|
finalise();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,13 @@ using osu.Game.Input.Bindings;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Volume
|
namespace osu.Game.Overlays.Volume
|
||||||
{
|
{
|
||||||
public class VolumeControlReceptor : Container, IKeyBindingHandler<GlobalAction>, IHandleGlobalInput
|
public class VolumeControlReceptor : Container, IScrollBindingHandler<GlobalAction>, IHandleGlobalInput
|
||||||
{
|
{
|
||||||
public Func<GlobalAction, bool> ActionRequested;
|
public Func<GlobalAction, bool> ActionRequested;
|
||||||
|
public Func<GlobalAction, float, bool, bool> ScrollActionRequested;
|
||||||
|
|
||||||
public bool OnPressed(GlobalAction action) => ActionRequested?.Invoke(action) ?? false;
|
public bool OnPressed(GlobalAction action) => ActionRequested?.Invoke(action) ?? false;
|
||||||
|
public bool OnScroll(GlobalAction action, float amount, bool isPrecise) => ScrollActionRequested?.Invoke(action, amount, isPrecise) ?? false;
|
||||||
public bool OnReleased(GlobalAction action) => false;
|
public bool OnReleased(GlobalAction action) => false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,17 +12,15 @@ using osu.Framework.Graphics.Effects;
|
|||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Input.Bindings;
|
|
||||||
using osu.Framework.MathUtils;
|
using osu.Framework.MathUtils;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Input.Bindings;
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Volume
|
namespace osu.Game.Overlays.Volume
|
||||||
{
|
{
|
||||||
public class VolumeMeter : Container, IKeyBindingHandler<GlobalAction>
|
public class VolumeMeter : Container
|
||||||
{
|
{
|
||||||
private CircularProgress volumeCircle;
|
private CircularProgress volumeCircle;
|
||||||
private CircularProgress volumeCircleGlow;
|
private CircularProgress volumeCircleGlow;
|
||||||
@ -226,59 +224,27 @@ namespace osu.Game.Overlays.Volume
|
|||||||
|
|
||||||
private const float adjust_step = 0.05f;
|
private const float adjust_step = 0.05f;
|
||||||
|
|
||||||
public void Increase() => adjust(1);
|
public void Increase(double amount = 1, bool isPrecise = false) => adjust(amount, isPrecise);
|
||||||
public void Decrease() => adjust(-1);
|
public void Decrease(double amount = 1, bool isPrecise = false) => adjust(-amount, isPrecise);
|
||||||
|
|
||||||
private void adjust(int direction)
|
|
||||||
{
|
|
||||||
float amount = adjust_step * direction;
|
|
||||||
|
|
||||||
// handle the case where the OnPressed action was actually a mouse wheel.
|
|
||||||
// this allows for precise wheel handling.
|
|
||||||
var state = GetContainingInputManager().CurrentState;
|
|
||||||
if (state.Mouse?.ScrollDelta.Y != 0)
|
|
||||||
{
|
|
||||||
OnScroll(state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Volume += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnPressed(GlobalAction action)
|
|
||||||
{
|
|
||||||
if (!IsHovered) return false;
|
|
||||||
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case GlobalAction.DecreaseVolume:
|
|
||||||
Decrease();
|
|
||||||
return true;
|
|
||||||
case GlobalAction.IncreaseVolume:
|
|
||||||
Increase();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// because volume precision is set to 0.01, this local is required to keep track of more precise adjustments and only apply when possible.
|
// because volume precision is set to 0.01, this local is required to keep track of more precise adjustments and only apply when possible.
|
||||||
private double scrollAmount;
|
private double adjustAccumulator;
|
||||||
|
|
||||||
|
private void adjust(double delta, bool isPrecise)
|
||||||
|
{
|
||||||
|
adjustAccumulator += delta * adjust_step * (isPrecise ? 0.1 : 1);
|
||||||
|
if (Math.Abs(adjustAccumulator) < Bindable.Precision)
|
||||||
|
return;
|
||||||
|
Volume += adjustAccumulator;
|
||||||
|
adjustAccumulator = 0;
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool OnScroll(InputState state)
|
protected override bool OnScroll(InputState state)
|
||||||
{
|
{
|
||||||
scrollAmount += adjust_step * state.Mouse.ScrollDelta.Y * (state.Mouse.HasPreciseScroll ? 0.1f : 1);
|
adjust(state.Mouse.ScrollDelta.Y, state.Mouse.HasPreciseScroll);
|
||||||
|
|
||||||
if (Math.Abs(scrollAmount) < Bindable.Precision)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Volume += scrollAmount;
|
|
||||||
scrollAmount = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnReleased(GlobalAction action) => false;
|
|
||||||
|
|
||||||
private const float transition_length = 500;
|
private const float transition_length = 500;
|
||||||
|
|
||||||
protected override bool OnHover(InputState state)
|
protected override bool OnHover(InputState state)
|
||||||
|
@ -93,7 +93,7 @@ namespace osu.Game.Overlays
|
|||||||
muteButton.Current.ValueChanged += _ => Show();
|
muteButton.Current.ValueChanged += _ => Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Adjust(GlobalAction action)
|
public bool Adjust(GlobalAction action, float amount = 1, bool isPrecise = false)
|
||||||
{
|
{
|
||||||
if (!IsLoaded) return false;
|
if (!IsLoaded) return false;
|
||||||
|
|
||||||
@ -103,13 +103,13 @@ namespace osu.Game.Overlays
|
|||||||
if (State == Visibility.Hidden)
|
if (State == Visibility.Hidden)
|
||||||
Show();
|
Show();
|
||||||
else
|
else
|
||||||
volumeMeterMaster.Decrease();
|
volumeMeterMaster.Decrease(amount, isPrecise);
|
||||||
return true;
|
return true;
|
||||||
case GlobalAction.IncreaseVolume:
|
case GlobalAction.IncreaseVolume:
|
||||||
if (State == Visibility.Hidden)
|
if (State == Visibility.Hidden)
|
||||||
Show();
|
Show();
|
||||||
else
|
else
|
||||||
volumeMeterMaster.Increase();
|
volumeMeterMaster.Increase(amount, isPrecise);
|
||||||
return true;
|
return true;
|
||||||
case GlobalAction.ToggleMute:
|
case GlobalAction.ToggleMute:
|
||||||
Show();
|
Show();
|
||||||
|
@ -6,6 +6,7 @@ using osu.Game.Rulesets.Objects.Types;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using osu.Game.Beatmaps.Formats;
|
using osu.Game.Beatmaps.Formats;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -196,9 +197,6 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
var bank = (LegacyBeatmapDecoder.LegacySampleBank)Convert.ToInt32(split[0]);
|
var bank = (LegacyBeatmapDecoder.LegacySampleBank)Convert.ToInt32(split[0]);
|
||||||
var addbank = (LegacyBeatmapDecoder.LegacySampleBank)Convert.ToInt32(split[1]);
|
var addbank = (LegacyBeatmapDecoder.LegacySampleBank)Convert.ToInt32(split[1]);
|
||||||
|
|
||||||
// Let's not implement this for now, because this doesn't fit nicely into the bank structure
|
|
||||||
//string sampleFile = split2.Length > 4 ? split2[4] : string.Empty;
|
|
||||||
|
|
||||||
string stringBank = bank.ToString().ToLower();
|
string stringBank = bank.ToString().ToLower();
|
||||||
if (stringBank == @"none")
|
if (stringBank == @"none")
|
||||||
stringBank = null;
|
stringBank = null;
|
||||||
@ -211,6 +209,8 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
if (split.Length > 3)
|
if (split.Length > 3)
|
||||||
bankInfo.Volume = int.Parse(split[3]);
|
bankInfo.Volume = int.Parse(split[3]);
|
||||||
|
|
||||||
|
bankInfo.Filename = split.Length > 4 ? split[4] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -252,6 +252,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
private List<SampleInfo> convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
|
private List<SampleInfo> convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
|
||||||
{
|
{
|
||||||
|
// Todo: This should return the normal SampleInfos if the specified sample file isn't found, but that's a pretty edge-case scenario
|
||||||
|
if (!string.IsNullOrEmpty(bankInfo.Filename))
|
||||||
|
return new List<SampleInfo> { new FileSampleInfo { Filename = bankInfo.Filename } };
|
||||||
|
|
||||||
var soundTypes = new List<SampleInfo>
|
var soundTypes = new List<SampleInfo>
|
||||||
{
|
{
|
||||||
new SampleInfo
|
new SampleInfo
|
||||||
@ -297,14 +301,24 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
private class SampleBankInfo
|
private class SampleBankInfo
|
||||||
{
|
{
|
||||||
|
public string Filename;
|
||||||
|
|
||||||
public string Normal;
|
public string Normal;
|
||||||
public string Add;
|
public string Add;
|
||||||
public int Volume;
|
public int Volume;
|
||||||
|
|
||||||
public SampleBankInfo Clone()
|
public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileSampleInfo : SampleInfo
|
||||||
|
{
|
||||||
|
public string Filename;
|
||||||
|
|
||||||
|
public override IEnumerable<string> LookupNames => new[]
|
||||||
{
|
{
|
||||||
return (SampleBankInfo)MemberwiseClone();
|
Filename,
|
||||||
}
|
Path.ChangeExtension(Filename, null)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
|
@ -44,19 +44,17 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
private SampleChannel loadChannel(SampleInfo info, Func<string, SampleChannel> getSampleFunction)
|
private SampleChannel loadChannel(SampleInfo info, Func<string, SampleChannel> getSampleFunction)
|
||||||
{
|
{
|
||||||
SampleChannel ch = null;
|
foreach (var lookup in info.LookupNames)
|
||||||
|
{
|
||||||
|
var ch = getSampleFunction($"Gameplay/{lookup}");
|
||||||
|
if (ch == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (info.Namespace != null)
|
|
||||||
ch = getSampleFunction($"Gameplay/{info.Namespace}/{info.Bank}-{info.Name}");
|
|
||||||
|
|
||||||
// try without namespace as a fallback.
|
|
||||||
if (ch == null)
|
|
||||||
ch = getSampleFunction($"Gameplay/{info.Bank}-{info.Name}");
|
|
||||||
|
|
||||||
if (ch != null)
|
|
||||||
ch.Volume.Value = info.Volume / 100.0;
|
ch.Volume.Value = info.Volume / 100.0;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
return ch;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.1.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.1.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2018.629.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2018.705.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.17.1" />
|
<PackageReference Include="SharpCompress" Version="0.17.1" />
|
||||||
<PackageReference Include="NUnit" Version="3.10.1" />
|
<PackageReference Include="NUnit" Version="3.10.1" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
|
||||||
|
Loading…
Reference in New Issue
Block a user