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

Merge branch 'master' into fix-double-comments

This commit is contained in:
Dan Balasescu 2020-06-15 15:21:34 +09:00 committed by GitHub
commit 9b31f8889b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 168 additions and 44 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -1,6 +1,12 @@
[General] [General]
Version: 2.4 Version: 2.5
[Mania] [Mania]
Keys: 4 Keys: 4
ColumnLineWidth: 3,1,3,1,1 ColumnLineWidth: 3,1,3,1,1
Hit0: mania/hit0
Hit50: mania/hit50
Hit100: mania/hit100
Hit200: mania/hit200
Hit300: mania/hit300
Hit300g: mania/hit300g

View File

@ -6,6 +6,7 @@ using System.Linq;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -16,14 +17,19 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
{ {
public TestSceneDrawableJudgement() public TestSceneDrawableJudgement()
{ {
var hitWindows = new ManiaHitWindows();
foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Skip(1)) foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Skip(1))
{ {
AddStep("Show " + result.GetDescription(), () => SetContents(() => if (hitWindows.IsHitResultAllowed(result))
new DrawableManiaJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) {
{ AddStep("Show " + result.GetDescription(), () => SetContents(() =>
Anchor = Anchor.Centre, new DrawableManiaJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null)
Origin = Anchor.Centre, {
})); Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}));
}
} }
} }
} }

View File

