mirror of
https://github.com/SK-la/Ez2Lazer.git
synced 2026-03-13 11:20:28 +00:00
[渐进]逐步回退、备份测试
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1121.1" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1205.1" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
||||
<AssemblyName>osu!</AssemblyName>
|
||||
<AssemblyTitle>osu!(lazer)</AssemblyTitle>
|
||||
<AssemblyName>Ez2osu!</AssemblyName>
|
||||
<AssemblyTitle>osu!(Ez2lazer)</AssemblyTitle>
|
||||
<Title>Ez2lazer!</Title>
|
||||
<Product>osu!(Ez2lazer)</Product>
|
||||
<ApplicationIcon>lazer.ico</ApplicationIcon>
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
|
||||
private double placementStartTime;
|
||||
private double placementEndTime;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public BananaShowerPlacementBlueprint()
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
|
||||
|
||||
private InputManager inputManager = null!;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public JuiceStreamPlacementBlueprint()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
@@ -16,6 +17,7 @@ using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Input;
|
||||
|
||||
@@ -36,21 +38,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
[Test]
|
||||
public void TestPlaceBeforeCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("seek to 200", () => HitObjectContainer.Dependencies.Get<EditorClock>().Seek(200));
|
||||
AddStep("move mouse before current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(-100));
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time < 0", () => getNote().StartTime < 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPlaceAfterCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("move mouse after current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(100));
|
||||
@@ -58,7 +47,22 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time > 0", () => getNote().StartTime > 0);
|
||||
AddAssert("note start time < 200", () => getNote().StartTime < 200);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPlaceAfterCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("seek to 200", () => HitObjectContainer.Dependencies.Get<EditorClock>().Seek(200));
|
||||
AddStep("move mouse after current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(300));
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time > 200", () => getNote().StartTime > 200);
|
||||
}
|
||||
|
||||
private Note getNote() => this.ChildrenOfType<DrawableNote>().FirstOrDefault()?.HitObject;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
[Resolved]
|
||||
private IScrollingInfo scrollingInfo { get; set; } = null!;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public HoldNotePlacementBlueprint()
|
||||
: base(new HoldNote())
|
||||
|
||||
@@ -56,7 +56,8 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
};
|
||||
|
||||
public override string ConvertSelectionToString()
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime).Select(h => $"{h.StartTime}|{h.Column}"));
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime)
|
||||
.Select(h => FormattableString.Invariant($"{Math.Round(h.StartTime)}|{h.Column}")));
|
||||
|
||||
// 123|0,456|1,789|2 ...
|
||||
private static readonly Regex selection_regex = new Regex(@"^\d+\|\d+(,\d+\|\d+)*$", RegexOptions.Compiled);
|
||||
@@ -75,10 +76,10 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
if (split.Length != 2)
|
||||
continue;
|
||||
|
||||
if (!double.TryParse(split[0], out double time) || !int.TryParse(split[1], out int column))
|
||||
if (!int.TryParse(split[0], out int time) || !int.TryParse(split[1], out int column))
|
||||
continue;
|
||||
|
||||
ManiaHitObject? current = remainingHitObjects.FirstOrDefault(h => h.StartTime == time && h.Column == column);
|
||||
ManiaHitObject? current = remainingHitObjects.FirstOrDefault(h => Precision.AlmostEquals(h.StartTime, time, 0.5) && h.Column == column);
|
||||
|
||||
if (current == null)
|
||||
continue;
|
||||
|
||||
@@ -67,30 +67,32 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new ManiaHealthProcessor(drainStartTime);
|
||||
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap)
|
||||
{
|
||||
var hitMode = GlobalConfigStore.Config?.Get<EzMUGHitMode>(OsuSetting.HitMode) ?? EzMUGHitMode.Lazer;
|
||||
ManiaBeatmapConverter.CurrentHitMode = hitMode;
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this);
|
||||
|
||||
if (hitMode == EzMUGHitMode.O2Jam)
|
||||
{
|
||||
double bpm = beatmap.BeatmapInfo.BPM;
|
||||
if (bpm == 0) bpm = 200;
|
||||
O2HitModeExtension.NowBeatmapBPM = bpm;
|
||||
double coolRange = 7500.0 / bpm;
|
||||
double goodRange = 22500.0 / bpm;
|
||||
double badRange = 31250.0 / bpm;
|
||||
var hw = new ManiaHitWindows();
|
||||
hw.SetSpecialDifficultyRange(coolRange, coolRange, goodRange, goodRange, badRange, badRange);
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// var hw = new ManiaHitWindows();
|
||||
// hw.ResetRange();
|
||||
// }
|
||||
|
||||
return new ManiaBeatmapConverter(beatmap, this);
|
||||
}
|
||||
// public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap)
|
||||
// {
|
||||
// var hitMode = GlobalConfigStore.Config?.Get<EzMUGHitMode>(OsuSetting.HitMode) ?? EzMUGHitMode.Lazer;
|
||||
// ManiaBeatmapConverter.CurrentHitMode = hitMode;
|
||||
//
|
||||
// if (hitMode == EzMUGHitMode.O2Jam)
|
||||
// {
|
||||
// double bpm = beatmap.BeatmapInfo.BPM;
|
||||
// if (bpm == 0) bpm = 200;
|
||||
// O2HitModeExtension.NowBeatmapBPM = bpm;
|
||||
// double coolRange = 7500.0 / bpm;
|
||||
// double goodRange = 22500.0 / bpm;
|
||||
// double badRange = 31250.0 / bpm;
|
||||
// var hw = new ManiaHitWindows();
|
||||
// hw.SetSpecialDifficultyRange(coolRange, coolRange, goodRange, goodRange, badRange, badRange);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var hw = new ManiaHitWindows();
|
||||
// hw.ResetRange();
|
||||
// }
|
||||
//
|
||||
// return new ManiaBeatmapConverter(beatmap, this);
|
||||
// }
|
||||
|
||||
public override PerformanceCalculator CreatePerformanceCalculator() => new ManiaPerformanceCalculator();
|
||||
|
||||
@@ -356,33 +358,33 @@ namespace osu.Game.Rulesets.Mania
|
||||
return new Mod[]
|
||||
{
|
||||
new ManiaModAdjust(),
|
||||
new ManiaModChangeSpeedByAccuracy(),
|
||||
// new ManiaModCleaner(),
|
||||
new ManiaModDeleteSpace(),
|
||||
new ManiaModDoublePlay(),
|
||||
new ManiaModDuplicate(),
|
||||
new ManiaModGracer(),
|
||||
new ManiaModJackAdjust(),
|
||||
new ManiaModJudgmentsAdjust(),
|
||||
new ManiaModJudgmentsProportion(),
|
||||
new ManiaModLN(),
|
||||
new ManiaModLNDoubleDistribution(),
|
||||
new ManiaModLNJudgementAdjust(),
|
||||
new ManiaModLNLongShortAddition(),
|
||||
new ManiaModLNSimplify(),
|
||||
new ManiaModLNTransformer(),
|
||||
new ManiaModMalodyStyleLN(),
|
||||
new ManiaModNewJudgement(),
|
||||
new ManiaModNoteAdjust(),
|
||||
new ManiaModNtoM(),
|
||||
new ManiaModNtoMAnother(),
|
||||
new ManiaModO2Health(),
|
||||
new ManiaModO2Judgement(),
|
||||
// new ManiaModPlayfieldTransformation(), //加载有问题
|
||||
new ManiaModReleaseAdjust(),
|
||||
new ManiaModRemedy(),
|
||||
new StarRatingRebirth(),
|
||||
new StarRatingRebirthNoTask(),
|
||||
// new ManiaModChangeSpeedByAccuracy(),
|
||||
// // new ManiaModCleaner(),
|
||||
// new ManiaModDeleteSpace(),
|
||||
// new ManiaModDoublePlay(),
|
||||
// new ManiaModDuplicate(),
|
||||
// new ManiaModGracer(),
|
||||
// new ManiaModJackAdjust(),
|
||||
// new ManiaModJudgmentsAdjust(),
|
||||
// new ManiaModJudgmentsProportion(),
|
||||
// new ManiaModLN(),
|
||||
// new ManiaModLNDoubleDistribution(),
|
||||
// new ManiaModLNJudgementAdjust(),
|
||||
// new ManiaModLNLongShortAddition(),
|
||||
// new ManiaModLNSimplify(),
|
||||
// new ManiaModLNTransformer(),
|
||||
// new ManiaModMalodyStyleLN(),
|
||||
// // new ManiaModNewJudgement(),
|
||||
// new ManiaModNoteAdjust(),
|
||||
// new ManiaModNtoM(),
|
||||
// new ManiaModNtoMAnother(),
|
||||
// new ManiaModO2Health(),
|
||||
// new ManiaModO2Judgement(),
|
||||
// // new ManiaModPlayfieldTransformation(), //加载有问题
|
||||
// new ManiaModReleaseAdjust(),
|
||||
// new ManiaModRemedy(),
|
||||
// new StarRatingRebirth(),
|
||||
// new StarRatingRebirthNoTask(),
|
||||
};
|
||||
|
||||
case ModType.Fun:
|
||||
@@ -472,6 +474,8 @@ namespace osu.Game.Rulesets.Mania
|
||||
HitResult.Good,
|
||||
HitResult.Ok,
|
||||
HitResult.Meh,
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.IgnoreMiss,
|
||||
|
||||
// HitResult.SmallBonus is used for awarding perfect bonus score but is not included here as
|
||||
// it would be a bit redundant to show this to the user.
|
||||
|
||||
@@ -4,18 +4,13 @@
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Scoring;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.EzCurrentHitObject
|
||||
{
|
||||
public partial class Ez2AcDrawableLNTail : DrawableHoldNoteTail
|
||||
{
|
||||
// public override bool DisplayResult => false;
|
||||
// public override bool OnPressed(KeyBindingPressEvent<ManiaAction> e)
|
||||
// {
|
||||
// return UpdateResult(true);
|
||||
// }
|
||||
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (HoldNote.IsHolding.Value && timeOffset >= 0)
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.EzCurrentHitObject
|
||||
NodeSamples = hold.NodeSamples;
|
||||
}
|
||||
|
||||
protected override HitWindows CreateHitWindows() => new EzCustomHitWindows();
|
||||
|
||||
protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
|
||||
{
|
||||
AddNested(Head = new Ez2AcLNHead
|
||||
@@ -55,14 +57,26 @@ namespace osu.Game.Rulesets.Mania.Objects.EzCurrentHitObject
|
||||
|
||||
public class Ez2AcLNHead : HeadNote
|
||||
{
|
||||
// public override Judgement CreateJudgement() => new Ez2AcJudgement();
|
||||
public override Judgement CreateJudgement() => new Ez2AcHeadJudgement();
|
||||
protected override HitWindows CreateHitWindows() => new EzCustomHitWindows();
|
||||
|
||||
private class Ez2AcHeadJudgement : ManiaJudgement
|
||||
{
|
||||
public override HitResult MaxResult => HitResult.Perfect;
|
||||
public override HitResult MinResult => HitResult.IgnoreMiss;
|
||||
}
|
||||
}
|
||||
|
||||
public class Ez2AcLNTail : TailNote
|
||||
{
|
||||
// public override Judgement CreateJudgement() => new Ez2AcJudgement();
|
||||
public override Judgement CreateJudgement() => new Ez2AcTailJudgement();
|
||||
protected override HitWindows CreateHitWindows() => new EzCustomHitWindows();
|
||||
|
||||
private class Ez2AcTailJudgement : ManiaJudgement
|
||||
{
|
||||
public override HitResult MaxResult => HitResult.Perfect;
|
||||
public override HitResult MinResult => HitResult.ComboBreak;
|
||||
}
|
||||
}
|
||||
|
||||
public class Ez2AcNote : Note
|
||||
@@ -74,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.Objects.EzCurrentHitObject
|
||||
Samples = note.Samples;
|
||||
}
|
||||
|
||||
// public override Judgement CreateJudgement() => new Ez2AcJudgement();
|
||||
public override Judgement CreateJudgement() => new Ez2AcJudgement();
|
||||
protected override HitWindows CreateHitWindows() => new EzCustomHitWindows();
|
||||
|
||||
protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
|
||||
@@ -82,8 +96,11 @@ namespace osu.Game.Rulesets.Mania.Objects.EzCurrentHitObject
|
||||
}
|
||||
}
|
||||
|
||||
public class Ez2AcJudgement : Judgement
|
||||
public class Ez2AcJudgement : ManiaJudgement
|
||||
{
|
||||
public override HitResult MaxResult => HitResult.Perfect;
|
||||
public override HitResult MinResult => HitResult.Pool;
|
||||
|
||||
protected override double HealthIncreaseFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
|
||||
@@ -126,6 +126,8 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
case HitResult.Meh:
|
||||
// case HitResult.Pool:
|
||||
case HitResult.Miss:
|
||||
case HitResult.IgnoreHit:
|
||||
case HitResult.IgnoreMiss:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osuTK;
|
||||
using EzLocalTextureFactory = osu.Game.LAsEzExtensions.EzLocalTextureFactory;
|
||||
using osu.Game.LAsEzExtensions;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
using EzLocalTextureFactory = osu.Game.LAsEzExtensions.EzLocalTextureFactory;
|
||||
using osu.Game.LAsEzExtensions;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens;
|
||||
using osuTK;
|
||||
using EzLocalTextureFactory = osu.Game.LAsEzExtensions.EzLocalTextureFactory;
|
||||
using osu.Game.LAsEzExtensions;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using EzLocalTextureFactory = osu.Game.LAsEzExtensions.EzLocalTextureFactory;
|
||||
using osu.Game.LAsEzExtensions;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
|
||||
@@ -10,7 +10,6 @@ using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
@@ -164,13 +163,13 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
base.LoadComplete();
|
||||
|
||||
// Configure pools based on hit mode
|
||||
foreach (var stage in Playfield.Stages)
|
||||
{
|
||||
foreach (var column in stage.Columns)
|
||||
{
|
||||
configurePools(column, ManiaBeatmapConverter.CurrentHitMode);
|
||||
}
|
||||
}
|
||||
// foreach (var stage in Playfield.Stages)
|
||||
// {
|
||||
// foreach (var column in stage.Columns)
|
||||
// {
|
||||
// configurePools(column, ManiaBeatmapConverter.CurrentHitMode);
|
||||
// }
|
||||
// }
|
||||
|
||||
// 启动独立的异步任务,预加载EzPro皮肤中会用到的贴图
|
||||
Schedule(() =>
|
||||
@@ -306,26 +305,12 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
currentSkin.SourceChanged -= onSkinChange;
|
||||
}
|
||||
|
||||
public bool SupportsBackgroundBlurMasking => true;
|
||||
|
||||
public RectangleF? GetPlayfieldBounds()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Playfield.ScreenSpaceDrawQuad.AABBFloat;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void configurePools(Column column, EzMUGHitMode hitMode)
|
||||
{
|
||||
switch (hitMode)
|
||||
{
|
||||
case EzMUGHitMode.EZ2AC:
|
||||
// column.RegisterPool<Ez2AcNote, DrawableNote>(10, 50);
|
||||
column.RegisterPool<Ez2AcNote, DrawableNote>(10, 50);
|
||||
column.RegisterPool<Ez2AcLNHead, DrawableHoldNoteHead>(10, 50);
|
||||
column.RegisterPool<NoMissLNBody, DrawableHoldNoteBody>(10, 50);
|
||||
column.RegisterPool<Ez2AcLNTail, Ez2AcDrawableLNTail>(10, 50);
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
@@ -90,23 +90,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
// TODO: 需要修改framework着色器-容器实现真正效果。动态根据实际的游戏中BackgroundScreen背景或故事版绘制局部虚化效果
|
||||
// // 注意,如果是真正的毛玻璃效果,此处就不应该在此处试图获取外部的背景内容,因为存在循环依赖问题。
|
||||
// acrylicEffect = new FrostedGlassContainer
|
||||
// {
|
||||
// Name = "Acrylic backdrop effect",
|
||||
// Anchor = Anchor.Centre,
|
||||
// Origin = Anchor.Centre,
|
||||
// RelativeSizeAxes = Axes.Both, //使用Both即可实现局部遮罩,因为此处父容器就是局部面板
|
||||
// BlurRotation = 50f,
|
||||
// Depth = 1, // 在背景层
|
||||
// Child = new Box
|
||||
// {
|
||||
// RelativeSizeAxes = Axes.Both,
|
||||
// Colour = Colour4.Red,
|
||||
// Alpha = 0.01f,
|
||||
// }
|
||||
// },
|
||||
dimBox = new Box //通过叠加覆盖实现暗化效果
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@@ -207,19 +190,12 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
onSkinChanged();
|
||||
|
||||
columnDim = ezSkinSettings.GetBindable<double>(EzSkinSetting.ColumnDim);
|
||||
// columnBlur = ezSkinSettings.GetBindable<double>(EzSkinSetting.ColumnBlur);
|
||||
|
||||
// 应用暗化效果
|
||||
columnDim.BindValueChanged(v =>
|
||||
{
|
||||
dimBox.Alpha = (float)v.NewValue;
|
||||
}, true);
|
||||
|
||||
// // 应用虚化效果
|
||||
// columnBlur.BindValueChanged(v =>
|
||||
// {
|
||||
// acrylicEffect.BlurRotation = (float)v.NewValue;
|
||||
// }, true);
|
||||
}
|
||||
|
||||
private void onSkinChanged()
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@@ -22,7 +23,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
[TestFixture]
|
||||
public partial class TestSceneSliderDrawing : TestSceneOsuEditor
|
||||
{
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new TestBeatmap(ruleset, false);
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTouchInputPlaceHitCircleDirectly()
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
|
||||
private readonly IncrementalBSplineBuilder bSplineBuilder = new IncrementalBSplineBuilder { Degree = 4 };
|
||||
|
||||
protected override bool IsValidForPlacement => HitObject.Path.HasValidLengthForPlacement;
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || HitObject.Path.HasValidLengthForPlacement);
|
||||
|
||||
public SliderPlacementBlueprint()
|
||||
: base(new Slider())
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
|
||||
[Resolved]
|
||||
private TaikoHitObjectComposer? composer { get; set; }
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(spanPlacementObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(spanPlacementObject.Duration, 0));
|
||||
|
||||
public TaikoSpanPlacementBlueprint(HitObject hitObject)
|
||||
: base(hitObject)
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
double lastStarRating = 0;
|
||||
double lastLength = 0;
|
||||
|
||||
AddStep("Add timing point", () => EditorBeatmap.ControlPointInfo.Add(200, new TimingControlPoint { BeatLength = 600 }));
|
||||
AddStep("Add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 600 }));
|
||||
AddStep("Change to placement mode", () => InputManager.Key(Key.Number2));
|
||||
AddStep("Move to playfield", () => InputManager.MoveMouseTo(Game.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("Place single hitcircle", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets;
|
||||
@@ -27,7 +28,12 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new TestBeatmap(ruleset, false);
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private GlobalActionContainer globalActionContainer => this.ChildrenOfType<GlobalActionContainer>().Single();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
@@ -27,7 +28,12 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new TestBeatmap(ruleset, false);
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 500 });
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private TimelineBlueprintContainer blueprintContainer
|
||||
=> Editor.ChildrenOfType<TimelineBlueprintContainer>().First();
|
||||
@@ -80,7 +86,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
InputManager.Key(Key.Number1);
|
||||
blueprint = this.ChildrenOfType<TimelineHitObjectBlueprint>().First();
|
||||
InputManager.MoveMouseTo(blueprint);
|
||||
InputManager.MoveMouseTo(blueprint, new Vector2(-1, 0));
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
|
||||
@@ -235,6 +235,22 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRollAnimationFinalRandom()
|
||||
{
|
||||
AddStep("play animation", () =>
|
||||
{
|
||||
(long[] candidateItems, _) = pickRandomItems(5);
|
||||
|
||||
candidateItems = candidateItems.Append(-1).ToArray();
|
||||
long finalItem = items.First(i => !candidateItems.Contains(i.ID)).ID;
|
||||
|
||||
grid.RollAndDisplayFinalBeatmap(candidateItems, -1, finalItem);
|
||||
});
|
||||
|
||||
AddWaitStep("wait for animation", 10);
|
||||
}
|
||||
|
||||
private (long[] candidateItems, long finalItem) pickRandomItems(int count)
|
||||
{
|
||||
long[] candidateItems = items.Select(it => it.ID).ToArray();
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// 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.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
@@ -33,6 +35,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new MultiplayerSkipOverlay(120000)
|
||||
{
|
||||
RequestSkip = () => MultiplayerClient.VoteToSkipIntro().WaitSafely(),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -47,26 +52,83 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int i2 = i;
|
||||
int userId = i;
|
||||
|
||||
AddStep($"join user {i2}", () =>
|
||||
AddStep($"join user {userId}", () =>
|
||||
{
|
||||
MultiplayerClient.AddUser(new APIUser
|
||||
{
|
||||
Id = i2,
|
||||
Username = $"User {i2}"
|
||||
Id = userId,
|
||||
Username = $"User {userId}"
|
||||
});
|
||||
|
||||
MultiplayerClient.ChangeUserState(i2, MultiplayerUserState.Playing);
|
||||
MultiplayerClient.ChangeUserState(userId, MultiplayerUserState.Playing);
|
||||
});
|
||||
}
|
||||
|
||||
AddStep("local user votes", () => MultiplayerClient.VoteToSkipIntro().WaitSafely());
|
||||
AddStep("user 0 votes", () => MultiplayerClient.UserVoteToSkipIntro(0).WaitSafely());
|
||||
AddStep("local user votes", () => this.ChildrenOfType<MultiplayerSkipOverlay.Button>().Single().TriggerClick());
|
||||
AddStep("user 1 votes", () => MultiplayerClient.UserVoteToSkipIntro(1).WaitSafely());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLeavingBeforeLocalVote()
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int i2 = i;
|
||||
AddStep($"user {i2} votes", () => MultiplayerClient.UserVoteToSkipIntro(i2).WaitSafely());
|
||||
int userId = i;
|
||||
|
||||
AddStep($"join user {userId}", () =>
|
||||
{
|
||||
MultiplayerClient.AddUser(new APIUser
|
||||
{
|
||||
Id = userId,
|
||||
Username = $"User {userId}"
|
||||
});
|
||||
|
||||
MultiplayerClient.ChangeUserState(userId, MultiplayerUserState.Playing);
|
||||
});
|
||||
}
|
||||
|
||||
AddStep("user 0 votes", () => MultiplayerClient.UserVoteToSkipIntro(0).WaitSafely());
|
||||
AddStep("user 1 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 1 }));
|
||||
AddStep("user 2 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 2 }));
|
||||
AddStep("user 3 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 3 }));
|
||||
AddStep("user 0 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 0 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLeavingAfterLocalVote()
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int userId = i;
|
||||
|
||||
AddStep($"join user {userId}", () =>
|
||||
{
|
||||
MultiplayerClient.AddUser(new APIUser
|
||||
{
|
||||
Id = userId,
|
||||
Username = $"User {userId}"
|
||||
});
|
||||
|
||||
MultiplayerClient.ChangeUserState(userId, MultiplayerUserState.Playing);
|
||||
});
|
||||
}
|
||||
|
||||
AddStep("local user votes", () => this.ChildrenOfType<MultiplayerSkipOverlay.Button>().Single().TriggerClick());
|
||||
AddStep("user 0 votes", () => MultiplayerClient.UserVoteToSkipIntro(0).WaitSafely());
|
||||
AddStep("user 1 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 1 }));
|
||||
AddStep("user 2 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 2 }));
|
||||
AddStep("user 3 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 3 }));
|
||||
AddStep("user 0 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 0 }));
|
||||
}
|
||||
|
||||
public partial class TestMultiplayerSkipOverlay : MultiplayerSkipOverlay
|
||||
{
|
||||
public TestMultiplayerSkipOverlay()
|
||||
: base(120000)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace osu.Game.Tests.Visual.Settings
|
||||
scrollToAndStartBinding("Increase volume");
|
||||
AddStep("press shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||
AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft));
|
||||
checkBinding("Increase volume", "LShift");
|
||||
checkBinding("Increase volume", "Shift");
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -77,7 +77,7 @@ namespace osu.Game.Tests.Visual.Settings
|
||||
AddStep("press shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||
AddStep("press k", () => InputManager.Key(Key.K));
|
||||
AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft));
|
||||
checkBinding("Increase volume", "LShift-K");
|
||||
checkBinding("Increase volume", "Shift-K");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -5,6 +5,7 @@ using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -139,9 +140,14 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
/// </summary>
|
||||
/// <param name="fullState">A <see cref="KeyCombination"/> generated from the full input state.</param>
|
||||
/// <param name="triggerKey">The key which triggered this update, and should be used as the binding.</param>
|
||||
public void UpdateKeyCombination(KeyCombination fullState, InputKey triggerKey) =>
|
||||
// TODO: Distinct() can be removed after https://github.com/ppy/osu-framework/pull/6130 is merged.
|
||||
UpdateKeyCombination(new KeyCombination(fullState.Keys.Where(KeyCombination.IsModifierKey).Append(triggerKey).Distinct().ToArray()));
|
||||
public void UpdateKeyCombination(KeyCombination fullState, InputKey triggerKey)
|
||||
{
|
||||
var combination = fullState.Keys.Where(KeyCombination.IsModifierKey)
|
||||
.Append(triggerKey)
|
||||
.Select(k => k.GetVirtualKey() ?? k)
|
||||
.ToArray();
|
||||
UpdateKeyCombination(new KeyCombination(combination));
|
||||
}
|
||||
|
||||
public void UpdateKeyCombination(KeyCombination newCombination)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
@@ -47,6 +48,8 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
private HitObject? getPreviousHitObject() => beatmap.HitObjects.TakeWhile(h => h.StartTime <= startTimeBindable.Value).LastOrDefault();
|
||||
|
||||
protected override bool IsValidForPlacement => HitObject.StartTime >= beatmap.ControlPointInfo.TimingPoints[0].Time;
|
||||
|
||||
[Resolved]
|
||||
private IPlacementHandler placementHandler { get; set; } = null!;
|
||||
|
||||
@@ -87,6 +90,13 @@ namespace osu.Game.Rulesets.Edit
|
||||
placementHandler.HidePlacement();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
Colour = IsValidForPlacement ? Colour4.White : Colour4.Red;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the time and position of this <see cref="PlacementBlueprint"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -64,20 +64,15 @@ namespace osu.Game.Screens
|
||||
{
|
||||
this.FadeOut();
|
||||
this.FadeIn(TRANSITION_LENGTH, Easing.InOutQuart);
|
||||
|
||||
if (!DisableParallax)
|
||||
{
|
||||
this.MoveToX(x_movement_amount);
|
||||
this.MoveToX(0, TRANSITION_LENGTH, Easing.InOutQuart);
|
||||
}
|
||||
}
|
||||
|
||||
base.OnEntering(e);
|
||||
}
|
||||
|
||||
public override void OnSuspending(ScreenTransitionEvent e)
|
||||
{
|
||||
if (!DisableParallax)
|
||||
this.MoveToX(-x_movement_amount, TRANSITION_LENGTH, Easing.InOutQuart);
|
||||
base.OnSuspending(e);
|
||||
}
|
||||
@@ -87,7 +82,6 @@ namespace osu.Game.Screens
|
||||
if (IsLoaded)
|
||||
{
|
||||
this.FadeOut(TRANSITION_LENGTH, Easing.OutExpo);
|
||||
if (!DisableParallax)
|
||||
this.MoveToX(x_movement_amount, TRANSITION_LENGTH, Easing.OutExpo);
|
||||
}
|
||||
|
||||
@@ -96,7 +90,7 @@ namespace osu.Game.Screens
|
||||
|
||||
public override void OnResuming(ScreenTransitionEvent e)
|
||||
{
|
||||
if (IsLoaded && !DisableParallax)
|
||||
if (IsLoaded)
|
||||
this.MoveToX(0, TRANSITION_LENGTH, Easing.OutExpo);
|
||||
base.OnResuming(e);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match.BeatmapSelect
|
||||
this.Delay(ARRANGE_DELAY)
|
||||
.Schedule(() => ArrangeItemsForRollAnimation())
|
||||
.Delay(arrange_duration)
|
||||
.Schedule(() => PlayRollAnimation(gameplayItemId, roll_duration))
|
||||
.Schedule(() => PlayRollAnimation(candidateItemId, roll_duration))
|
||||
.Delay(roll_duration + present_beatmap_delay)
|
||||
.Schedule(() => PresentRolledBeatmap(candidateItemId, gameplayItemId));
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match
|
||||
client.MatchRoomStateChanged += onRoomStateChanged;
|
||||
client.UserJoined += onUserJoined;
|
||||
client.UserLeft += onUserLeft;
|
||||
client.UserKicked += onUserLeft;
|
||||
|
||||
if (client.Room != null)
|
||||
{
|
||||
@@ -207,6 +208,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match
|
||||
client.MatchRoomStateChanged -= onRoomStateChanged;
|
||||
client.UserJoined -= onUserJoined;
|
||||
client.UserLeft -= onUserLeft;
|
||||
client.UserKicked -= onUserLeft;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,15 +4,24 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -23,90 +32,49 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; } = null!;
|
||||
|
||||
private Drawable votedIcon = null!;
|
||||
private OsuSpriteText countText = null!;
|
||||
[Resolved]
|
||||
private OsuColour colours { get; set; } = null!;
|
||||
|
||||
private Button skipButton = null!;
|
||||
|
||||
public MultiplayerSkipOverlay(double startTime)
|
||||
: base(startTime)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
protected override OsuClickableContainer CreateButton() => skipButton = new Button
|
||||
{
|
||||
FadingContent.AddRange(
|
||||
[
|
||||
votedIcon = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Position = new Vector2(50, 0),
|
||||
Size = new Vector2(20),
|
||||
Alpha = 0,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Green
|
||||
},
|
||||
new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.5f),
|
||||
Icon = FontAwesome.Solid.Check
|
||||
}
|
||||
}
|
||||
},
|
||||
countText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.X,
|
||||
Position = new Vector2(0.75f, 0),
|
||||
Font = OsuFont.Default.With(size: 36, weight: FontWeight.Bold)
|
||||
}
|
||||
]);
|
||||
}
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
skipButton.Enabled.BindValueChanged(e =>
|
||||
{
|
||||
RemainingTimeBox.Colour = e.NewValue ? colours.Orange3 : Button.COLOUR_GRAY;
|
||||
}, true);
|
||||
|
||||
client.UserLeft += onUserLeft;
|
||||
client.UserStateChanged += onUserStateChanged;
|
||||
client.UserVotedToSkipIntro += onUserVotedToSkipIntro;
|
||||
|
||||
updateText();
|
||||
updateCount();
|
||||
}
|
||||
|
||||
private void onUserLeft(MultiplayerRoomUser user)
|
||||
{
|
||||
Schedule(updateText);
|
||||
}
|
||||
private void onUserLeft(MultiplayerRoomUser user) => Schedule(updateCount);
|
||||
|
||||
private void onUserStateChanged(MultiplayerRoomUser user, MultiplayerUserState state)
|
||||
{
|
||||
Schedule(updateText);
|
||||
}
|
||||
private void onUserStateChanged(MultiplayerRoomUser user, MultiplayerUserState state) => Schedule(updateCount);
|
||||
|
||||
private void onUserVotedToSkipIntro(int userId) => Schedule(() =>
|
||||
{
|
||||
updateText();
|
||||
|
||||
countText.ScaleTo(1.5f).ScaleTo(1, 200, Easing.OutSine);
|
||||
|
||||
if (userId == client.LocalUser?.UserID)
|
||||
{
|
||||
votedIcon.ScaleTo(1.5f).ScaleTo(1, 200, Easing.OutSine);
|
||||
votedIcon.FadeInFromZero(100);
|
||||
}
|
||||
FadingContent.TriggerShow();
|
||||
updateCount();
|
||||
});
|
||||
|
||||
private void updateText()
|
||||
private void updateCount()
|
||||
{
|
||||
if (client.Room == null || client.Room.Settings.AutoSkip)
|
||||
return;
|
||||
@@ -115,7 +83,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
int countSkipped = client.Room.Users.Count(u => u.State == MultiplayerUserState.Playing && u.VotedToSkipIntro);
|
||||
int countRequired = countTotal / 2 + 1;
|
||||
|
||||
countText.Text = $"{Math.Min(countRequired, countSkipped)} / {countRequired}";
|
||||
skipButton.SkippedCount.Value = Math.Min(countRequired, countSkipped);
|
||||
skipButton.RequiredCount.Value = countRequired;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
@@ -129,5 +98,218 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
client.UserVotedToSkipIntro -= onUserVotedToSkipIntro;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Button : OsuClickableContainer
|
||||
{
|
||||
private const float chevron_y = 0.4f;
|
||||
private const float secondary_y = 0.7f;
|
||||
|
||||
public static readonly Color4 COLOUR_GRAY = OsuColour.Gray(0.4f);
|
||||
|
||||
private Box background = null!;
|
||||
private Box box = null!;
|
||||
private TrianglesV2 triangles = null!;
|
||||
private OsuSpriteText countText = null!;
|
||||
private OsuSpriteText skipText = null!;
|
||||
private AspectContainer aspect = null!;
|
||||
|
||||
private FillFlowContainer chevrons = null!;
|
||||
|
||||
private Sample sampleConfirm = null!;
|
||||
|
||||
public readonly BindableInt SkippedCount = new BindableInt();
|
||||
public readonly BindableInt RequiredCount = new BindableInt();
|
||||
|
||||
[Resolved]
|
||||
private OsuColour colours { get; set; } = null!;
|
||||
|
||||
public Button()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleConfirm = audio.Samples.Get(@"UI/submit-select");
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
Alpha = 0.2f,
|
||||
Colour = Color4.Black,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
aspect = new AspectContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Height = 0.6f,
|
||||
Masking = true,
|
||||
CornerRadius = 15,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
box = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
triangles = new TrianglesV2
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
countText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Y = 0.35f,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24),
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
chevrons = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new[]
|
||||
{
|
||||
new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight },
|
||||
new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight },
|
||||
new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight },
|
||||
}
|
||||
},
|
||||
skipText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12),
|
||||
Origin = Anchor.Centre,
|
||||
Text = @"SKIP",
|
||||
Y = secondary_y,
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
SkippedCount.BindValueChanged(_ => updateCount());
|
||||
RequiredCount.BindValueChanged(_ => updateCount(), true);
|
||||
Enabled.BindValueChanged(_ => updateColours(), true);
|
||||
|
||||
FinishTransforms(true);
|
||||
}
|
||||
|
||||
private void updateChevronsSpacing()
|
||||
{
|
||||
if (SkippedCount.Value > 0 && RequiredCount.Value > 1)
|
||||
chevrons.TransformSpacingTo(new Vector2(-5f), 500, Easing.OutQuint);
|
||||
else
|
||||
chevrons.TransformSpacingTo(IsHovered ? new Vector2(5f) : new Vector2(0f), 500, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateCount()
|
||||
{
|
||||
if (SkippedCount.Value > 0 && RequiredCount.Value > 1)
|
||||
{
|
||||
countText.FadeIn(300, Easing.OutQuint);
|
||||
countText.Text = $"{SkippedCount.Value} / {RequiredCount.Value}";
|
||||
|
||||
chevrons.ScaleTo(0.5f, 300, Easing.OutQuint)
|
||||
.MoveTo(new Vector2(-11, secondary_y), 300, Easing.OutQuint);
|
||||
|
||||
skipText.MoveToX(11f, 300, Easing.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
countText.FadeOut(300, Easing.OutQuint);
|
||||
|
||||
chevrons.ScaleTo(1f, 300, Easing.OutQuint)
|
||||
.MoveTo(new Vector2(0, chevron_y), 300, Easing.OutQuint);
|
||||
|
||||
skipText.MoveToX(0f, 300, Easing.OutQuint);
|
||||
}
|
||||
|
||||
updateChevronsSpacing();
|
||||
updateColours();
|
||||
}
|
||||
|
||||
private void updateColours()
|
||||
{
|
||||
if (!Enabled.Value)
|
||||
{
|
||||
box.FadeColour(COLOUR_GRAY, 500, Easing.OutQuint);
|
||||
triangles.FadeColour(ColourInfo.GradientVertical(COLOUR_GRAY.Lighten(0.2f), COLOUR_GRAY), 500, Easing.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
box.FadeColour(IsHovered ? colours.Orange3.Lighten(0.2f) : colours.Orange3, 500, Easing.OutQuint);
|
||||
triangles.FadeColour(ColourInfo.GradientVertical(colours.Orange3.Lighten(0.2f), colours.Orange3), 500, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
if (Enabled.Value)
|
||||
{
|
||||
updateChevronsSpacing();
|
||||
updateColours();
|
||||
background.FadeTo(0.4f, 500, Easing.OutQuint);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateChevronsSpacing();
|
||||
updateColours();
|
||||
background.FadeTo(0.2f, 500, Easing.OutQuint);
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
if (Enabled.Value)
|
||||
aspect.ScaleTo(0.75f, 2000, Easing.OutQuint);
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
if (Enabled.Value)
|
||||
aspect.ScaleTo(1, 1000, Easing.OutElastic);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (!Enabled.Value)
|
||||
return false;
|
||||
|
||||
sampleConfirm.Play();
|
||||
|
||||
box.FlashColour(Color4.White, 500, Easing.OutQuint);
|
||||
aspect.ScaleTo(1.2f, 2000, Easing.OutQuint);
|
||||
|
||||
base.OnClick(e);
|
||||
|
||||
Enabled.Value = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
countText.Scale = new Vector2(Math.Min(0.85f * aspect.DrawWidth / countText.DrawWidth, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,20 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||
foreach (var r in group)
|
||||
results[r.result] = judgementCount;
|
||||
}
|
||||
|
||||
// Add Pool for Mania
|
||||
if (ruleset.Value.ShortName == "mania")
|
||||
{
|
||||
var poolCount = new JudgementCount
|
||||
{
|
||||
DisplayName = "Pool",
|
||||
Types = new[] { HitResult.Pool },
|
||||
ResultCount = new BindableInt()
|
||||
};
|
||||
|
||||
counters.Add(poolCount);
|
||||
results[HitResult.Pool] = poolCount;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
||||
@@ -10,7 +10,9 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
@@ -19,6 +21,7 @@ using osu.Framework.Input.Events;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Input.Bindings;
|
||||
@@ -41,12 +44,18 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
protected FadeContainer FadingContent { get; private set; }
|
||||
|
||||
private Button button;
|
||||
private OsuClickableContainer button;
|
||||
|
||||
private ButtonContainer buttonContainer;
|
||||
private Circle remainingTimeBox;
|
||||
protected Circle RemainingTimeBox { get; private set; }
|
||||
|
||||
private double displayTime;
|
||||
|
||||
/// <summary>
|
||||
/// Becomes <see langword="false"/> when the overlay starts fading out.
|
||||
/// </summary>
|
||||
private bool isClickable;
|
||||
|
||||
private bool skipQueued;
|
||||
|
||||
[Resolved]
|
||||
@@ -83,17 +92,13 @@ namespace osu.Game.Screens.Play
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
button = new Button
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
remainingTimeBox = new Circle
|
||||
button = CreateButton(),
|
||||
RemainingTimeBox = new Circle
|
||||
{
|
||||
Height = 5,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Colour = colours.Yellow,
|
||||
Colour = colours.Orange3,
|
||||
RelativeSizeAxes = Axes.X
|
||||
}
|
||||
}
|
||||
@@ -101,6 +106,12 @@ namespace osu.Game.Screens.Play
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual OsuClickableContainer CreateButton() => new Button
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
|
||||
private const double fade_time = 300;
|
||||
|
||||
private double fadeOutBeginTime => startTime - MasterGameplayClockContainer.MINIMUM_SKIP_TIME;
|
||||
@@ -174,10 +185,13 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
double progress = Math.Max(0, 1 - (gameplayClock.CurrentTime - displayTime) / (fadeOutBeginTime - displayTime));
|
||||
|
||||
remainingTimeBox.Width = (float)Interpolation.Lerp(remainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1));
|
||||
RemainingTimeBox.Width = (float)Interpolation.Lerp(RemainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1));
|
||||
|
||||
isClickable = progress > 0;
|
||||
button.Enabled.Value = isClickable;
|
||||
|
||||
if (!isClickable)
|
||||
button.Enabled.Value = false;
|
||||
|
||||
buttonContainer.State.Value = isClickable ? Visibility.Visible : Visibility.Hidden;
|
||||
}
|
||||
|
||||
@@ -220,7 +234,7 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
float progress = (float)(gameplayClock.CurrentTime - displayTime) / (float)(fadeOutBeginTime - displayTime);
|
||||
float newWidth = 1 - Math.Clamp(progress, 0, 1);
|
||||
remainingTimeBox.ResizeWidthTo(newWidth, timingPoint.BeatLength * 3.5, Easing.OutQuint);
|
||||
RemainingTimeBox.ResizeWidthTo(newWidth, timingPoint.BeatLength * 3.5, Easing.OutQuint);
|
||||
}
|
||||
|
||||
public partial class FadeContainer : Container, IStateful<Visibility>
|
||||
@@ -328,8 +342,8 @@ namespace osu.Game.Screens.Play
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, AudioManager audio)
|
||||
{
|
||||
colourNormal = colours.Yellow;
|
||||
colourHover = colours.YellowDark;
|
||||
colourNormal = colours.Orange3;
|
||||
colourHover = colours.Orange3.Lighten(0.2f);
|
||||
|
||||
sampleConfirm = audio.Samples.Get(@"UI/submit-select");
|
||||
|
||||
@@ -356,6 +370,11 @@ namespace osu.Game.Screens.Play
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourNormal,
|
||||
},
|
||||
new TrianglesV2
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientVertical(colourNormal.Lighten(0.2f), colourNormal)
|
||||
},
|
||||
flow = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
|
||||
@@ -30,7 +30,6 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
[Cached(typeof(IPreviewTrackOwner))]
|
||||
public partial class SoloSpectatorScreen : SpectatorScreen, IPreviewTrackOwner
|
||||
{
|
||||
[Resolved]
|
||||
|
||||
@@ -33,8 +33,6 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
private const float corner_radius = 10;
|
||||
|
||||
public static WorkingBeatmap SelectedWorkingBeatmap = null!;
|
||||
|
||||
[Resolved]
|
||||
private IBindable<WorkingBeatmap> working { get; set; } = null!;
|
||||
|
||||
@@ -183,11 +181,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
working.BindValueChanged(value =>
|
||||
{
|
||||
SelectedWorkingBeatmap = value.NewValue;
|
||||
updateDisplay();
|
||||
});
|
||||
working.BindValueChanged(_ => updateDisplay());
|
||||
ruleset.BindValueChanged(_ => updateDisplay());
|
||||
onlineLookupResult.BindValueChanged(_ => updateDisplay());
|
||||
|
||||
|
||||
@@ -818,7 +818,8 @@ namespace osu.Game.Screens.SelectV2
|
||||
// Probably needs more thought because this needs to be in every `ApplyToBackground` currently to restore sane defaults.
|
||||
backgroundModeBeatmap.FadeColour(Color4.White, 250);
|
||||
|
||||
backgroundModeBeatmap.BlurAmount.Value = revealingBackground == null && configBackgroundBlur.Value ? 20 : 0f;
|
||||
bool backgroundRevealActive = revealingBackground?.State == ScheduledDelegate.RunState.Running || revealingBackground?.State == ScheduledDelegate.RunState.Complete;
|
||||
backgroundModeBeatmap.BlurAmount.Value = configBackgroundBlur.Value && !backgroundRevealActive ? 20 : 0f;
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -417,7 +417,7 @@ namespace osu.Game.Skinning.Components
|
||||
applyEzStyleEffect(drawable, new Vector2(1f));
|
||||
break;
|
||||
|
||||
// case HitResult.Pool:
|
||||
case HitResult.Pool:
|
||||
case HitResult.Miss:
|
||||
// 中心小状态,放大后快速消失
|
||||
applyEzStyleEffect(drawable, new Vector2(1f));
|
||||
|
||||
@@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@@ -55,6 +56,7 @@ namespace osu.Game.Tests.Visual
|
||||
var playable = Beatmap.Value.GetPlayableBeatmap(rulesetInfo);
|
||||
playable.BeatmapInfo.Ruleset = rulesetInfo;
|
||||
playable.Difficulty.CircleSize = 2;
|
||||
playable.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||
return playable;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="20.1.0" />
|
||||
<!-- <PackageReference Include="ppy.osu.Framework" Version="2025.1205.1" />-->
|
||||
<!-- <PackageReference Include="ppy.osu.Game.Resources" Version="2025.1125.0" />-->
|
||||
<PackageReference Include="Sentry" Version="5.1.1" />
|
||||
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
||||
<PackageReference Include="SharpCompress" Version="0.39.0" />
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
<MtouchInterpreter>-all</MtouchInterpreter>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2025.1121.1" />
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2025.1205.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user