mirror of
https://github.com/ppy/osu
synced 2025-01-31 10:22:02 +00:00
Merge branch 'master' into fix-click-through-timeline
This commit is contained in:
commit
b2d3aa982d
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
@ -4,6 +4,7 @@ Version: 2.5
|
||||
[Mania]
|
||||
Keys: 4
|
||||
ColumnLineWidth: 3,1,3,1,1
|
||||
LightFramePerSecond: 15
|
||||
// some skins found in the wild had configuration keys where the @2x suffix was included in the values.
|
||||
// the expected compatibility behaviour is that the presence of the @2x suffix shouldn't change anything
|
||||
// if @2x assets are present.
|
||||
@ -15,5 +16,6 @@ Hit300: mania/hit300@2x
|
||||
Hit300g: mania/hit300g@2x
|
||||
StageLeft: mania/stage-left
|
||||
StageRight: mania/stage-right
|
||||
StageLight: mania/stage-light
|
||||
NoteImage0L: LongNoteTailWang
|
||||
NoteImage1L: LongNoteTailWang
|
||||
|
@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
isHitting.BindTo(holdNote.IsHitting);
|
||||
|
||||
bodySprite = skin.GetAnimation(imageName, wrapMode, wrapMode, true, true).With(d =>
|
||||
bodySprite = skin.GetAnimation(imageName, wrapMode, wrapMode, true, true, frameLength: 30).With(d =>
|
||||
{
|
||||
if (d == null)
|
||||
return;
|
||||
|
@ -5,7 +5,6 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Container lightContainer = null!;
|
||||
private Sprite light = null!;
|
||||
private Drawable light = null!;
|
||||
|
||||
public LegacyColumnBackground()
|
||||
{
|
||||
@ -39,6 +38,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
Color4 lightColour = GetColumnSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.ColumnLightColour)?.Value
|
||||
?? Color4.White;
|
||||
|
||||
int lightFramePerSecond = skin.GetManiaSkinConfig<int>(LegacyManiaSkinConfigurationLookups.LightFramePerSecond)?.Value ?? 60;
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
lightContainer = new Container
|
||||
@ -46,16 +47,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
Origin = Anchor.BottomCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Bottom = lightPosition },
|
||||
Child = light = new Sprite
|
||||
Child = light = skin.GetAnimation(lightImage, true, true, frameLength: 1000d / lightFramePerSecond)?.With(l =>
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Colour = LegacyColourCompatibility.DisallowZeroAlpha(lightColour),
|
||||
Texture = skin.GetTexture(lightImage),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 1,
|
||||
Alpha = 0
|
||||
}
|
||||
l.Anchor = Anchor.BottomCentre;
|
||||
l.Origin = Anchor.BottomCentre;
|
||||
l.Colour = LegacyColourCompatibility.DisallowZeroAlpha(lightColour);
|
||||
l.RelativeSizeAxes = Axes.X;
|
||||
l.Width = 1;
|
||||
l.Alpha = 0;
|
||||
}) ?? Empty(),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
string filename = this.GetManiaSkinConfig<string>(hit_result_mapping[result])?.Value
|
||||
?? default_hit_result_skin_filenames[result];
|
||||
|
||||
var animation = this.GetAnimation(filename, true, true);
|
||||
var animation = this.GetAnimation(filename, true, true, frameLength: 1000 / 20d);
|
||||
return animation == null ? null : new LegacyManiaJudgementPiece(result, animation);
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
Child = piece = new TestLegacyMainCirclePiece(priorityLookup),
|
||||
};
|
||||
|
||||
var sprites = this.ChildrenOfType<Sprite>().Where(s => !string.IsNullOrEmpty(s.Texture.AssetName)).DistinctBy(s => s.Texture.AssetName).ToArray();
|
||||
var sprites = this.ChildrenOfType<Sprite>().Where(s => !string.IsNullOrEmpty(s.Texture?.AssetName)).DistinctBy(s => s.Texture.AssetName).ToArray();
|
||||
Debug.Assert(sprites.Length <= 2);
|
||||
});
|
||||
|
||||
@ -103,8 +103,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
private partial class TestLegacyMainCirclePiece : LegacyMainCirclePiece
|
||||
{
|
||||
public new Sprite? CircleSprite => base.CircleSprite.ChildrenOfType<Sprite>().DistinctBy(s => s.Texture.AssetName).SingleOrDefault();
|
||||
public new Sprite? OverlaySprite => base.OverlaySprite.ChildrenOfType<Sprite>().DistinctBy(s => s.Texture.AssetName).SingleOrDefault();
|
||||
public new Sprite? CircleSprite => base.CircleSprite.ChildrenOfType<Sprite>().Where(s => !string.IsNullOrEmpty(s.Texture?.AssetName)).DistinctBy(s => s.Texture.AssetName).SingleOrDefault();
|
||||
public new Sprite? OverlaySprite => base.OverlaySprite.ChildrenOfType<Sprite>().Where(s => !string.IsNullOrEmpty(s.Texture?.AssetName)).DistinctBy(s => s.Texture.AssetName).SingleOrDefault();
|
||||
|
||||
public TestLegacyMainCirclePiece(string? priorityLookupPrefix)
|
||||
: base(priorityLookupPrefix, false)
|
||||
|
@ -14,6 +14,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
@ -62,12 +63,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
// otherwise fall back to the default prefix "hitcircle".
|
||||
string circleName = (priorityLookupPrefix != null && skin.GetTexture(priorityLookupPrefix) != null) ? priorityLookupPrefix : @"hitcircle";
|
||||
|
||||
Vector2 maxSize = OsuHitObject.OBJECT_DIMENSIONS * 2;
|
||||
|
||||
// at this point, any further texture fetches should be correctly using the priority source if the base texture was retrieved using it.
|
||||
// the conditional above handles the case where a sliderendcircle.png is retrieved from the skin, but sliderendcircleoverlay.png doesn't exist.
|
||||
// expected behaviour in this scenario is not showing the overlay, rather than using hitcircleoverlay.png.
|
||||
InternalChildren = new[]
|
||||
{
|
||||
CircleSprite = new LegacyKiaiFlashingDrawable(() => new Sprite { Texture = skin.GetTexture(circleName)?.WithMaximumSize(OsuHitObject.OBJECT_DIMENSIONS * 2) })
|
||||
CircleSprite = new LegacyKiaiFlashingDrawable(() => new Sprite { Texture = skin.GetTexture(circleName)?.WithMaximumSize(maxSize) })
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -76,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Child = OverlaySprite = new LegacyKiaiFlashingDrawable(() => skin.GetAnimation(@$"{circleName}overlay", true, true, frameLength: 1000 / 2d, maxSize: OsuHitObject.OBJECT_DIMENSIONS * 2))
|
||||
Child = OverlaySprite = new LegacyKiaiFlashingDrawable(() => new Sprite { Texture = skin.GetTexture(@$"{circleName}overlay")?.WithMaximumSize(maxSize) })
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
@ -8,6 +8,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
@ -41,11 +42,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
|
||||
var skin = skinSource.FindProvider(s => s.GetTexture(lookupName) != null);
|
||||
|
||||
InternalChild = arrow = (skin?.GetAnimation(lookupName, true, true, maxSize: OsuHitObject.OBJECT_DIMENSIONS * 2) ?? Empty()).With(d =>
|
||||
InternalChild = arrow = new Sprite
|
||||
{
|
||||
d.Anchor = Anchor.Centre;
|
||||
d.Origin = Anchor.Centre;
|
||||
});
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = skin?.GetTexture(lookupName)?.WithMaximumSize(maxSize: OsuHitObject.OBJECT_DIMENSIONS * 2),
|
||||
};
|
||||
|
||||
textureIsDefaultSkin = skin is ISkinTransformer transformer && transformer.Skin is DefaultLegacySkin;
|
||||
|
||||
|
@ -48,40 +48,45 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, DrawableHitObject drawableHitObject, IBeatSyncProvider? beatSyncProvider)
|
||||
{
|
||||
Drawable? getDrawableFor(string lookup)
|
||||
Drawable? getDrawableFor(string lookup, bool animatable)
|
||||
{
|
||||
const string normal_hit = "taikohit";
|
||||
const string big_hit = "taikobig";
|
||||
|
||||
string prefix = ((drawableHitObject.HitObject as TaikoStrongableHitObject)?.IsStrong ?? false) ? big_hit : normal_hit;
|
||||
|
||||
return skin.GetAnimation($"{prefix}{lookup}", true, false, maxSize: max_circle_sprite_size) ??
|
||||
return skin.GetAnimation($"{prefix}{lookup}", animatable, false, maxSize: max_circle_sprite_size) ??
|
||||
// fallback to regular size if "big" version doesn't exist.
|
||||
skin.GetAnimation($"{normal_hit}{lookup}", true, false, maxSize: max_circle_sprite_size);
|
||||
skin.GetAnimation($"{normal_hit}{lookup}", animatable, false, maxSize: max_circle_sprite_size);
|
||||
}
|
||||
|
||||
// backgroundLayer is guaranteed to exist due to the pre-check in TaikoLegacySkinTransformer.
|
||||
AddInternal(backgroundLayer = new LegacyKiaiFlashingDrawable(() => getDrawableFor("circle")));
|
||||
AddInternal(backgroundLayer = new LegacyKiaiFlashingDrawable(() => getDrawableFor("circle", false))
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
});
|
||||
|
||||
foregroundLayer = getDrawableFor("circleoverlay", true);
|
||||
|
||||
foregroundLayer = getDrawableFor("circleoverlay");
|
||||
if (foregroundLayer != null)
|
||||
{
|
||||
foregroundLayer.Anchor = Anchor.Centre;
|
||||
foregroundLayer.Origin = Anchor.Centre;
|
||||
|
||||
// Animations in taiko skins are used in a custom way (>150 combo and animating in time with beat).
|
||||
// For now just stop at first frame for sanity.
|
||||
if (foregroundLayer is IFramedAnimation animatedForegroundLayer)
|
||||
animatedForegroundLayer.Stop();
|
||||
|
||||
AddInternal(foregroundLayer);
|
||||
}
|
||||
|
||||
drawableHitObject.StartTimeBindable.BindValueChanged(startTime =>
|
||||
{
|
||||
timingPoint = beatSyncProvider?.ControlPoints?.TimingPointAt(startTime.NewValue) ?? TimingControlPoint.DEFAULT;
|
||||
}, true);
|
||||
|
||||
// Animations in taiko skins are used in a custom way (>150 combo and animating in time with beat).
|
||||
// For now just stop at first frame for sanity.
|
||||
foreach (var c in InternalChildren)
|
||||
{
|
||||
(c as IFramedAnimation)?.Stop();
|
||||
|
||||
c.Anchor = Anchor.Centre;
|
||||
c.Origin = Anchor.Centre;
|
||||
}
|
||||
|
||||
if (gameplayState != null)
|
||||
currentCombo.BindTo(gameplayState.ScoreProcessor.Combo);
|
||||
}
|
||||
@ -101,11 +106,11 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
foreach (var c in InternalChildren)
|
||||
c.Scale = new Vector2(DrawHeight / circle_piece_size.Y);
|
||||
|
||||
if (foregroundLayer is IFramedAnimation animatableForegroundLayer)
|
||||
animateForegroundLayer(animatableForegroundLayer);
|
||||
if (foregroundLayer is IFramedAnimation animatedForegroundLayer)
|
||||
animateForegroundLayer(animatedForegroundLayer);
|
||||
}
|
||||
|
||||
private void animateForegroundLayer(IFramedAnimation animatableForegroundLayer)
|
||||
private void animateForegroundLayer(IFramedAnimation animation)
|
||||
{
|
||||
int multiplier;
|
||||
|
||||
@ -119,12 +124,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
}
|
||||
else
|
||||
{
|
||||
animatableForegroundLayer.GotoFrame(0);
|
||||
animation.GotoFrame(0);
|
||||
return;
|
||||
}
|
||||
|
||||
animationFrame = Math.Abs(Time.Current - timingPoint.Time) % ((timingPoint.BeatLength * 2) / multiplier) >= timingPoint.BeatLength / multiplier ? 0 : 1;
|
||||
animatableForegroundLayer.GotoFrame(animationFrame);
|
||||
animation.GotoFrame(animationFrame);
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
|
@ -9,6 +9,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Tests.Resources;
|
||||
|
||||
namespace osu.Game.Tests
|
||||
@ -46,12 +47,15 @@ namespace osu.Game.Tests
|
||||
public partial class TestOsuGameBase : OsuGameBase
|
||||
{
|
||||
public RealmAccess Realm => Dependencies.Get<RealmAccess>();
|
||||
public new IAPIProvider API => base.API;
|
||||
|
||||
private readonly bool withBeatmap;
|
||||
|
||||
public TestOsuGameBase(bool withBeatmap)
|
||||
{
|
||||
this.withBeatmap = withBeatmap;
|
||||
|
||||
base.API = new DummyAPIAccess();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -11,7 +11,10 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
@ -67,6 +70,116 @@ namespace osu.Game.Tests.Scores.IO
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestLastPlayedUpdate(bool isLocalUser)
|
||||
{
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost())
|
||||
{
|
||||
try
|
||||
{
|
||||
var osu = LoadOsuIntoHost(host, true);
|
||||
|
||||
if (!isLocalUser)
|
||||
osu.API.Logout();
|
||||
|
||||
var beatmap = BeatmapImportHelper.LoadOszIntoOsu(osu, TestResources.GetQuickTestBeatmapForImport()).GetResultSafely();
|
||||
var beatmapInfo = beatmap.Beatmaps.First();
|
||||
|
||||
DateTimeOffset replayDate = DateTimeOffset.Now;
|
||||
|
||||
var toImport = new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.B,
|
||||
TotalScore = 987654,
|
||||
Accuracy = 0.8,
|
||||
MaxCombo = 500,
|
||||
Combo = 250,
|
||||
User = new APIUser
|
||||
{
|
||||
Username = "Test user",
|
||||
Id = DummyAPIAccess.DUMMY_USER_ID,
|
||||
},
|
||||
Date = replayDate,
|
||||
OnlineID = 12345,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
BeatmapInfo = beatmapInfo
|
||||
};
|
||||
|
||||
var imported = LoadScoreIntoOsu(osu, toImport);
|
||||
|
||||
Assert.AreEqual(toImport.Rank, imported.Rank);
|
||||
Assert.AreEqual(toImport.TotalScore, imported.TotalScore);
|
||||
Assert.AreEqual(toImport.Accuracy, imported.Accuracy);
|
||||
Assert.AreEqual(toImport.MaxCombo, imported.MaxCombo);
|
||||
Assert.AreEqual(toImport.User.Username, imported.User.Username);
|
||||
Assert.AreEqual(toImport.Date, imported.Date);
|
||||
Assert.AreEqual(toImport.OnlineID, imported.OnlineID);
|
||||
|
||||
if (isLocalUser)
|
||||
Assert.That(imported.BeatmapInfo!.LastPlayed, Is.EqualTo(replayDate));
|
||||
else
|
||||
Assert.That(imported.BeatmapInfo!.LastPlayed, Is.Null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
host.Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLastPlayedNotUpdatedDueToNewerPlays()
|
||||
{
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost())
|
||||
{
|
||||
try
|
||||
{
|
||||
var osu = LoadOsuIntoHost(host, true);
|
||||
|
||||
var beatmap = BeatmapImportHelper.LoadOszIntoOsu(osu, TestResources.GetQuickTestBeatmapForImport()).GetResultSafely();
|
||||
var beatmapInfo = beatmap.Beatmaps.First();
|
||||
|
||||
var realmAccess = osu.Dependencies.Get<RealmAccess>();
|
||||
realmAccess.Write(r => r.Find<BeatmapInfo>(beatmapInfo.ID)!.LastPlayed = new DateTimeOffset(2023, 10, 30, 0, 0, 0, TimeSpan.Zero));
|
||||
|
||||
var toImport = new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.B,
|
||||
TotalScore = 987654,
|
||||
Accuracy = 0.8,
|
||||
MaxCombo = 500,
|
||||
Combo = 250,
|
||||
User = new APIUser
|
||||
{
|
||||
Username = "Test user",
|
||||
Id = DummyAPIAccess.DUMMY_USER_ID,
|
||||
},
|
||||
Date = new DateTimeOffset(2023, 10, 27, 0, 0, 0, TimeSpan.Zero),
|
||||
OnlineID = 12345,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
BeatmapInfo = beatmapInfo
|
||||
};
|
||||
|
||||
var imported = LoadScoreIntoOsu(osu, toImport);
|
||||
|
||||
Assert.AreEqual(toImport.Rank, imported.Rank);
|
||||
Assert.AreEqual(toImport.TotalScore, imported.TotalScore);
|
||||
Assert.AreEqual(toImport.Accuracy, imported.Accuracy);
|
||||
Assert.AreEqual(toImport.MaxCombo, imported.MaxCombo);
|
||||
Assert.AreEqual(toImport.User.Username, imported.User.Username);
|
||||
Assert.AreEqual(toImport.Date, imported.Date);
|
||||
Assert.AreEqual(toImport.OnlineID, imported.OnlineID);
|
||||
|
||||
Assert.That(imported.BeatmapInfo!.LastPlayed, Is.EqualTo(new DateTimeOffset(2023, 10, 30, 0, 0, 0, TimeSpan.Zero)));
|
||||
}
|
||||
finally
|
||||
{
|
||||
host.Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportMods()
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
@ -1111,6 +1112,23 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
AddAssert("0 matching shown", () => songSelect.ChildrenOfType<FilterControl>().Single().InformationalText == "0 matches");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCutInFilterTextBox()
|
||||
{
|
||||
createSongSelect();
|
||||
|
||||
AddStep("set filter text", () => songSelect!.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = "nonono");
|
||||
AddStep("select all", () => InputManager.Keys(PlatformAction.SelectAll));
|
||||
AddStep("press ctrl-x", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ControlLeft);
|
||||
InputManager.Key(Key.X);
|
||||
InputManager.ReleaseKey(Key.ControlLeft);
|
||||
});
|
||||
|
||||
AddAssert("filter text cleared", () => songSelect!.FilterControl.ChildrenOfType<SearchTextBox>().First().Text, () => Is.Empty);
|
||||
}
|
||||
|
||||
private void waitForInitialSelection()
|
||||
{
|
||||
AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault);
|
||||
|
@ -112,7 +112,7 @@ namespace osu.Game.Online.API
|
||||
LocalUser.Value = new APIUser
|
||||
{
|
||||
Username = username,
|
||||
Id = 1001,
|
||||
Id = DUMMY_USER_ID,
|
||||
};
|
||||
|
||||
state.Value = APIState.Online;
|
||||
|
@ -182,6 +182,12 @@ namespace osu.Game.Scoring
|
||||
base.PostImport(model, realm, parameters);
|
||||
|
||||
populateUserDetails(model);
|
||||
|
||||
Debug.Assert(model.BeatmapInfo != null);
|
||||
|
||||
// This needs to be run after user detail population to ensure we have a valid user id.
|
||||
if (api.IsLoggedIn && api.LocalUser.Value.OnlineID == model.UserID && (model.BeatmapInfo.LastPlayed == null || model.Date > model.BeatmapInfo.LastPlayed))
|
||||
model.BeatmapInfo.LastPlayed = model.Date;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -9,6 +9,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Collections;
|
||||
@ -23,6 +24,7 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Select.Filter;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
@ -254,9 +256,6 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
public OsuSpriteText FilterText { get; private set; }
|
||||
|
||||
// clipboard is disabled because one of the "cut" platform key bindings (shift-delete) conflicts with the beatmap deletion action.
|
||||
protected override bool AllowClipboardExport => false;
|
||||
|
||||
public FilterControlTextBox()
|
||||
{
|
||||
Height += filter_text_size;
|
||||
@ -277,6 +276,15 @@ namespace osu.Game.Screens.Select
|
||||
Colour = colours.Yellow
|
||||
});
|
||||
}
|
||||
|
||||
public override bool OnPressed(KeyBindingPressEvent<PlatformAction> e)
|
||||
{
|
||||
// the "cut" platform key binding (shift-delete) conflicts with the beatmap deletion action.
|
||||
if (e.Action == PlatformAction.Cut && e.ShiftPressed && e.CurrentState.Keyboard.Keys.IsPressed(Key.Delete))
|
||||
return false;
|
||||
|
||||
return base.OnPressed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ namespace osu.Game.Skinning
|
||||
public float ScorePosition = 300 * POSITION_SCALE_FACTOR;
|
||||
public bool ShowJudgementLine = true;
|
||||
public bool KeysUnderNotes;
|
||||
public int LightFramePerSecond = 60;
|
||||
|
||||
public LegacyNoteBodyStyle? NoteBodyStyle;
|
||||
|
||||
|
@ -74,6 +74,7 @@ namespace osu.Game.Skinning
|
||||
Hit50,
|
||||
Hit0,
|
||||
KeysUnderNotes,
|
||||
NoteBodyStyle
|
||||
NoteBodyStyle,
|
||||
LightFramePerSecond
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,11 @@ namespace osu.Game.Skinning
|
||||
currentConfig.WidthForNoteHeightScale = (float.Parse(pair.Value, CultureInfo.InvariantCulture)) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR;
|
||||
break;
|
||||
|
||||
case "LightFramePerSecond":
|
||||
int lightFramePerSecond = int.Parse(pair.Value, CultureInfo.InvariantCulture);
|
||||
currentConfig.LightFramePerSecond = lightFramePerSecond > 0 ? lightFramePerSecond : 24;
|
||||
break;
|
||||
|
||||
case string when pair.Key.StartsWith("Colour", StringComparison.Ordinal):
|
||||
HandleColours(currentConfig, line, true);
|
||||
break;
|
||||
|
@ -273,6 +273,9 @@ namespace osu.Game.Skinning
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.KeysUnderNotes:
|
||||
return SkinUtils.As<TValue>(new Bindable<bool>(existing.KeysUnderNotes));
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.LightFramePerSecond:
|
||||
return SkinUtils.As<TValue>(new Bindable<int>(existing.LightFramePerSecond));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
Loading…
Reference in New Issue
Block a user