@ -11,6 +11,7 @@ using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Skinning; using osu.Game.Skinning;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Mania.Skinning namespace osu.Game.Rulesets.Mania.Skinning
{ {
@ -19,6 +20,36 @@ namespace osu.Game.Rulesets.Mania.Skinning
private readonly ISkin source; private readonly ISkin source;
private readonly ManiaBeatmap beatmap; private readonly ManiaBeatmap beatmap;
/// <summary>
/// Mapping of <see cref="HitResult"/> to their corresponding
/// <see cref="LegacyManiaSkinConfigurationLookups"/> value.
/// </summary>
private static readonly IReadOnlyDictionary<HitResult, LegacyManiaSkinConfigurationLookups> hitresult_mapping
= new Dictionary<HitResult, LegacyManiaSkinConfigurationLookups>
{
{ HitResult.Perfect, LegacyManiaSkinConfigurationLookups.Hit300g },
{ HitResult.Great, LegacyManiaSkinConfigurationLookups.Hit300 },
{ HitResult.Good, LegacyManiaSkinConfigurationLookups.Hit200 },
{ HitResult.Ok, LegacyManiaSkinConfigurationLookups.Hit100 },
{ HitResult.Meh, LegacyManiaSkinConfigurationLookups.Hit50 },
{ HitResult.Miss, LegacyManiaSkinConfigurationLookups.Hit0 }
};
/// <summary>
/// Mapping of <see cref="HitResult"/> to their corresponding
/// default filenames.
/// </summary>
private static readonly IReadOnlyDictionary<HitResult, string> default_hitresult_skin_filenames
= new Dictionary<HitResult, string>
{
{ HitResult.Perfect, "mania-hit300g" },
{ HitResult.Great, "mania-hit300" },
{ HitResult.Good, "mania-hit200" },
{ HitResult.Ok, "mania-hit100" },
{ HitResult.Meh, "mania-hit50" },
{ HitResult.Miss, "mania-hit0" }
};
private Lazy<bool> isLegacySkin; private Lazy<bool> isLegacySkin;
/// <summary> /// <summary>
@ -50,7 +81,7 @@ namespace osu.Game.Rulesets.Mania.Skinning
switch (component) switch (component)
{ {
case GameplaySkinComponent<HitResult> resultComponent: case GameplaySkinComponent<HitResult> resultComponent:
return getResult(resultComponent); return getResult(resultComponent.Component);
case ManiaSkinComponent maniaComponent: case ManiaSkinComponent maniaComponent:
if (!isLegacySkin.Value || !hasKeyTexture.Value) if (!isLegacySkin.Value || !hasKeyTexture.Value)
@ -95,30 +126,13 @@ namespace osu.Game.Rulesets.Mania.Skinning
return null; return null;
} }
private Drawable getResult(GameplaySkinComponent<HitResult> resultComponent) private Drawable getResult(HitResult result)
{ {
switch (resultComponent.Component) string filename = GetConfig<ManiaSkinConfigurationLookup, string>(
{ new ManiaSkinConfigurationLookup(hitresult_mapping[result])
case HitResult.Miss: )?.Value ?? default_hitresult_skin_filenames[result];
return this.GetAnimation("mania-hit0", true, true);
case HitResult.Meh: return this.GetAnimation(filename, true, true);
return this.GetAnimation("mania-hit50", true, true);
case HitResult.Ok:
return this.GetAnimation("mania-hit100", true, true);
case HitResult.Good:
return this.GetAnimation("mania-hit200", true, true);
case HitResult.Great:
return this.GetAnimation("mania-hit300", true, true);
case HitResult.Perfect:
return this.GetAnimation("mania-hit300g", true, true);
}
return null;
} }
public Texture GetTexture(string componentName) => source.GetTexture(componentName); public Texture GetTexture(string componentName) => source.GetTexture(componentName);

View File

@ -0,0 +1,25 @@
// 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 NUnit.Framework;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
namespace osu.Game.Tests.Gameplay
{
public class TestSceneGameplayClockContainer : OsuTestScene
{
[Test]
public void TestStartThenElapsedTime()
{
GameplayClockContainer gcc = null;
AddStep("create container", () => Add(gcc = new GameplayClockContainer(CreateWorkingBeatmap(new OsuRuleset().RulesetInfo), Array.Empty<Mod>(), 0)));
AddStep("start track", () => gcc.Start());
AddUntilStep("elapsed greater than zero", () => gcc.GameplayClock.ElapsedFrameTime > 0);
}
}
}

View File

@ -1,6 +1,7 @@
// 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 System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -10,7 +11,12 @@ using osu.Framework.Audio.Sample;
using osu.Framework.IO.Stores; using osu.Framework.IO.Stores;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Play;
using osu.Game.Skinning; using osu.Game.Skinning;
using osu.Game.Storyboards;
using osu.Game.Storyboards.Drawables;
using osu.Game.Tests.Resources; using osu.Game.Tests.Resources;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
@ -43,6 +49,27 @@ namespace osu.Game.Tests.Gameplay
AddAssert("sample is non-null", () => channel != null); AddAssert("sample is non-null", () => channel != null);
} }
[Test]
public void TestSamplePlaybackAtZero()
{
GameplayClockContainer gameplayContainer = null;
DrawableStoryboardSample sample = null;
AddStep("create container", () =>
{
Add(gameplayContainer = new GameplayClockContainer(CreateWorkingBeatmap(new OsuRuleset().RulesetInfo), Array.Empty<Mod>(), 0));
gameplayContainer.Add(sample = new DrawableStoryboardSample(new StoryboardSampleInfo(string.Empty, 0, 1))
{
Clock = gameplayContainer.GameplayClock
});
});
AddStep("start time", () => gameplayContainer.Start());
AddUntilStep("sample playback succeeded", () => sample.LifetimeEnd < double.MaxValue);
}
private class TestSkin : LegacySkin private class TestSkin : LegacySkin
{ {
public TestSkin(string resourceName, AudioManager audioManager) public TestSkin(string resourceName, AudioManager audioManager)

View File

@ -26,6 +26,9 @@ namespace osu.Game.Rulesets.Mods
[SettingSource("Final rate", "The final speed to ramp to")] [SettingSource("Final rate", "The final speed to ramp to")]
public abstract BindableNumber<double> FinalRate { get; } public abstract BindableNumber<double> FinalRate { get; }
[SettingSource("Adjust pitch", "Should pitch be adjusted with speed")]
public abstract BindableBool AdjustPitch { get; }
public override string SettingDescription => $"{InitialRate.Value:N2}x to {FinalRate.Value:N2}x"; public override string SettingDescription => $"{InitialRate.Value:N2}x to {FinalRate.Value:N2}x";
private double finalRateTime; private double finalRateTime;
@ -43,15 +46,16 @@ namespace osu.Game.Rulesets.Mods
protected ModTimeRamp() protected ModTimeRamp()
{ {
// for preview purpose at song select. eventually we'll want to be able to update every frame. // for preview purpose at song select. eventually we'll want to be able to update every frame.
FinalRate.BindValueChanged(val => applyAdjustment(1), true); FinalRate.BindValueChanged(val => applyRateAdjustment(1), true);
AdjustPitch.BindValueChanged(applyPitchAdjustment);
} }
public void ApplyToTrack(Track track) public void ApplyToTrack(Track track)
{ {
this.track = track; this.track = track;
track.AddAdjustment(AdjustableProperty.Frequency, SpeedChange);
FinalRate.TriggerChange(); FinalRate.TriggerChange();
AdjustPitch.TriggerChange();
} }
public virtual void ApplyToBeatmap(IBeatmap beatmap) public virtual void ApplyToBeatmap(IBeatmap beatmap)
@ -66,14 +70,25 @@ namespace osu.Game.Rulesets.Mods
public virtual void Update(Playfield playfield) public virtual void Update(Playfield playfield)
{ {
applyAdjustment((track.CurrentTime - beginRampTime) / finalRateTime); applyRateAdjustment((track.CurrentTime - beginRampTime) / finalRateTime);
} }
/// <summary> /// <summary>
/// Adjust the rate along the specified ramp /// Adjust the rate along the specified ramp
/// </summary> /// </summary>
/// <param name="amount">The amount of adjustment to apply (from 0..1).</param> /// <param name="amount">The amount of adjustment to apply (from 0..1).</param>
private void applyAdjustment(double amount) => private void applyRateAdjustment(double amount) =>
SpeedChange.Value = InitialRate.Value + (FinalRate.Value - InitialRate.Value) * Math.Clamp(amount, 0, 1); SpeedChange.Value = InitialRate.Value + (FinalRate.Value - InitialRate.Value) * Math.Clamp(amount, 0, 1);
private void applyPitchAdjustment(ValueChangedEvent<bool> adjustPitchSetting)
{
// remove existing old adjustment
track.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange);
track.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange);
}
private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue)
=> adjustPitchSettingValue ? AdjustableProperty.Frequency : AdjustableProperty.Tempo;
} }
} }

View File

@ -37,6 +37,13 @@ namespace osu.Game.Rulesets.Mods
Precision = 0.01, Precision = 0.01,
}; };
[SettingSource("Adjust pitch", "Should pitch be adjusted with speed")]
public override BindableBool AdjustPitch { get; } = new BindableBool
{
Default = true,
Value = true
};
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray();
} }
} }

View File

@ -37,6 +37,13 @@ namespace osu.Game.Rulesets.Mods
Precision = 0.01, Precision = 0.01,
}; };
[SettingSource("Adjust pitch", "Should pitch be adjusted with speed")]
public override BindableBool AdjustPitch { get; } = new BindableBool
{
Default = true,
Value = true
};
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray();
} }
} }

View File

@ -18,6 +18,8 @@ namespace osu.Game.Scoring
protected override IQueryable<ScoreInfo> AddIncludesForConsumption(IQueryable<ScoreInfo> query) protected override IQueryable<ScoreInfo> AddIncludesForConsumption(IQueryable<ScoreInfo> query)
=> base.AddIncludesForConsumption(query) => base.AddIncludesForConsumption(query)
.Include(s => s.Beatmap) .Include(s => s.Beatmap)
.Include(s => s.Beatmap).ThenInclude(b => b.Metadata)
.Include(s => s.Beatmap).ThenInclude(b => b.BeatmapSet).ThenInclude(s => s.Metadata)
.Include(s => s.Ruleset); .Include(s => s.Ruleset);
} }
} }

View File

@ -44,8 +44,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
private readonly BindableList<HitObject> selectedHitObjects = new BindableList<HitObject>(); private readonly BindableList<HitObject> selectedHitObjects = new BindableList<HitObject>();
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
[Resolved(canBeNull: true)] [Resolved(canBeNull: true)]
private IPositionSnapProvider snapProvider { get; set; } private IPositionSnapProvider snapProvider { get; set; }

View File

@ -11,6 +11,7 @@ using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
namespace osu.Game.Screens.Edit.Compose.Components namespace osu.Game.Screens.Edit.Compose.Components
{ {
@ -26,6 +27,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
private readonly Container<PlacementBlueprint> placementBlueprintContainer; private readonly Container<PlacementBlueprint> placementBlueprintContainer;
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
private InputManager inputManager; private InputManager inputManager;
private readonly IEnumerable<DrawableHitObject> drawableHitObjects; private readonly IEnumerable<DrawableHitObject> drawableHitObjects;

View File

@ -251,8 +251,9 @@ namespace osu.Game.Screens.Play
private class HardwareCorrectionOffsetClock : FramedOffsetClock private class HardwareCorrectionOffsetClock : FramedOffsetClock
{ {
// we always want to apply the same real-time offset, so it should be adjusted by the playback rate to achieve this. // we always want to apply the same real-time offset, so it should be adjusted by the difference in playback rate (from realtime) to achieve this.
public override double CurrentTime => SourceTime + Offset * Rate; // base implementation already adds offset at 1.0 rate, so we only add the difference from that here.
public override double CurrentTime => base.CurrentTime + Offset * (Rate - 1);
public HardwareCorrectionOffsetClock(IClock source, bool processSource = true) public HardwareCorrectionOffsetClock(IClock source, bool processSource = true)
: base(source, processSource) : base(source, processSource)

View File

@ -43,6 +43,12 @@ namespace osu.Game.Skinning
MinimumColumnWidth, MinimumColumnWidth,
LeftStageImage, LeftStageImage,
RightStageImage, RightStageImage,
BottomStageImage BottomStageImage,
Hit300g,
Hit300,
Hit200,
Hit100,
Hit50,
Hit0,
} }
} }

View File

@ -111,11 +111,10 @@ namespace osu.Game.Skinning
HandleColours(currentConfig, line); HandleColours(currentConfig, line);
break; break;
// Custom sprite paths
case string _ when pair.Key.StartsWith("NoteImage"): case string _ when pair.Key.StartsWith("NoteImage"):
currentConfig.ImageLookups[pair.Key] = pair.Value;
break;
case string _ when pair.Key.StartsWith("KeyImage"): case string _ when pair.Key.StartsWith("KeyImage"):
case string _ when pair.Key.StartsWith("Hit"):
currentConfig.ImageLookups[pair.Key] = pair.Value; currentConfig.ImageLookups[pair.Key] = pair.Value;
break; break;
} }

View File

@ -257,6 +257,14 @@ namespace osu.Game.Skinning
case LegacyManiaSkinConfigurationLookups.RightLineWidth: case LegacyManiaSkinConfigurationLookups.RightLineWidth:
Debug.Assert(maniaLookup.TargetColumn != null); Debug.Assert(maniaLookup.TargetColumn != null);
return SkinUtils.As<TValue>(new Bindable<float>(existing.ColumnLineWidth[maniaLookup.TargetColumn.Value + 1])); return SkinUtils.As<TValue>(new Bindable<float>(existing.ColumnLineWidth[maniaLookup.TargetColumn.Value + 1]));
case LegacyManiaSkinConfigurationLookups.Hit0:
case LegacyManiaSkinConfigurationLookups.Hit50:
case LegacyManiaSkinConfigurationLookups.Hit100:
case LegacyManiaSkinConfigurationLookups.Hit200:
case LegacyManiaSkinConfigurationLookups.Hit300:
case LegacyManiaSkinConfigurationLookups.Hit300g:
return SkinUtils.As<TValue>(getManiaImage(existing, maniaLookup.Lookup.ToString()));
} }
return null; return null;

View File

@ -51,7 +51,7 @@ namespace osu.Game.Storyboards.Drawables
LifetimeStart = sampleInfo.StartTime; LifetimeStart = sampleInfo.StartTime;
LifetimeEnd = double.MaxValue; LifetimeEnd = double.MaxValue;
} }
else if (Time.Current - Time.Elapsed < sampleInfo.StartTime) else if (Time.Current - Time.Elapsed <= sampleInfo.StartTime)
{ {
// We've passed the start time of the sample. We only play the sample if we're within an allowable range // We've passed the start time of the sample. We only play the sample if we're within an allowable range
// from the sample's start, to reduce layering if we've been fast-forwarded far into the future // from the sample's start, to reduce layering if we've been fast-forwarded far into the future