mirror of
https://github.com/ppy/osu.git
synced 2025-03-28 20:47:22 +08:00
Merge branch 'master' into catcher-trail-entry
This commit is contained in:
commit
9b98014606
@ -190,3 +190,5 @@ dotnet_diagnostic.CA2225.severity = none
|
|||||||
|
|
||||||
# Banned APIs
|
# Banned APIs
|
||||||
dotnet_diagnostic.RS0030.severity = error
|
dotnet_diagnostic.RS0030.severity = error
|
||||||
|
|
||||||
|
dotnet_diagnostic.OLOC001.license_header = // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.\n// See the LICENCE file in the repository root for full licence text.
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.722.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.730.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.728.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.728.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
<PackageReference Include="Xamarin.Essentials" Version="1.7.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
@ -130,7 +130,8 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
return new Mod[]
|
return new Mod[]
|
||||||
{
|
{
|
||||||
new MultiMod(new ModWindUp(), new ModWindDown()),
|
new MultiMod(new ModWindUp(), new ModWindDown()),
|
||||||
new CatchModFloatingFruits()
|
new CatchModFloatingFruits(),
|
||||||
|
new CatchModMuted(),
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
12
osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs
Normal file
12
osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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 osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Mods
|
||||||
|
{
|
||||||
|
public class CatchModMuted : ModMuted<CatchHitObject>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -253,7 +253,8 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
case ModType.Fun:
|
case ModType.Fun:
|
||||||
return new Mod[]
|
return new Mod[]
|
||||||
{
|
{
|
||||||
new MultiMod(new ModWindUp(), new ModWindDown())
|
new MultiMod(new ModWindUp(), new ModWindDown()),
|
||||||
|
new ManiaModMuted(),
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
12
osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs
Normal file
12
osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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 osu.Game.Rulesets.Mania.Objects;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Mods
|
||||||
|
{
|
||||||
|
public class ManiaModMuted : ModMuted<ManiaHitObject>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
12
osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs
Normal file
12
osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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 osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Mods
|
||||||
|
{
|
||||||
|
public class OsuModMuted : ModMuted<OsuHitObject>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -4,8 +4,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Audio.Track;
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
@ -16,7 +14,6 @@ using osu.Game.Beatmaps.ControlPoints;
|
|||||||
using osu.Game.Beatmaps.Timing;
|
using osu.Game.Beatmaps.Timing;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
|
||||||
using osu.Game.Overlays.Settings;
|
using osu.Game.Overlays.Settings;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
@ -29,7 +26,6 @@ using osu.Game.Rulesets.Osu.UI;
|
|||||||
using osu.Game.Rulesets.Osu.Utils;
|
using osu.Game.Rulesets.Osu.Utils;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Skinning;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -67,11 +63,6 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const float distance_cap = 380f;
|
private const float distance_cap = 380f;
|
||||||
|
|
||||||
// The distances from the hit objects to the borders of the playfield they start to "turn around" and curve towards the middle.
|
|
||||||
// The closer the hit objects draw to the border, the sharper the turn
|
|
||||||
private const byte border_distance_x = 192;
|
|
||||||
private const byte border_distance_y = 144;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The extent of rotation towards playfield centre when a circle is near the edge
|
/// The extent of rotation towards playfield centre when a circle is near the edge
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -341,46 +332,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
|
|
||||||
public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset)
|
public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset)
|
||||||
{
|
{
|
||||||
drawableRuleset.Overlays.Add(new TargetBeatContainer(drawableRuleset.Beatmap.HitObjects.First().StartTime));
|
drawableRuleset.Overlays.Add(new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime));
|
||||||
}
|
|
||||||
|
|
||||||
public class TargetBeatContainer : BeatSyncedContainer
|
|
||||||
{
|
|
||||||
private readonly double firstHitTime;
|
|
||||||
|
|
||||||
private PausableSkinnableSound sample;
|
|
||||||
|
|
||||||
public TargetBeatContainer(double firstHitTime)
|
|
||||||
{
|
|
||||||
this.firstHitTime = firstHitTime;
|
|
||||||
AllowMistimedEventFiring = false;
|
|
||||||
Divisor = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana"))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
|
||||||
{
|
|
||||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
|
||||||
|
|
||||||
if (!IsBeatSyncedWithTrack) return;
|
|
||||||
|
|
||||||
int timeSignature = (int)timingPoint.TimeSignature;
|
|
||||||
|
|
||||||
// play metronome from one measure before the first object.
|
|
||||||
if (BeatSyncClock.CurrentTime < firstHitTime - timingPoint.BeatLength * timeSignature)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sample.Frequency.Value = beatIndex % timeSignature == 0 ? 1 : 0.5f;
|
|
||||||
sample.Play();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -189,6 +189,7 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
new OsuModTraceable(),
|
new OsuModTraceable(),
|
||||||
new OsuModBarrelRoll(),
|
new OsuModBarrelRoll(),
|
||||||
new OsuModApproachDifferent(),
|
new OsuModApproachDifferent(),
|
||||||
|
new OsuModMuted(),
|
||||||
};
|
};
|
||||||
|
|
||||||
case ModType.System:
|
case ModType.System:
|
||||||
|
@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
|
|
||||||
private void onJudgementLoaded(DrawableOsuJudgement judgement)
|
private void onJudgementLoaded(DrawableOsuJudgement judgement)
|
||||||
{
|
{
|
||||||
judgementAboveHitObjectLayer.Add(judgement.GetProxyAboveHitObjectsContent());
|
judgementAboveHitObjectLayer.Add(judgement.ProxiedAboveHitObjectsContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
@ -150,6 +150,10 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
DrawableOsuJudgement explosion = poolDictionary[result.Type].Get(doj => doj.Apply(result, judgedObject));
|
DrawableOsuJudgement explosion = poolDictionary[result.Type].Get(doj => doj.Apply(result, judgedObject));
|
||||||
|
|
||||||
judgementLayer.Add(explosion);
|
judgementLayer.Add(explosion);
|
||||||
|
|
||||||
|
// the proxied content is added to judgementAboveHitObjectLayer once, on first load, and never removed from it.
|
||||||
|
// ensure that ordering is consistent with expectations (latest judgement should be front-most).
|
||||||
|
judgementAboveHitObjectLayer.ChangeChildDepth(explosion.ProxiedAboveHitObjectsContent, (float)-result.TimeAbsolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObjectContainer.ReceivePositionalInputAt(screenSpacePos);
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObjectContainer.ReceivePositionalInputAt(screenSpacePos);
|
||||||
|
12
osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs
Normal file
12
osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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 osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.Mods
|
||||||
|
{
|
||||||
|
public class TaikoModMuted : ModMuted<TaikoHitObject>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -149,7 +149,8 @@ namespace osu.Game.Rulesets.Taiko
|
|||||||
case ModType.Fun:
|
case ModType.Fun:
|
||||||
return new Mod[]
|
return new Mod[]
|
||||||
{
|
{
|
||||||
new MultiMod(new ModWindUp(), new ModWindDown())
|
new MultiMod(new ModWindUp(), new ModWindDown()),
|
||||||
|
new TaikoModMuted(),
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
41
osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs
Normal file
41
osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// 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.Extensions;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.NonVisual
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TimeDisplayExtensionTest
|
||||||
|
{
|
||||||
|
private static readonly object[][] editor_formatted_duration_tests =
|
||||||
|
{
|
||||||
|
new object[] { new TimeSpan(0, 0, 0, 0, 50), "00:00:050" },
|
||||||
|
new object[] { new TimeSpan(0, 0, 0, 10, 50), "00:10:050" },
|
||||||
|
new object[] { new TimeSpan(0, 0, 5, 10), "05:10:000" },
|
||||||
|
new object[] { new TimeSpan(0, 1, 5, 10), "65:10:000" },
|
||||||
|
};
|
||||||
|
|
||||||
|
[TestCaseSource(nameof(editor_formatted_duration_tests))]
|
||||||
|
public void TestEditorFormat(TimeSpan input, string expectedOutput)
|
||||||
|
{
|
||||||
|
Assert.AreEqual(expectedOutput, input.ToEditorFormattedString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly object[][] formatted_duration_tests =
|
||||||
|
{
|
||||||
|
new object[] { new TimeSpan(0, 0, 10), "00:10" },
|
||||||
|
new object[] { new TimeSpan(0, 5, 10), "05:10" },
|
||||||
|
new object[] { new TimeSpan(1, 5, 10), "01:05:10" },
|
||||||
|
new object[] { new TimeSpan(1, 1, 5, 10), "01:01:05:10" },
|
||||||
|
};
|
||||||
|
|
||||||
|
[TestCaseSource(nameof(formatted_duration_tests))]
|
||||||
|
public void TestFormattedDuration(TimeSpan input, string expectedOutput)
|
||||||
|
{
|
||||||
|
Assert.AreEqual(expectedOutput, input.ToFormattedDuration().ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -168,8 +168,8 @@ namespace osu.Game.Tests.Online
|
|||||||
|
|
||||||
public override async Task<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
public override async Task<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
await AllowImport.Task;
|
await AllowImport.Task.ConfigureAwait(false);
|
||||||
return await (CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken));
|
return await (CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,9 +143,9 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
public override async Task<StarDifficulty> GetDifficultyAsync(BeatmapInfo beatmapInfo, RulesetInfo rulesetInfo = null, IEnumerable<Mod> mods = null, CancellationToken cancellationToken = default)
|
public override async Task<StarDifficulty> GetDifficultyAsync(BeatmapInfo beatmapInfo, RulesetInfo rulesetInfo = null, IEnumerable<Mod> mods = null, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
if (blockCalculation)
|
if (blockCalculation)
|
||||||
await calculationBlocker.Task;
|
await calculationBlocker.Task.ConfigureAwait(false);
|
||||||
|
|
||||||
return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken);
|
return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
// 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.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Graphics.Cursor;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.UserInterface
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
{
|
{
|
||||||
public class TestSceneLabelledColourPalette : OsuTestScene
|
public class TestSceneLabelledColourPalette : OsuManualInputManagerTestScene
|
||||||
{
|
{
|
||||||
private LabelledColourPalette component;
|
private LabelledColourPalette component;
|
||||||
|
|
||||||
@ -30,21 +35,41 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
}, 8);
|
}, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestUserInteractions()
|
||||||
|
{
|
||||||
|
createColourPalette();
|
||||||
|
assertColourCount(4);
|
||||||
|
|
||||||
|
clickAddColour();
|
||||||
|
assertColourCount(5);
|
||||||
|
|
||||||
|
deleteFirstColour();
|
||||||
|
assertColourCount(4);
|
||||||
|
|
||||||
|
clickFirstColour();
|
||||||
|
AddAssert("colour picker spawned", () => this.ChildrenOfType<OsuColourPicker>().Any());
|
||||||
|
}
|
||||||
|
|
||||||
private void createColourPalette(bool hasDescription = false)
|
private void createColourPalette(bool hasDescription = false)
|
||||||
{
|
{
|
||||||
AddStep("create component", () =>
|
AddStep("create component", () =>
|
||||||
{
|
{
|
||||||
Child = new Container
|
Child = new OsuContextMenuContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Origin = Anchor.Centre,
|
Child = new Container
|
||||||
Width = 500,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Child = component = new LabelledColourPalette
|
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
ColourNamePrefix = "My colour #"
|
Width = 500,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Child = component = new LabelledColourPalette
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
ColourNamePrefix = "My colour #"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,18 +78,49 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
component.Colours.AddRange(new[]
|
component.Colours.AddRange(new[]
|
||||||
{
|
{
|
||||||
Color4.DarkRed,
|
Colour4.DarkRed,
|
||||||
Color4.Aquamarine,
|
Colour4.Aquamarine,
|
||||||
Color4.Goldenrod,
|
Colour4.Goldenrod,
|
||||||
Color4.Gainsboro
|
Colour4.Gainsboro
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color4 randomColour() => new Color4(
|
private Colour4 randomColour() => new Color4(
|
||||||
RNG.NextSingle(),
|
RNG.NextSingle(),
|
||||||
RNG.NextSingle(),
|
RNG.NextSingle(),
|
||||||
RNG.NextSingle(),
|
RNG.NextSingle(),
|
||||||
1);
|
1);
|
||||||
|
|
||||||
|
private void assertColourCount(int count) => AddAssert($"colour count is {count}", () => component.Colours.Count == count);
|
||||||
|
|
||||||
|
private void clickAddColour() => AddStep("click new colour button", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(this.ChildrenOfType<ColourPalette.AddColourButton>().Single());
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
private void clickFirstColour() => AddStep("click first colour", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(this.ChildrenOfType<ColourDisplay>().First());
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
private void deleteFirstColour()
|
||||||
|
{
|
||||||
|
AddStep("right-click first colour", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(this.ChildrenOfType<ColourDisplay>().First());
|
||||||
|
InputManager.Click(MouseButton.Right);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for menu", () => this.ChildrenOfType<OsuContextMenu>().Any());
|
||||||
|
|
||||||
|
AddStep("click delete", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(this.ChildrenOfType<DrawableOsuMenuItem>().Single());
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,18 @@
|
|||||||
// 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.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework;
|
using osu.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Tournament.Configuration;
|
|
||||||
using osu.Game.Tests;
|
using osu.Game.Tests;
|
||||||
|
using osu.Game.Tournament.Configuration;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.NonVisual
|
namespace osu.Game.Tournament.Tests.NonVisual
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class CustomTourneyDirectoryTest
|
public class CustomTourneyDirectoryTest : TournamentHostTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDefaultDirectory()
|
public void TestDefaultDirectory()
|
||||||
@ -24,7 +21,7 @@ namespace osu.Game.Tournament.Tests.NonVisual
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var osu = loadOsu(host);
|
var osu = LoadTournament(host);
|
||||||
var storage = osu.Dependencies.Get<Storage>();
|
var storage = osu.Dependencies.Get<Storage>();
|
||||||
|
|
||||||
Assert.That(storage.GetFullPath("."), Is.EqualTo(Path.Combine(host.Storage.GetFullPath("."), "tournaments", "default")));
|
Assert.That(storage.GetFullPath("."), Is.EqualTo(Path.Combine(host.Storage.GetFullPath("."), "tournaments", "default")));
|
||||||
@ -54,7 +51,7 @@ namespace osu.Game.Tournament.Tests.NonVisual
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var osu = loadOsu(host);
|
var osu = LoadTournament(host);
|
||||||
|
|
||||||
storage = osu.Dependencies.Get<Storage>();
|
storage = osu.Dependencies.Get<Storage>();
|
||||||
|
|
||||||
@ -111,7 +108,7 @@ namespace osu.Game.Tournament.Tests.NonVisual
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var osu = loadOsu(host);
|
var osu = LoadTournament(host);
|
||||||
|
|
||||||
var storage = osu.Dependencies.Get<Storage>();
|
var storage = osu.Dependencies.Get<Storage>();
|
||||||
|
|
||||||
@ -151,25 +148,6 @@ namespace osu.Game.Tournament.Tests.NonVisual
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TournamentGameBase loadOsu(GameHost host)
|
|
||||||
{
|
|
||||||
var osu = new TournamentGameBase();
|
|
||||||
Task.Run(() => host.Run(osu))
|
|
||||||
.ContinueWith(t => Assert.Fail($"Host threw exception {t.Exception}"), TaskContinuationOptions.OnlyOnFaulted);
|
|
||||||
waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time");
|
|
||||||
return osu;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void waitForOrAssert(Func<bool> result, string failureMessage, int timeout = 90000)
|
|
||||||
{
|
|
||||||
Task task = Task.Run(() =>
|
|
||||||
{
|
|
||||||
while (!result()) Thread.Sleep(200);
|
|
||||||
});
|
|
||||||
|
|
||||||
Assert.IsTrue(task.Wait(timeout), failureMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string basePath(string testInstance) => Path.Combine(RuntimeInfo.StartupDirectory, "headless", testInstance);
|
private string basePath(string testInstance) => Path.Combine(RuntimeInfo.StartupDirectory, "headless", testInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
45
osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs
Normal file
45
osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// 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.IO;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Platform;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Tests;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Tests.NonVisual
|
||||||
|
{
|
||||||
|
public class DataLoadTest : TournamentHostTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestUnavailableRuleset()
|
||||||
|
{
|
||||||
|
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestUnavailableRuleset)))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var osu = new TestTournament();
|
||||||
|
|
||||||
|
LoadTournament(host, osu);
|
||||||
|
var storage = osu.Dependencies.Get<Storage>();
|
||||||
|
|
||||||
|
Assert.That(storage.GetFullPath("."), Is.EqualTo(Path.Combine(host.Storage.GetFullPath("."), "tournaments", "default")));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
host.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestTournament : TournamentGameBase
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Ruleset.Value = new RulesetInfo(); // not available
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +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.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework;
|
using osu.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -15,7 +12,7 @@ using osu.Game.Tournament.IPC;
|
|||||||
namespace osu.Game.Tournament.Tests.NonVisual
|
namespace osu.Game.Tournament.Tests.NonVisual
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class IPCLocationTest
|
public class IPCLocationTest : TournamentHostTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void CheckIPCLocation()
|
public void CheckIPCLocation()
|
||||||
@ -34,11 +31,11 @@ namespace osu.Game.Tournament.Tests.NonVisual
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var osu = loadOsu(host);
|
var osu = LoadTournament(host);
|
||||||
TournamentStorage storage = (TournamentStorage)osu.Dependencies.Get<Storage>();
|
TournamentStorage storage = (TournamentStorage)osu.Dependencies.Get<Storage>();
|
||||||
FileBasedIPC ipc = null;
|
FileBasedIPC ipc = null;
|
||||||
|
|
||||||
waitForOrAssert(() => (ipc = osu.Dependencies.Get<MatchIPCInfo>() as FileBasedIPC) != null, @"ipc could not be populated in a reasonable amount of time");
|
WaitForOrAssert(() => (ipc = osu.Dependencies.Get<MatchIPCInfo>() as FileBasedIPC) != null, @"ipc could not be populated in a reasonable amount of time");
|
||||||
|
|
||||||
Assert.True(ipc.SetIPCLocation(testStableInstallDirectory));
|
Assert.True(ipc.SetIPCLocation(testStableInstallDirectory));
|
||||||
Assert.True(storage.AllTournaments.Exists("stable.json"));
|
Assert.True(storage.AllTournaments.Exists("stable.json"));
|
||||||
@ -51,24 +48,5 @@ namespace osu.Game.Tournament.Tests.NonVisual
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TournamentGameBase loadOsu(GameHost host)
|
|
||||||
{
|
|
||||||
var osu = new TournamentGameBase();
|
|
||||||
Task.Run(() => host.Run(osu))
|
|
||||||
.ContinueWith(t => Assert.Fail($"Host threw exception {t.Exception}"), TaskContinuationOptions.OnlyOnFaulted);
|
|
||||||
waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time");
|
|
||||||
return osu;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void waitForOrAssert(Func<bool> result, string failureMessage, int timeout = 90000)
|
|
||||||
{
|
|
||||||
Task task = Task.Run(() =>
|
|
||||||
{
|
|
||||||
while (!result()) Thread.Sleep(200);
|
|
||||||
});
|
|
||||||
|
|
||||||
Assert.IsTrue(task.Wait(timeout), failureMessage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs
Normal file
33
osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// 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 System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Platform;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Tests.NonVisual
|
||||||
|
{
|
||||||
|
public abstract class TournamentHostTest
|
||||||
|
{
|
||||||
|
public static TournamentGameBase LoadTournament(GameHost host, TournamentGameBase tournament = null)
|
||||||
|
{
|
||||||
|
tournament ??= new TournamentGameBase();
|
||||||
|
Task.Run(() => host.Run(tournament))
|
||||||
|
.ContinueWith(t => Assert.Fail($"Host threw exception {t.Exception}"), TaskContinuationOptions.OnlyOnFaulted);
|
||||||
|
WaitForOrAssert(() => tournament.IsLoaded, @"osu! failed to start in a reasonable amount of time");
|
||||||
|
return tournament;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WaitForOrAssert(Func<bool> result, string failureMessage, int timeout = 90000)
|
||||||
|
{
|
||||||
|
Task task = Task.Run(() =>
|
||||||
|
{
|
||||||
|
while (!result()) Thread.Sleep(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.IsTrue(task.Wait(timeout), failureMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
// 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 osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -11,6 +10,7 @@ using osu.Framework.Graphics.Shapes;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.Legacy;
|
using osu.Game.Beatmaps.Legacy;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
@ -198,8 +198,8 @@ namespace osu.Game.Tournament.Components
|
|||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new DiffPiece(("Length", TimeSpan.FromMilliseconds(length).ToString(@"mm\:ss"))),
|
new DiffPiece(("Length", length.ToFormattedDuration().ToString())),
|
||||||
new DiffPiece(("BPM", $"{bpm:0.#}"))
|
new DiffPiece(("BPM", $"{bpm:0.#}")),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
|
@ -27,6 +27,9 @@ namespace osu.Game.Tournament.Screens.Drawings.Components
|
|||||||
{
|
{
|
||||||
var teams = new List<TournamentTeam>();
|
var teams = new List<TournamentTeam>();
|
||||||
|
|
||||||
|
if (!storage.Exists(teams_filename))
|
||||||
|
return teams;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (Stream stream = storage.GetStream(teams_filename, FileAccess.Read, FileMode.Open))
|
using (Stream stream = storage.GetStream(teams_filename, FileAccess.Read, FileMode.Open))
|
||||||
|
@ -9,11 +9,13 @@ using System.Threading.Tasks;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Tournament.Components;
|
using osu.Game.Tournament.Components;
|
||||||
using osu.Game.Tournament.Models;
|
using osu.Game.Tournament.Models;
|
||||||
using osu.Game.Tournament.Screens.Drawings.Components;
|
using osu.Game.Tournament.Screens.Drawings.Components;
|
||||||
@ -51,6 +53,29 @@ namespace osu.Game.Tournament.Screens.Drawings
|
|||||||
|
|
||||||
if (!TeamList.Teams.Any())
|
if (!TeamList.Teams.Any())
|
||||||
{
|
{
|
||||||
|
LinkFlowContainer links;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Colour = Color4.Black,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Height = 0.3f,
|
||||||
|
},
|
||||||
|
new WarningBox("No drawings.txt file found. Please create one and restart the client."),
|
||||||
|
links = new LinkFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Y = 60,
|
||||||
|
AutoSizeAxes = Axes.Both
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
links.AddLink("Click for details on the file format", "https://osu.ppy.sh/wiki/en/Tournament_Drawings", t => t.Colour = Color4.White);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,9 @@ namespace osu.Game.Tournament
|
|||||||
}
|
}
|
||||||
|
|
||||||
ladder ??= new LadderInfo();
|
ladder ??= new LadderInfo();
|
||||||
ladder.Ruleset.Value ??= RulesetStore.AvailableRulesets.First();
|
|
||||||
|
ladder.Ruleset.Value = RulesetStore.GetRuleset(ladder.Ruleset.Value?.ShortName)
|
||||||
|
?? RulesetStore.AvailableRulesets.First();
|
||||||
|
|
||||||
bool addedInfo = false;
|
bool addedInfo = false;
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
[*.cs]
|
[*.cs]
|
||||||
dotnet_diagnostic.OLOC001.prefix_namespace = osu.Game.Resources.Localisation
|
dotnet_diagnostic.OLOC001.prefix_namespace = osu.Game.Resources.Localisation
|
||||||
|
dotnet_diagnostic.OLOC001.license_header = // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.\n// See the LICENCE file in the repository root for full licence text.
|
@ -1,26 +0,0 @@
|
|||||||
// 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;
|
|
||||||
|
|
||||||
namespace osu.Game.Extensions
|
|
||||||
{
|
|
||||||
public static class EditorDisplayExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Get an editor formatted string (mm:ss:mss)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="milliseconds">A time value in milliseconds.</param>
|
|
||||||
/// <returns>An editor formatted display string.</returns>
|
|
||||||
public static string ToEditorFormattedString(this double milliseconds) =>
|
|
||||||
ToEditorFormattedString(TimeSpan.FromMilliseconds(milliseconds));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get an editor formatted string (mm:ss:mss)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timeSpan">A time value.</param>
|
|
||||||
/// <returns>An editor formatted display string.</returns>
|
|
||||||
public static string ToEditorFormattedString(this TimeSpan timeSpan) =>
|
|
||||||
$"{(timeSpan < TimeSpan.Zero ? "-" : string.Empty)}{timeSpan:mm\\:ss\\:fff}";
|
|
||||||
}
|
|
||||||
}
|
|
51
osu.Game/Extensions/TimeDisplayExtensions.cs
Normal file
51
osu.Game/Extensions/TimeDisplayExtensions.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// 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 osu.Framework.Localisation;
|
||||||
|
|
||||||
|
namespace osu.Game.Extensions
|
||||||
|
{
|
||||||
|
public static class TimeDisplayExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get an editor formatted string (mm:ss:mss)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="milliseconds">A time value in milliseconds.</param>
|
||||||
|
/// <returns>An editor formatted display string.</returns>
|
||||||
|
public static string ToEditorFormattedString(this double milliseconds) =>
|
||||||
|
ToEditorFormattedString(TimeSpan.FromMilliseconds(milliseconds));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an editor formatted string (mm:ss:mss)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timeSpan">A time value.</param>
|
||||||
|
/// <returns>An editor formatted display string.</returns>
|
||||||
|
public static string ToEditorFormattedString(this TimeSpan timeSpan) =>
|
||||||
|
$"{(timeSpan < TimeSpan.Zero ? "-" : string.Empty)}{(int)timeSpan.TotalMinutes:00}:{timeSpan:ss\\:fff}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a formatted duration (dd:hh:mm:ss with days/hours omitted if zero).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="milliseconds">A duration in milliseconds.</param>
|
||||||
|
/// <returns>A formatted duration string.</returns>
|
||||||
|
public static LocalisableString ToFormattedDuration(this double milliseconds) =>
|
||||||
|
ToFormattedDuration(TimeSpan.FromMilliseconds(milliseconds));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a formatted duration (dd:hh:mm:ss with days/hours omitted if zero).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timeSpan">A duration value.</param>
|
||||||
|
/// <returns>A formatted duration string.</returns>
|
||||||
|
public static LocalisableString ToFormattedDuration(this TimeSpan timeSpan)
|
||||||
|
{
|
||||||
|
if (timeSpan.TotalDays >= 1)
|
||||||
|
return new LocalisableFormattableString(timeSpan, @"dd\:hh\:mm\:ss");
|
||||||
|
|
||||||
|
if (timeSpan.TotalHours >= 1)
|
||||||
|
return new LocalisableFormattableString(timeSpan, @"hh\:mm\:ss");
|
||||||
|
|
||||||
|
return new LocalisableFormattableString(timeSpan, @"mm\:ss");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
@ -25,6 +26,9 @@ namespace osu.Game.Graphics.Containers
|
|||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
private OsuGame game { get; set; }
|
private OsuGame game { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private GameHost host { get; set; }
|
||||||
|
|
||||||
public void AddLinks(string text, List<Link> links)
|
public void AddLinks(string text, List<Link> links)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(text) || links == null)
|
if (string.IsNullOrEmpty(text) || links == null)
|
||||||
@ -91,8 +95,11 @@ namespace osu.Game.Graphics.Containers
|
|||||||
{
|
{
|
||||||
if (action != null)
|
if (action != null)
|
||||||
action();
|
action();
|
||||||
else
|
else if (game != null)
|
||||||
game?.HandleLink(link);
|
game.HandleLink(link);
|
||||||
|
// fallback to handle cases where OsuGame is not available, ie. tournament client.
|
||||||
|
else if (link.Action == LinkAction.External)
|
||||||
|
host.OpenUrlExternally(link.Argument);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -59,33 +60,37 @@ namespace osu.Game.Graphics.Containers
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
InternalChild = new GridContainer
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
new GridContainer
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Content = new[]
|
|
||||||
{
|
{
|
||||||
new[]
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Content = new[]
|
||||||
{
|
{
|
||||||
handleContainer = new Container
|
new[]
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
handleContainer = new Container
|
||||||
Origin = Anchor.Centre,
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Padding = new MarginPadding { Horizontal = 5 },
|
|
||||||
Child = handle = new PlaylistItemHandle
|
|
||||||
{
|
{
|
||||||
Size = new Vector2(12),
|
Anchor = Anchor.Centre,
|
||||||
Colour = HandleColour,
|
Origin = Anchor.Centre,
|
||||||
AlwaysPresent = true,
|
AutoSizeAxes = Axes.Both,
|
||||||
Alpha = 0
|
Padding = new MarginPadding { Horizontal = 5 },
|
||||||
}
|
Child = handle = new PlaylistItemHandle
|
||||||
},
|
{
|
||||||
CreateContent()
|
Size = new Vector2(12),
|
||||||
}
|
Colour = HandleColour,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CreateContent()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) },
|
||||||
|
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }
|
||||||
},
|
},
|
||||||
ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) },
|
new HoverClickSounds()
|
||||||
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
{
|
{
|
||||||
Size = TwoLayerButton.SIZE_EXTENDED;
|
Size = TwoLayerButton.SIZE_EXTENDED;
|
||||||
|
|
||||||
Child = button = new TwoLayerButton
|
Child = button = new TwoLayerButton(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopLeft,
|
Anchor = Anchor.TopLeft,
|
||||||
Origin = Anchor.TopLeft,
|
Origin = Anchor.TopLeft,
|
||||||
|
@ -56,6 +56,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
private Vector2 hoverSpacing => new Vector2(3f, 0f);
|
private Vector2 hoverSpacing => new Vector2(3f, 0f);
|
||||||
|
|
||||||
public DialogButton()
|
public DialogButton()
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
|
|
||||||
|
@ -23,14 +23,20 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private GameHost host { get; set; }
|
private GameHost host { get; set; }
|
||||||
|
|
||||||
|
private readonly SpriteIcon linkIcon;
|
||||||
|
|
||||||
public ExternalLinkButton(string link = null)
|
public ExternalLinkButton(string link = null)
|
||||||
{
|
{
|
||||||
Link = link;
|
Link = link;
|
||||||
Size = new Vector2(12);
|
Size = new Vector2(12);
|
||||||
InternalChild = new SpriteIcon
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
Icon = FontAwesome.Solid.ExternalLinkAlt,
|
linkIcon = new SpriteIcon
|
||||||
RelativeSizeAxes = Axes.Both
|
{
|
||||||
|
Icon = FontAwesome.Solid.ExternalLinkAlt,
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
new HoverClickSounds(HoverSampleSet.Submit)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,13 +48,13 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
{
|
{
|
||||||
InternalChild.FadeColour(hoverColour, 500, Easing.OutQuint);
|
linkIcon.FadeColour(hoverColour, 500, Easing.OutQuint);
|
||||||
return base.OnHover(e);
|
return base.OnHover(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
{
|
{
|
||||||
InternalChild.FadeColour(Color4.White, 500, Easing.OutQuint);
|
linkIcon.FadeColour(Color4.White, 500, Easing.OutQuint);
|
||||||
base.OnHoverLost(e);
|
base.OnHoverLost(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
[Description("default")]
|
[Description("default")]
|
||||||
Default,
|
Default,
|
||||||
|
|
||||||
[Description("soft")]
|
[Description("submit")]
|
||||||
Soft,
|
Submit,
|
||||||
|
|
||||||
[Description("button")]
|
[Description("button")]
|
||||||
Button,
|
Button,
|
||||||
|
@ -71,7 +71,8 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TwoLayerButton()
|
public TwoLayerButton(HoverSampleSet sampleSet = HoverSampleSet.Default)
|
||||||
|
: base(sampleSet)
|
||||||
{
|
{
|
||||||
Size = SIZE_RETRACTED;
|
Size = SIZE_RETRACTED;
|
||||||
Shear = shear;
|
Shear = shear;
|
||||||
|
@ -1,32 +1,39 @@
|
|||||||
// 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 osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterfaceV2
|
namespace osu.Game.Graphics.UserInterfaceV2
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A component which displays a colour along with related description text.
|
/// A component which displays a colour along with related description text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ColourDisplay : CompositeDrawable, IHasCurrentValue<Color4>
|
public class ColourDisplay : CompositeDrawable, IHasCurrentValue<Colour4>
|
||||||
{
|
{
|
||||||
private readonly BindableWithCurrent<Color4> current = new BindableWithCurrent<Color4>();
|
/// <summary>
|
||||||
|
/// Invoked when the user has requested the colour corresponding to this <see cref="ColourDisplay"/>
|
||||||
|
/// to be removed from its palette.
|
||||||
|
/// </summary>
|
||||||
|
public event Action<ColourDisplay> DeleteRequested;
|
||||||
|
|
||||||
|
private readonly BindableWithCurrent<Colour4> current = new BindableWithCurrent<Colour4>();
|
||||||
|
|
||||||
private Box fill;
|
|
||||||
private OsuSpriteText colourHexCode;
|
|
||||||
private OsuSpriteText colourName;
|
private OsuSpriteText colourName;
|
||||||
|
|
||||||
public Bindable<Color4> Current
|
public Bindable<Colour4> Current
|
||||||
{
|
{
|
||||||
get => current.Current;
|
get => current.Current;
|
||||||
set => current.Current = value;
|
set => current.Current = value;
|
||||||
@ -62,24 +69,10 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
Spacing = new Vector2(0, 10),
|
Spacing = new Vector2(0, 10),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new CircularContainer
|
new ColourCircle
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
Current = { BindTarget = Current },
|
||||||
Height = 100,
|
DeleteRequested = () => DeleteRequested?.Invoke(this)
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
fill = new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both
|
|
||||||
},
|
|
||||||
colourHexCode = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Font = OsuFont.Default.With(size: 12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
colourName = new OsuSpriteText
|
colourName = new OsuSpriteText
|
||||||
{
|
{
|
||||||
@ -90,18 +83,64 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
private class ColourCircle : OsuClickableContainer, IHasPopover, IHasContextMenu
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
public Bindable<Colour4> Current { get; } = new Bindable<Colour4>();
|
||||||
|
|
||||||
current.BindValueChanged(_ => updateColour(), true);
|
public Action DeleteRequested { get; set; }
|
||||||
}
|
|
||||||
|
|
||||||
private void updateColour()
|
private readonly Box fill;
|
||||||
{
|
private readonly OsuSpriteText colourHexCode;
|
||||||
fill.Colour = current.Value;
|
|
||||||
colourHexCode.Text = current.Value.ToHex();
|
public ColourCircle()
|
||||||
colourHexCode.Colour = OsuColour.ForegroundTextColourFor(current.Value);
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Height = 100;
|
||||||
|
CornerRadius = 50;
|
||||||
|
Masking = true;
|
||||||
|
Action = this.ShowPopover;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
fill = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
colourHexCode = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Font = OsuFont.Default.With(size: 12)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
Current.BindValueChanged(_ => updateColour(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateColour()
|
||||||
|
{
|
||||||
|
fill.Colour = Current.Value;
|
||||||
|
colourHexCode.Text = Current.Value.ToHex();
|
||||||
|
colourHexCode.Colour = OsuColour.ForegroundTextColourFor(Current.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Popover GetPopover() => new OsuPopover(false)
|
||||||
|
{
|
||||||
|
Child = new OsuColourPicker
|
||||||
|
{
|
||||||
|
Current = { BindTarget = Current }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public MenuItem[] ContextMenuItems => new MenuItem[]
|
||||||
|
{
|
||||||
|
new OsuMenuItem("Delete", MenuItemType.Destructive, () => DeleteRequested?.Invoke())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
// 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.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterfaceV2
|
namespace osu.Game.Graphics.UserInterfaceV2
|
||||||
{
|
{
|
||||||
@ -17,7 +22,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ColourPalette : CompositeDrawable
|
public class ColourPalette : CompositeDrawable
|
||||||
{
|
{
|
||||||
public BindableList<Color4> Colours { get; } = new BindableList<Color4>();
|
public BindableList<Colour4> Colours { get; } = new BindableList<Colour4>();
|
||||||
|
|
||||||
private string colourNamePrefix = "Colour";
|
private string colourNamePrefix = "Colour";
|
||||||
|
|
||||||
@ -36,36 +41,24 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FillFlowContainer<ColourDisplay> palette;
|
private FillFlowContainer palette;
|
||||||
private Container placeholder;
|
|
||||||
|
private IEnumerable<ColourDisplay> colourDisplays => palette.OfType<ColourDisplay>();
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
AutoSizeAxes = Axes.Y;
|
AutoSizeAxes = Axes.Y;
|
||||||
|
AutoSizeDuration = fade_duration;
|
||||||
|
AutoSizeEasing = Easing.OutQuint;
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChild = palette = new FillFlowContainer
|
||||||
{
|
{
|
||||||
palette = new FillFlowContainer<ColourDisplay>
|
RelativeSizeAxes = Axes.X,
|
||||||
{
|
AutoSizeAxes = Axes.Y,
|
||||||
RelativeSizeAxes = Axes.X,
|
Spacing = new Vector2(10),
|
||||||
AutoSizeAxes = Axes.Y,
|
Direction = FillDirection.Full
|
||||||
Spacing = new Vector2(10),
|
|
||||||
Direction = FillDirection.Full
|
|
||||||
},
|
|
||||||
placeholder = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Child = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
Text = "(none)",
|
|
||||||
Font = OsuFont.Default.With(weight: FontWeight.Bold)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +66,11 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
Colours.BindCollectionChanged((_, __) => updatePalette(), true);
|
Colours.BindCollectionChanged((_, args) =>
|
||||||
|
{
|
||||||
|
if (args.Action != NotifyCollectionChangedAction.Replace)
|
||||||
|
updatePalette();
|
||||||
|
}, true);
|
||||||
FinishTransforms(true);
|
FinishTransforms(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,37 +80,103 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
{
|
{
|
||||||
palette.Clear();
|
palette.Clear();
|
||||||
|
|
||||||
if (Colours.Any())
|
for (int i = 0; i < Colours.Count; ++i)
|
||||||
{
|
{
|
||||||
palette.FadeIn(fade_duration, Easing.OutQuint);
|
// copy to avoid accesses to modified closure.
|
||||||
placeholder.FadeOut(fade_duration, Easing.OutQuint);
|
int colourIndex = i;
|
||||||
}
|
ColourDisplay display;
|
||||||
else
|
|
||||||
{
|
palette.Add(display = new ColourDisplay
|
||||||
palette.FadeOut(fade_duration, Easing.OutQuint);
|
{
|
||||||
placeholder.FadeIn(fade_duration, Easing.OutQuint);
|
Current = { Value = Colours[colourIndex] }
|
||||||
|
});
|
||||||
|
|
||||||
|
display.Current.BindValueChanged(colour => Colours[colourIndex] = colour.NewValue);
|
||||||
|
display.DeleteRequested += colourDeletionRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var item in Colours)
|
palette.Add(new AddColourButton
|
||||||
{
|
{
|
||||||
palette.Add(new ColourDisplay
|
Action = () => Colours.Add(Colour4.White)
|
||||||
{
|
});
|
||||||
Current = { Value = item }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
reindexItems();
|
reindexItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void colourDeletionRequested(ColourDisplay display) => Colours.RemoveAt(palette.IndexOf(display));
|
||||||
|
|
||||||
private void reindexItems()
|
private void reindexItems()
|
||||||
{
|
{
|
||||||
int index = 1;
|
int index = 1;
|
||||||
|
|
||||||
foreach (var colour in palette)
|
foreach (var colourDisplay in colourDisplays)
|
||||||
{
|
{
|
||||||
colour.ColourName = $"{colourNamePrefix} {index}";
|
colourDisplay.ColourName = $"{colourNamePrefix} {index}";
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class AddColourButton : CompositeDrawable
|
||||||
|
{
|
||||||
|
public Action Action
|
||||||
|
{
|
||||||
|
set => circularButton.Action = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly OsuClickableContainer circularButton;
|
||||||
|
|
||||||
|
public AddColourButton()
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
Width = 100;
|
||||||
|
|
||||||
|
InternalChild = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 10),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
circularButton = new OsuClickableContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 100,
|
||||||
|
CornerRadius = 50,
|
||||||
|
Masking = true,
|
||||||
|
BorderThickness = 5,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Colour4.Transparent,
|
||||||
|
AlwaysPresent = true
|
||||||
|
},
|
||||||
|
new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(20),
|
||||||
|
Icon = FontAwesome.Solid.Plus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = "New"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
circularButton.BorderColour = colours.BlueDarker;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// 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 osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osuTK.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterfaceV2
|
namespace osu.Game.Graphics.UserInterfaceV2
|
||||||
{
|
{
|
||||||
@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindableList<Color4> Colours => Component.Colours;
|
public BindableList<Colour4> Colours => Component.Colours;
|
||||||
|
|
||||||
public string ColourNamePrefix
|
public string ColourNamePrefix
|
||||||
{
|
{
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
{
|
{
|
||||||
Depth = 1
|
Depth = 1
|
||||||
},
|
},
|
||||||
new HoverClickSounds(HoverSampleSet.Soft)
|
new HoverClickSounds()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
{
|
{
|
||||||
Depth = 1
|
Depth = 1
|
||||||
},
|
},
|
||||||
new HoverClickSounds(HoverSampleSet.Soft)
|
new HoverClickSounds()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ namespace osu.Game.Online.API
|
|||||||
|
|
||||||
userReq.Failure += ex =>
|
userReq.Failure += ex =>
|
||||||
{
|
{
|
||||||
if (ex.InnerException is WebException webException && webException.Message == @"Unauthorized")
|
if (ex is WebException webException && webException.Message == @"Unauthorized")
|
||||||
{
|
{
|
||||||
log.Add(@"Login no longer valid");
|
log.Add(@"Login no longer valid");
|
||||||
Logout();
|
Logout();
|
||||||
|
@ -86,8 +86,6 @@ namespace osu.Game.Online.API
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private APIRequestCompletionState completionState;
|
private APIRequestCompletionState completionState;
|
||||||
|
|
||||||
private Action pendingFailure;
|
|
||||||
|
|
||||||
public void Perform(IAPIProvider api)
|
public void Perform(IAPIProvider api)
|
||||||
{
|
{
|
||||||
if (!(api is APIAccess apiAccess))
|
if (!(api is APIAccess apiAccess))
|
||||||
@ -99,29 +97,23 @@ namespace osu.Game.Online.API
|
|||||||
API = apiAccess;
|
API = apiAccess;
|
||||||
User = apiAccess.LocalUser.Value;
|
User = apiAccess.LocalUser.Value;
|
||||||
|
|
||||||
if (checkAndScheduleFailure())
|
if (isFailing) return;
|
||||||
return;
|
|
||||||
|
|
||||||
WebRequest = CreateWebRequest();
|
WebRequest = CreateWebRequest();
|
||||||
WebRequest.Failed += Fail;
|
WebRequest.Failed += Fail;
|
||||||
WebRequest.AllowRetryOnTimeout = false;
|
WebRequest.AllowRetryOnTimeout = false;
|
||||||
WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}");
|
WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}");
|
||||||
|
|
||||||
if (checkAndScheduleFailure())
|
if (isFailing) return;
|
||||||
return;
|
|
||||||
|
|
||||||
if (!WebRequest.Aborted) // could have been aborted by a Cancel() call
|
Logger.Log($@"Performing request {this}", LoggingTarget.Network);
|
||||||
{
|
WebRequest.Perform();
|
||||||
Logger.Log($@"Performing request {this}", LoggingTarget.Network);
|
|
||||||
WebRequest.Perform();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkAndScheduleFailure())
|
if (isFailing) return;
|
||||||
return;
|
|
||||||
|
|
||||||
PostProcess();
|
PostProcess();
|
||||||
|
|
||||||
API.Schedule(TriggerSuccess);
|
TriggerSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -141,7 +133,10 @@ namespace osu.Game.Online.API
|
|||||||
completionState = APIRequestCompletionState.Completed;
|
completionState = APIRequestCompletionState.Completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Success?.Invoke();
|
if (API == null)
|
||||||
|
Success?.Invoke();
|
||||||
|
else
|
||||||
|
API.Schedule(() => Success?.Invoke());
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void TriggerFailure(Exception e)
|
internal void TriggerFailure(Exception e)
|
||||||
@ -154,7 +149,10 @@ namespace osu.Game.Online.API
|
|||||||
completionState = APIRequestCompletionState.Failed;
|
completionState = APIRequestCompletionState.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Failure?.Invoke(e);
|
if (API == null)
|
||||||
|
Failure?.Invoke(e);
|
||||||
|
else
|
||||||
|
API.Schedule(() => Failure?.Invoke(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled"));
|
public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled"));
|
||||||
@ -163,59 +161,47 @@ namespace osu.Game.Online.API
|
|||||||
{
|
{
|
||||||
lock (completionStateLock)
|
lock (completionStateLock)
|
||||||
{
|
{
|
||||||
// while it doesn't matter if code following this check is run more than once,
|
|
||||||
// this avoids unnecessarily performing work where we are already sure the user has been informed.
|
|
||||||
if (completionState != APIRequestCompletionState.Waiting)
|
if (completionState != APIRequestCompletionState.Waiting)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
WebRequest?.Abort();
|
WebRequest?.Abort();
|
||||||
|
|
||||||
// in the case of a cancellation we don't care about whether there's an error in the response.
|
// in the case of a cancellation we don't care about whether there's an error in the response.
|
||||||
if (!(e is OperationCanceledException))
|
if (!(e is OperationCanceledException))
|
||||||
{
|
|
||||||
string responseString = WebRequest?.GetResponseString();
|
|
||||||
|
|
||||||
// naive check whether there's an error in the response to avoid unnecessary JSON deserialisation.
|
|
||||||
if (!string.IsNullOrEmpty(responseString) && responseString.Contains(@"""error"""))
|
|
||||||
{
|
{
|
||||||
try
|
string responseString = WebRequest?.GetResponseString();
|
||||||
{
|
|
||||||
// attempt to decode a displayable error string.
|
// naive check whether there's an error in the response to avoid unnecessary JSON deserialisation.
|
||||||
var error = JsonConvert.DeserializeObject<DisplayableError>(responseString);
|
if (!string.IsNullOrEmpty(responseString) && responseString.Contains(@"""error"""))
|
||||||
if (error != null)
|
|
||||||
e = new APIException(error.ErrorMessage, e);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// attempt to decode a displayable error string.
|
||||||
|
var error = JsonConvert.DeserializeObject<DisplayableError>(responseString);
|
||||||
|
if (error != null)
|
||||||
|
e = new APIException(error.ErrorMessage, e);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Log($@"Failing request {this} ({e})", LoggingTarget.Network);
|
Logger.Log($@"Failing request {this} ({e})", LoggingTarget.Network);
|
||||||
pendingFailure = () => TriggerFailure(e);
|
TriggerFailure(e);
|
||||||
checkAndScheduleFailure();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checked for cancellation or error. Also queues up the Failed event if we can.
|
/// Whether this request is in a failing or failed state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Whether we are in a failed or cancelled state.</returns>
|
private bool isFailing
|
||||||
private bool checkAndScheduleFailure()
|
|
||||||
{
|
{
|
||||||
lock (completionStateLock)
|
get
|
||||||
{
|
{
|
||||||
if (pendingFailure == null)
|
lock (completionStateLock)
|
||||||
return completionState == APIRequestCompletionState.Failed;
|
return completionState == APIRequestCompletionState.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (API == null)
|
|
||||||
pendingFailure();
|
|
||||||
else
|
|
||||||
API.Schedule(pendingFailure);
|
|
||||||
|
|
||||||
pendingFailure = null;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DisplayableError
|
private class DisplayableError
|
||||||
|
@ -31,6 +31,7 @@ namespace osu.Game.Online.Chat
|
|||||||
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new LinkHoverSounds(sampleSet, Parts);
|
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new LinkHoverSounds(sampleSet, Parts);
|
||||||
|
|
||||||
public DrawableLinkCompiler(IEnumerable<Drawable> parts)
|
public DrawableLinkCompiler(IEnumerable<Drawable> parts)
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
Parts = parts.ToList();
|
Parts = parts.ToList();
|
||||||
}
|
}
|
||||||
|
@ -1058,7 +1058,7 @@ namespace osu.Game
|
|||||||
OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode);
|
OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode);
|
||||||
API.Activity.BindTo(newOsuScreen.Activity);
|
API.Activity.BindTo(newOsuScreen.Activity);
|
||||||
|
|
||||||
MusicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments;
|
MusicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments;
|
||||||
|
|
||||||
if (newOsuScreen.HideOverlaysOnEnter)
|
if (newOsuScreen.HideOverlaysOnEnter)
|
||||||
CloseAllOverlays();
|
CloseAllOverlays();
|
||||||
|
@ -479,7 +479,7 @@ namespace osu.Game
|
|||||||
if (r.NewValue?.Available != true)
|
if (r.NewValue?.Available != true)
|
||||||
{
|
{
|
||||||
// reject the change if the ruleset is not available.
|
// reject the change if the ruleset is not available.
|
||||||
Ruleset.Value = r.OldValue;
|
Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
protected Action ViewBeatmap;
|
protected Action ViewBeatmap;
|
||||||
|
|
||||||
protected BeatmapPanel(BeatmapSetInfo setInfo)
|
protected BeatmapPanel(BeatmapSetInfo setInfo)
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
Debug.Assert(setInfo.OnlineBeatmapSetID != null);
|
Debug.Assert(setInfo.OnlineBeatmapSetID != null);
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ using osu.Framework.Graphics.Cursor;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -62,7 +63,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToString(@"m\:ss");
|
length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToFormattedDuration();
|
||||||
circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString();
|
circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString();
|
||||||
sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToString();
|
sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToString();
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -13,6 +16,7 @@ using osu.Framework.Graphics.UserInterface;
|
|||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.Chat;
|
using osu.Game.Online.Chat;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -39,6 +43,8 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
|
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
|
private Sample sampleTabSwitched;
|
||||||
|
|
||||||
public ChannelTabItem(Channel value)
|
public ChannelTabItem(Channel value)
|
||||||
: base(value)
|
: base(value)
|
||||||
{
|
{
|
||||||
@ -112,6 +118,7 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
new HoverSounds()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,11 +159,12 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours, AudioManager audio)
|
||||||
{
|
{
|
||||||
BackgroundActive = colours.ChatBlue;
|
BackgroundActive = colours.ChatBlue;
|
||||||
BackgroundInactive = colours.Gray4;
|
BackgroundInactive = colours.Gray4;
|
||||||
backgroundHover = colours.Gray7;
|
backgroundHover = colours.Gray7;
|
||||||
|
sampleTabSwitched = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select");
|
||||||
|
|
||||||
highlightBox.Colour = colours.Yellow;
|
highlightBox.Colour = colours.Yellow;
|
||||||
}
|
}
|
||||||
@ -217,7 +225,14 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
Text.Font = Text.Font.With(weight: FontWeight.Medium);
|
Text.Font = Text.Font.With(weight: FontWeight.Medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnActivated() => updateState();
|
protected override void OnActivated()
|
||||||
|
{
|
||||||
|
if (IsLoaded)
|
||||||
|
sampleTabSwitched?.Play();
|
||||||
|
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnDeactivated() => updateState();
|
protected override void OnDeactivated() => updateState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
if (value.Type != ChannelType.PM)
|
if (value.Type != ChannelType.PM)
|
||||||
throw new ArgumentException("Argument value needs to have the targettype user!");
|
throw new ArgumentException("Argument value needs to have the targettype user!");
|
||||||
|
|
||||||
ClickableAvatar avatar;
|
DrawableAvatar avatar;
|
||||||
|
|
||||||
AddRange(new Drawable[]
|
AddRange(new Drawable[]
|
||||||
{
|
{
|
||||||
@ -48,10 +48,9 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Child = new DelayedLoadWrapper(avatar = new ClickableAvatar(value.Users.First())
|
Child = new DelayedLoadWrapper(avatar = new DrawableAvatar(value.Users.First())
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both
|
||||||
OpenOnClick = false,
|
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
@ -400,35 +400,38 @@ namespace osu.Game.Overlays
|
|||||||
NextTrack();
|
NextTrack();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool allowRateAdjustments;
|
private bool allowTrackAdjustments;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether mod rate adjustments are allowed to be applied.
|
/// Whether mod track adjustments are allowed to be applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowRateAdjustments
|
public bool AllowTrackAdjustments
|
||||||
{
|
{
|
||||||
get => allowRateAdjustments;
|
get => allowTrackAdjustments;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (allowRateAdjustments == value)
|
if (allowTrackAdjustments == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
allowRateAdjustments = value;
|
allowTrackAdjustments = value;
|
||||||
ResetTrackAdjustments();
|
ResetTrackAdjustments();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets the speed adjustments currently applied on <see cref="CurrentTrack"/> and applies the mod adjustments if <see cref="AllowRateAdjustments"/> is <c>true</c>.
|
/// Resets the adjustments currently applied on <see cref="CurrentTrack"/> and applies the mod adjustments if <see cref="AllowTrackAdjustments"/> is <c>true</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Does not reset speed adjustments applied directly to the beatmap track.
|
/// Does not reset any adjustments applied directly to the beatmap track.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public void ResetTrackAdjustments()
|
public void ResetTrackAdjustments()
|
||||||
{
|
{
|
||||||
CurrentTrack.ResetSpeedAdjustments();
|
CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Balance);
|
||||||
|
CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Frequency);
|
||||||
|
CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Tempo);
|
||||||
|
CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Volume);
|
||||||
|
|
||||||
if (allowRateAdjustments)
|
if (allowTrackAdjustments)
|
||||||
{
|
{
|
||||||
foreach (var mod in mods.Value.OfType<IApplicableToTrack>())
|
foreach (var mod in mods.Value.OfType<IApplicableToTrack>())
|
||||||
mod.ApplyToTrack(CurrentTrack);
|
mod.ApplyToTrack(CurrentTrack);
|
||||||
|
@ -14,6 +14,7 @@ using osu.Framework.Platform;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.News
|
namespace osu.Game.Overlays.News
|
||||||
@ -28,6 +29,7 @@ namespace osu.Game.Overlays.News
|
|||||||
private TextFlowContainer main;
|
private TextFlowContainer main;
|
||||||
|
|
||||||
public NewsCard(APINewsPost post)
|
public NewsCard(APINewsPost post)
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
this.post = post;
|
this.post = post;
|
||||||
|
|
||||||
|
@ -15,13 +15,18 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.News.Sidebar
|
namespace osu.Game.Overlays.News.Sidebar
|
||||||
{
|
{
|
||||||
public class MonthSection : CompositeDrawable
|
public class MonthSection : CompositeDrawable
|
||||||
{
|
{
|
||||||
private const int animation_duration = 250;
|
private const int animation_duration = 250;
|
||||||
|
private Sample sampleOpen;
|
||||||
|
private Sample sampleClose;
|
||||||
|
|
||||||
public readonly BindableBool Expanded = new BindableBool();
|
public readonly BindableBool Expanded = new BindableBool();
|
||||||
|
|
||||||
@ -51,6 +56,21 @@ namespace osu.Game.Overlays.News.Sidebar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Expanded.ValueChanged += expanded =>
|
||||||
|
{
|
||||||
|
if (expanded.NewValue)
|
||||||
|
sampleOpen?.Play();
|
||||||
|
else
|
||||||
|
sampleClose?.Play();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(AudioManager audio)
|
||||||
|
{
|
||||||
|
sampleOpen = audio.Samples.Get(@"UI/dropdown-open");
|
||||||
|
sampleClose = audio.Samples.Get(@"UI/dropdown-close");
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DropdownHeader : OsuClickableContainer
|
private class DropdownHeader : OsuClickableContainer
|
||||||
@ -59,6 +79,8 @@ namespace osu.Game.Overlays.News.Sidebar
|
|||||||
|
|
||||||
private readonly SpriteIcon icon;
|
private readonly SpriteIcon icon;
|
||||||
|
|
||||||
|
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds();
|
||||||
|
|
||||||
public DropdownHeader(int month, int year)
|
public DropdownHeader(int month, int year)
|
||||||
{
|
{
|
||||||
var date = new DateTime(year, month, 1);
|
var date = new DateTime(year, month, 1);
|
||||||
@ -104,6 +126,7 @@ namespace osu.Game.Overlays.News.Sidebar
|
|||||||
private readonly APINewsPost post;
|
private readonly APINewsPost post;
|
||||||
|
|
||||||
public PostButton(APINewsPost post)
|
public PostButton(APINewsPost post)
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
this.post = post;
|
this.post = post;
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Sections
|
namespace osu.Game.Overlays.Profile.Sections
|
||||||
{
|
{
|
||||||
@ -17,6 +18,7 @@ namespace osu.Game.Overlays.Profile.Sections
|
|||||||
private readonly BeatmapInfo beatmap;
|
private readonly BeatmapInfo beatmap;
|
||||||
|
|
||||||
protected BeatmapMetadataContainer(BeatmapInfo beatmap)
|
protected BeatmapMetadataContainer(BeatmapInfo beatmap)
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
this.beatmap = beatmap;
|
this.beatmap = beatmap;
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
@ -52,7 +53,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Font = OsuFont.GetFont(size: 12),
|
Font = OsuFont.GetFont(size: 12),
|
||||||
Text = UsersStrings.ShowExtraTopRanksPpWeight(weight.ToString("0%"))
|
Text = UsersStrings.ShowExtraTopRanksPpWeight(weight.ToLocalisableString("0%"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,9 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Rankings
|
namespace osu.Game.Overlays.Rankings
|
||||||
{
|
{
|
||||||
@ -29,13 +32,14 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
{
|
{
|
||||||
public RankingsTitle()
|
public RankingsTitle()
|
||||||
{
|
{
|
||||||
Title = "ranking";
|
Title = PageTitleStrings.MainRankingControllerDefault;
|
||||||
Description = "find out who's the best right now";
|
Description = "find out who's the best right now";
|
||||||
IconTexture = "Icons/Hexacons/rankings";
|
IconTexture = "Icons/Hexacons/rankings";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))]
|
||||||
public enum RankingsScope
|
public enum RankingsScope
|
||||||
{
|
{
|
||||||
Performance,
|
Performance,
|
||||||
@ -43,4 +47,28 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
Score,
|
Score,
|
||||||
Country
|
Country
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class RankingsScopeEnumLocalisationMapper : EnumLocalisationMapper<RankingsScope>
|
||||||
|
{
|
||||||
|
public override LocalisableString Map(RankingsScope value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case RankingsScope.Performance:
|
||||||
|
return RankingsStrings.TypePerformance;
|
||||||
|
|
||||||
|
case RankingsScope.Spotlights:
|
||||||
|
return RankingsStrings.TypeCharts;
|
||||||
|
|
||||||
|
case RankingsScope.Score:
|
||||||
|
return RankingsStrings.TypeScore;
|
||||||
|
|
||||||
|
case RankingsScope.Country:
|
||||||
|
return RankingsStrings.TypeCountry;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value), value, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,43 @@
|
|||||||
// 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 osu.Framework.Extensions.LocalisationExtensions;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Rankings
|
namespace osu.Game.Overlays.Rankings
|
||||||
{
|
{
|
||||||
public class RankingsSortTabControl : OverlaySortTabControl<RankingsSortCriteria>
|
public class RankingsSortTabControl : OverlaySortTabControl<RankingsSortCriteria>
|
||||||
{
|
{
|
||||||
public RankingsSortTabControl()
|
public RankingsSortTabControl()
|
||||||
{
|
{
|
||||||
Title = "Show";
|
Title = RankingsStrings.FilterTitle.ToUpper();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[LocalisableEnum(typeof(RankingsSortCriteriaEnumLocalisationMapper))]
|
||||||
public enum RankingsSortCriteria
|
public enum RankingsSortCriteria
|
||||||
{
|
{
|
||||||
All,
|
All,
|
||||||
Friends
|
Friends
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class RankingsSortCriteriaEnumLocalisationMapper : EnumLocalisationMapper<RankingsSortCriteria>
|
||||||
|
{
|
||||||
|
public override LocalisableString Map(RankingsSortCriteria value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case RankingsSortCriteria.All:
|
||||||
|
return SortStrings.All;
|
||||||
|
|
||||||
|
case RankingsSortCriteria.Friends:
|
||||||
|
return SortStrings.Friends;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value), value, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Rankings
|
namespace osu.Game.Overlays.Rankings
|
||||||
{
|
{
|
||||||
@ -92,10 +94,10 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
Margin = new MarginPadding { Bottom = 5 },
|
Margin = new MarginPadding { Bottom = 5 },
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
startDateColumn = new InfoColumn(@"Start Date"),
|
startDateColumn = new InfoColumn(RankingsStrings.SpotlightStartDate),
|
||||||
endDateColumn = new InfoColumn(@"End Date"),
|
endDateColumn = new InfoColumn(RankingsStrings.SpotlightEndDate),
|
||||||
mapCountColumn = new InfoColumn(@"Map Count"),
|
mapCountColumn = new InfoColumn(RankingsStrings.SpotlightMapCount),
|
||||||
participantsColumn = new InfoColumn(@"Participants")
|
participantsColumn = new InfoColumn(RankingsStrings.SpotlightParticipants)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new RankingsSortTabControl
|
new RankingsSortTabControl
|
||||||
@ -122,22 +124,22 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
{
|
{
|
||||||
startDateColumn.Value = dateToString(response.Spotlight.StartDate);
|
startDateColumn.Value = dateToString(response.Spotlight.StartDate);
|
||||||
endDateColumn.Value = dateToString(response.Spotlight.EndDate);
|
endDateColumn.Value = dateToString(response.Spotlight.EndDate);
|
||||||
mapCountColumn.Value = response.BeatmapSets.Count.ToString();
|
mapCountColumn.Value = response.BeatmapSets.Count.ToLocalisableString(@"N0");
|
||||||
participantsColumn.Value = response.Spotlight.Participants?.ToString("N0");
|
participantsColumn.Value = response.Spotlight.Participants?.ToLocalisableString(@"N0");
|
||||||
}
|
}
|
||||||
|
|
||||||
private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd");
|
private LocalisableString dateToString(DateTimeOffset date) => date.ToLocalisableString(@"yyyy-MM-dd");
|
||||||
|
|
||||||
private class InfoColumn : FillFlowContainer
|
private class InfoColumn : FillFlowContainer
|
||||||
{
|
{
|
||||||
public string Value
|
public LocalisableString Value
|
||||||
{
|
{
|
||||||
set => valueText.Text = value;
|
set => valueText.Text = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly OsuSpriteText valueText;
|
private readonly OsuSpriteText valueText;
|
||||||
|
|
||||||
public InfoColumn(string name)
|
public InfoColumn(LocalisableString name)
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
Direction = FillDirection.Vertical;
|
Direction = FillDirection.Vertical;
|
||||||
|
@ -9,6 +9,8 @@ using osu.Game.Graphics;
|
|||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Rankings.Tables
|
namespace osu.Game.Overlays.Rankings.Tables
|
||||||
{
|
{
|
||||||
@ -19,14 +21,14 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override TableColumn[] CreateAdditionalHeaders() => new[]
|
protected override RankingsTableColumn[] CreateAdditionalHeaders() => new[]
|
||||||
{
|
{
|
||||||
new TableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatActiveUsers, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||||
new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatPlayCount, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||||
new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatRankedScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||||
new TableColumn("Avg. Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatAverageScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||||
new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatPerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true),
|
||||||
new TableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatAveragePerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override Country GetCountry(CountryStatistics item) => item.Country;
|
protected override Country GetCountry(CountryStatistics item) => item.Country;
|
||||||
@ -35,29 +37,29 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
|
|
||||||
protected override Drawable[] CreateAdditionalContent(CountryStatistics item) => new Drawable[]
|
protected override Drawable[] CreateAdditionalContent(CountryStatistics item) => new Drawable[]
|
||||||
{
|
{
|
||||||
new ColoredRowText
|
new ColouredRowText
|
||||||
{
|
{
|
||||||
Text = $@"{item.ActiveUsers:N0}",
|
Text = item.ActiveUsers.ToLocalisableString(@"N0")
|
||||||
},
|
},
|
||||||
new ColoredRowText
|
new ColouredRowText
|
||||||
{
|
{
|
||||||
Text = $@"{item.PlayCount:N0}",
|
Text = item.PlayCount.ToLocalisableString(@"N0")
|
||||||
},
|
},
|
||||||
new ColoredRowText
|
new ColouredRowText
|
||||||
{
|
{
|
||||||
Text = $@"{item.RankedScore:N0}",
|
Text = item.RankedScore.ToLocalisableString(@"N0")
|
||||||
},
|
},
|
||||||
new ColoredRowText
|
new ColouredRowText
|
||||||
{
|
{
|
||||||
Text = $@"{item.RankedScore / Math.Max(item.ActiveUsers, 1):N0}",
|
Text = (item.RankedScore / Math.Max(item.ActiveUsers, 1)).ToLocalisableString(@"N0")
|
||||||
},
|
},
|
||||||
new RowText
|
new RowText
|
||||||
{
|
{
|
||||||
Text = $@"{item.Performance:N0}",
|
Text = item.Performance.ToLocalisableString(@"N0")
|
||||||
},
|
},
|
||||||
new ColoredRowText
|
new ColouredRowText
|
||||||
{
|
{
|
||||||
Text = $@"{item.Performance / Math.Max(item.ActiveUsers, 1):N0}",
|
Text = (item.Performance / Math.Max(item.ActiveUsers, 1)).ToLocalisableString(@"N0")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Rankings.Tables
|
namespace osu.Game.Overlays.Rankings.Tables
|
||||||
@ -15,14 +17,14 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override TableColumn[] CreateUniqueHeaders() => new[]
|
protected override RankingsTableColumn[] CreateUniqueHeaders() => new[]
|
||||||
{
|
{
|
||||||
new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatPerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true),
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[]
|
protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[]
|
||||||
{
|
{
|
||||||
new RowText { Text = $@"{item.PP:N0}", }
|
new RowText { Text = item.PP.ToLocalisableString(@"N0"), }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,29 +55,24 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
|
|
||||||
rankings.ForEach(_ => backgroundFlow.Add(new TableRowBackground { Height = row_height }));
|
rankings.ForEach(_ => backgroundFlow.Add(new TableRowBackground { Height = row_height }));
|
||||||
|
|
||||||
Columns = mainHeaders.Concat(CreateAdditionalHeaders()).ToArray();
|
Columns = mainHeaders.Concat(CreateAdditionalHeaders()).Cast<TableColumn>().ToArray();
|
||||||
Content = rankings.Select((s, i) => createContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular();
|
Content = rankings.Select((s, i) => createContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Drawable[] createContent(int index, TModel item) => new Drawable[] { createIndexDrawable(index), createMainContent(item) }.Concat(CreateAdditionalContent(item)).ToArray();
|
private Drawable[] createContent(int index, TModel item) => new Drawable[] { createIndexDrawable(index), createMainContent(item) }.Concat(CreateAdditionalContent(item)).ToArray();
|
||||||
|
|
||||||
private static TableColumn[] mainHeaders => new[]
|
private static RankingsTableColumn[] mainHeaders => new[]
|
||||||
{
|
{
|
||||||
new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 40)), // place
|
new RankingsTableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 40)), // place
|
||||||
new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension()), // flag and username (country name)
|
new RankingsTableColumn(string.Empty, Anchor.CentreLeft, new Dimension()), // flag and username (country name)
|
||||||
};
|
};
|
||||||
|
|
||||||
protected abstract TableColumn[] CreateAdditionalHeaders();
|
protected abstract RankingsTableColumn[] CreateAdditionalHeaders();
|
||||||
|
|
||||||
protected abstract Drawable[] CreateAdditionalContent(TModel item);
|
protected abstract Drawable[] CreateAdditionalContent(TModel item);
|
||||||
|
|
||||||
protected virtual string HighlightedColumn => @"Performance";
|
protected sealed override Drawable CreateHeader(int index, TableColumn column)
|
||||||
|
=> (column as RankingsTableColumn)?.CreateHeaderText() ?? new HeaderText(column?.Header ?? default, false);
|
||||||
protected override Drawable CreateHeader(int index, TableColumn column)
|
|
||||||
{
|
|
||||||
var title = column?.Header ?? default;
|
|
||||||
return new HeaderText(title, title == HighlightedColumn);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Country GetCountry(TModel item);
|
protected abstract Country GetCountry(TModel item);
|
||||||
|
|
||||||
@ -85,7 +80,7 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
|
|
||||||
private OsuSpriteText createIndexDrawable(int index) => new RowText
|
private OsuSpriteText createIndexDrawable(int index) => new RowText
|
||||||
{
|
{
|
||||||
Text = $"#{index + 1}",
|
Text = (index + 1).ToLocalisableString(@"\##"),
|
||||||
Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.SemiBold)
|
Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.SemiBold)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,6 +101,19 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected class RankingsTableColumn : TableColumn
|
||||||
|
{
|
||||||
|
protected readonly bool Highlighted;
|
||||||
|
|
||||||
|
public RankingsTableColumn(LocalisableString? header = null, Anchor anchor = Anchor.TopLeft, Dimension dimension = null, bool highlighted = false)
|
||||||
|
: base(header, anchor, dimension)
|
||||||
|
{
|
||||||
|
Highlighted = highlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual HeaderText CreateHeaderText() => new HeaderText(Header, Highlighted);
|
||||||
|
}
|
||||||
|
|
||||||
protected class HeaderText : OsuSpriteText
|
protected class HeaderText : OsuSpriteText
|
||||||
{
|
{
|
||||||
private readonly bool isHighlighted;
|
private readonly bool isHighlighted;
|
||||||
@ -136,7 +144,7 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class ColoredRowText : RowText
|
protected class ColouredRowText : RowText
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OverlayColourProvider colourProvider)
|
private void load(OverlayColourProvider colourProvider)
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Rankings.Tables
|
namespace osu.Game.Overlays.Rankings.Tables
|
||||||
@ -15,24 +17,22 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override TableColumn[] CreateUniqueHeaders() => new[]
|
protected override RankingsTableColumn[] CreateUniqueHeaders() => new[]
|
||||||
{
|
{
|
||||||
new TableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatTotalScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||||
new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize))
|
new RankingsTableColumn(RankingsStrings.StatRankedScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true)
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[]
|
protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[]
|
||||||
{
|
{
|
||||||
new ColoredRowText
|
new ColouredRowText
|
||||||
{
|
{
|
||||||
Text = $@"{item.TotalScore:N0}",
|
Text = item.TotalScore.ToLocalisableString(@"N0"),
|
||||||
},
|
},
|
||||||
new RowText
|
new RowText
|
||||||
{
|
{
|
||||||
Text = $@"{item.RankedScore:N0}",
|
Text = item.RankedScore.ToLocalisableString(@"N0")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override string HighlightedColumn => @"Ranked Score";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using osu.Game.Graphics.Containers;
|
|||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Rankings.Tables
|
namespace osu.Game.Overlays.Rankings.Tables
|
||||||
{
|
{
|
||||||
@ -20,22 +21,16 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IEnumerable<string> GradeColumns => new List<string> { "SS", "S", "A" };
|
protected virtual IEnumerable<LocalisableString> GradeColumns => new List<LocalisableString> { RankingsStrings.Statss, RankingsStrings.Stats, RankingsStrings.Stata };
|
||||||
|
|
||||||
protected override TableColumn[] CreateAdditionalHeaders() => new[]
|
protected override RankingsTableColumn[] CreateAdditionalHeaders() => new[]
|
||||||
{
|
{
|
||||||
new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatAccuracy, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||||
new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
new RankingsTableColumn(RankingsStrings.StatPlayCount, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||||
}.Concat(CreateUniqueHeaders())
|
}.Concat(CreateUniqueHeaders())
|
||||||
.Concat(GradeColumns.Select(grade => new TableColumn(grade, Anchor.Centre, new Dimension(GridSizeMode.AutoSize))))
|
.Concat(GradeColumns.Select(grade => new GradeTableColumn(grade, Anchor.Centre, new Dimension(GridSizeMode.AutoSize))))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
protected override Drawable CreateHeader(int index, TableColumn column)
|
|
||||||
{
|
|
||||||
var title = column?.Header ?? default;
|
|
||||||
return new UserTableHeaderText(title, HighlightedColumn == title, GradeColumns.Contains(title.ToString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected sealed override Country GetCountry(UserStatistics item) => item.User.Country;
|
protected sealed override Country GetCountry(UserStatistics item) => item.User.Country;
|
||||||
|
|
||||||
protected sealed override Drawable CreateFlagContent(UserStatistics item)
|
protected sealed override Drawable CreateFlagContent(UserStatistics item)
|
||||||
@ -52,28 +47,38 @@ namespace osu.Game.Overlays.Rankings.Tables
|
|||||||
|
|
||||||
protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[]
|
protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[]
|
||||||
{
|
{
|
||||||
new ColoredRowText { Text = item.DisplayAccuracy, },
|
new ColouredRowText { Text = item.DisplayAccuracy, },
|
||||||
new ColoredRowText { Text = $@"{item.PlayCount:N0}", },
|
new ColouredRowText { Text = item.PlayCount.ToLocalisableString(@"N0") },
|
||||||
}.Concat(CreateUniqueContent(item)).Concat(new[]
|
}.Concat(CreateUniqueContent(item)).Concat(new[]
|
||||||
{
|
{
|
||||||
new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]:N0}", },
|
new ColouredRowText { Text = (item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]).ToLocalisableString(@"N0"), },
|
||||||
new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]:N0}", },
|
new ColouredRowText { Text = (item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]).ToLocalisableString(@"N0"), },
|
||||||
new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.A]:N0}", }
|
new ColouredRowText { Text = item.GradesCount[ScoreRank.A].ToLocalisableString(@"N0"), }
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
protected abstract TableColumn[] CreateUniqueHeaders();
|
protected abstract RankingsTableColumn[] CreateUniqueHeaders();
|
||||||
|
|
||||||
protected abstract Drawable[] CreateUniqueContent(UserStatistics item);
|
protected abstract Drawable[] CreateUniqueContent(UserStatistics item);
|
||||||
|
|
||||||
private class UserTableHeaderText : HeaderText
|
private class GradeTableColumn : RankingsTableColumn
|
||||||
{
|
{
|
||||||
public UserTableHeaderText(LocalisableString text, bool isHighlighted, bool isGrade)
|
public GradeTableColumn(LocalisableString? header = null, Anchor anchor = Anchor.TopLeft, Dimension dimension = null, bool highlighted = false)
|
||||||
|
: base(header, anchor, dimension, highlighted)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override HeaderText CreateHeaderText() => new GradeHeaderText(Header, Highlighted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class GradeHeaderText : HeaderText
|
||||||
|
{
|
||||||
|
public GradeHeaderText(LocalisableString text, bool isHighlighted)
|
||||||
: base(text, isHighlighted)
|
: base(text, isHighlighted)
|
||||||
{
|
{
|
||||||
Margin = new MarginPadding
|
Margin = new MarginPadding
|
||||||
{
|
{
|
||||||
// Grade columns have extra horizontal padding for readibility
|
// Grade columns have extra horizontal padding for readibility
|
||||||
Horizontal = isGrade ? 20 : 10,
|
Horizontal = 20,
|
||||||
Vertical = 5
|
Vertical = 5
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
new HoverClickSounds()
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var b in bindings)
|
foreach (var b in bindings)
|
||||||
@ -458,6 +459,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Text = keyBinding.KeyCombination.ReadableString(),
|
Text = keyBinding.KeyCombination.ReadableString(),
|
||||||
},
|
},
|
||||||
|
new HoverSounds()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.Diagnostics;
|
using System.Diagnostics;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -31,6 +32,9 @@ namespace osu.Game.Rulesets.Judgements
|
|||||||
|
|
||||||
private readonly Container aboveHitObjectsContent;
|
private readonly Container aboveHitObjectsContent;
|
||||||
|
|
||||||
|
private readonly Lazy<Drawable> proxiedAboveHitObjectsContent;
|
||||||
|
public Drawable ProxiedAboveHitObjectsContent => proxiedAboveHitObjectsContent.Value;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a drawable which visualises a <see cref="Judgements.Judgement"/>.
|
/// Creates a drawable which visualises a <see cref="Judgements.Judgement"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -52,6 +56,8 @@ namespace osu.Game.Rulesets.Judgements
|
|||||||
Depth = float.MinValue,
|
Depth = float.MinValue,
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
});
|
});
|
||||||
|
|
||||||
|
proxiedAboveHitObjectsContent = new Lazy<Drawable>(() => aboveHitObjectsContent.CreateProxy());
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -60,8 +66,6 @@ namespace osu.Game.Rulesets.Judgements
|
|||||||
prepareDrawables();
|
prepareDrawables();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Drawable GetProxyAboveHitObjectsContent() => aboveHitObjectsContent.CreateProxy();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply top-level animations to the current judgement when successfully hit.
|
/// Apply top-level animations to the current judgement when successfully hit.
|
||||||
/// If displaying components which require lifetime extensions, manually adjusting <see cref="Drawable.LifetimeEnd"/> is required.
|
/// If displaying components which require lifetime extensions, manually adjusting <see cref="Drawable.LifetimeEnd"/> is required.
|
||||||
|
@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
public interface IApplicableToHealthProcessor : IApplicableMod
|
public interface IApplicableToHealthProcessor : IApplicableMod
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provide a <see cref="HealthProcessor"/> to a mod. Called once on initialisation of a play instance.
|
/// Provides a loaded <see cref="HealthProcessor"/> to a mod. Called once on initialisation of a play instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ApplyToHealthProcessor(HealthProcessor healthProcessor);
|
void ApplyToHealthProcessor(HealthProcessor healthProcessor);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
public interface IApplicableToScoreProcessor : IApplicableMod
|
public interface IApplicableToScoreProcessor : IApplicableMod
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provide a <see cref="ScoreProcessor"/> to a mod. Called once on initialisation of a play instance.
|
/// Provides a loaded <see cref="ScoreProcessor"/> to a mod. Called once on initialisation of a play instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ApplyToScoreProcessor(ScoreProcessor scoreProcessor);
|
void ApplyToScoreProcessor(ScoreProcessor scoreProcessor);
|
||||||
|
|
||||||
|
91
osu.Game/Rulesets/Mods/Metronome.cs
Normal file
91
osu.Game/Rulesets/Mods/Metronome.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// 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 osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Track;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mods
|
||||||
|
{
|
||||||
|
public class Metronome : BeatSyncedContainer, IAdjustableAudioComponent
|
||||||
|
{
|
||||||
|
private readonly double firstHitTime;
|
||||||
|
|
||||||
|
private readonly PausableSkinnableSound sample;
|
||||||
|
|
||||||
|
/// <param name="firstHitTime">Start time of the first hit object, used for providing a count down.</param>
|
||||||
|
public Metronome(double firstHitTime)
|
||||||
|
{
|
||||||
|
this.firstHitTime = firstHitTime;
|
||||||
|
AllowMistimedEventFiring = false;
|
||||||
|
Divisor = 1;
|
||||||
|
|
||||||
|
InternalChild = sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana"));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
||||||
|
{
|
||||||
|
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||||
|
|
||||||
|
if (!IsBeatSyncedWithTrack) return;
|
||||||
|
|
||||||
|
int timeSignature = (int)timingPoint.TimeSignature;
|
||||||
|
|
||||||
|
// play metronome from one measure before the first object.
|
||||||
|
if (BeatSyncClock.CurrentTime < firstHitTime - timingPoint.BeatLength * timeSignature)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sample.Frequency.Value = beatIndex % timeSignature == 0 ? 1 : 0.5f;
|
||||||
|
sample.Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IAdjustableAudioComponent
|
||||||
|
|
||||||
|
public IBindable<double> AggregateVolume => sample.AggregateVolume;
|
||||||
|
|
||||||
|
public IBindable<double> AggregateBalance => sample.AggregateBalance;
|
||||||
|
|
||||||
|
public IBindable<double> AggregateFrequency => sample.AggregateFrequency;
|
||||||
|
|
||||||
|
public IBindable<double> AggregateTempo => sample.AggregateTempo;
|
||||||
|
|
||||||
|
public BindableNumber<double> Volume => sample.Volume;
|
||||||
|
|
||||||
|
public BindableNumber<double> Balance => sample.Balance;
|
||||||
|
|
||||||
|
public BindableNumber<double> Frequency => sample.Frequency;
|
||||||
|
|
||||||
|
public BindableNumber<double> Tempo => sample.Tempo;
|
||||||
|
|
||||||
|
public void BindAdjustments(IAggregateAudioAdjustment component)
|
||||||
|
{
|
||||||
|
sample.BindAdjustments(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnbindAdjustments(IAggregateAudioAdjustment component)
|
||||||
|
{
|
||||||
|
sample.UnbindAdjustments(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAdjustment(AdjustableProperty type, IBindable<double> adjustBindable)
|
||||||
|
{
|
||||||
|
sample.AddAdjustment(type, adjustBindable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAdjustment(AdjustableProperty type, IBindable<double> adjustBindable)
|
||||||
|
{
|
||||||
|
sample.RemoveAdjustment(type, adjustBindable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAllAdjustments(AdjustableProperty type)
|
||||||
|
{
|
||||||
|
sample.RemoveAllAdjustments(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
104
osu.Game/Rulesets/Mods/ModMuted.cs
Normal file
104
osu.Game/Rulesets/Mods/ModMuted.cs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// 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 System.Linq;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Track;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mods
|
||||||
|
{
|
||||||
|
public abstract class ModMuted : Mod
|
||||||
|
{
|
||||||
|
public override string Name => "Muted";
|
||||||
|
public override string Acronym => "MU";
|
||||||
|
public override IconUsage? Icon => FontAwesome.Solid.VolumeMute;
|
||||||
|
public override string Description => "Can you still feel the rhythm without music?";
|
||||||
|
public override ModType Type => ModType.Fun;
|
||||||
|
public override double ScoreMultiplier => 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class ModMuted<TObject> : ModMuted, IApplicableToDrawableRuleset<TObject>, IApplicableToTrack, IApplicableToScoreProcessor
|
||||||
|
where TObject : HitObject
|
||||||
|
{
|
||||||
|
private readonly BindableNumber<double> mainVolumeAdjust = new BindableDouble(0.5);
|
||||||
|
private readonly BindableNumber<double> metronomeVolumeAdjust = new BindableDouble(0.5);
|
||||||
|
|
||||||
|
private BindableNumber<int> currentCombo;
|
||||||
|
|
||||||
|
[SettingSource("Enable metronome", "Add a metronome beat to help you keep track of the rhythm.")]
|
||||||
|
public BindableBool EnableMetronome { get; } = new BindableBool
|
||||||
|
{
|
||||||
|
Default = true,
|
||||||
|
Value = true
|
||||||
|
};
|
||||||
|
|
||||||
|
[SettingSource("Final volume at combo", "The combo count at which point the track reaches its final volume.")]
|
||||||
|
public BindableInt MuteComboCount { get; } = new BindableInt
|
||||||
|
{
|
||||||
|
Default = 100,
|
||||||
|
Value = 100,
|
||||||
|
MinValue = 0,
|
||||||
|
MaxValue = 500,
|
||||||
|
};
|
||||||
|
|
||||||
|
[SettingSource("Start muted", "Increase volume as combo builds.")]
|
||||||
|
public BindableBool InverseMuting { get; } = new BindableBool
|
||||||
|
{
|
||||||
|
Default = false,
|
||||||
|
Value = false
|
||||||
|
};
|
||||||
|
|
||||||
|
[SettingSource("Mute hit sounds", "Hit sounds are also muted alongside the track.")]
|
||||||
|
public BindableBool AffectsHitSounds { get; } = new BindableBool
|
||||||
|
{
|
||||||
|
Default = true,
|
||||||
|
Value = true
|
||||||
|
};
|
||||||
|
|
||||||
|
public void ApplyToTrack(ITrack track)
|
||||||
|
{
|
||||||
|
track.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyToDrawableRuleset(DrawableRuleset<TObject> drawableRuleset)
|
||||||
|
{
|
||||||
|
if (EnableMetronome.Value)
|
||||||
|
{
|
||||||
|
Metronome metronome;
|
||||||
|
|
||||||
|
drawableRuleset.Overlays.Add(metronome = new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime));
|
||||||
|
|
||||||
|
metronome.AddAdjustment(AdjustableProperty.Volume, metronomeVolumeAdjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AffectsHitSounds.Value)
|
||||||
|
drawableRuleset.Audio.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
|
||||||
|
{
|
||||||
|
currentCombo = scoreProcessor.Combo.GetBoundCopy();
|
||||||
|
currentCombo.BindValueChanged(combo =>
|
||||||
|
{
|
||||||
|
double dimFactor = Math.Min(1, (double)combo.NewValue / MuteComboCount.Value);
|
||||||
|
|
||||||
|
if (InverseMuting.Value)
|
||||||
|
dimFactor = 1 - dimFactor;
|
||||||
|
|
||||||
|
scoreProcessor.TransformBindableTo(metronomeVolumeAdjust, dimFactor, 500, Easing.OutQuint);
|
||||||
|
scoreProcessor.TransformBindableTo(mainVolumeAdjust, 1 - dimFactor, 500, Easing.OutQuint);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,30 @@
|
|||||||
// 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 osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
using osu.Game.Input.Handlers;
|
using osu.Game.Input.Handlers;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Rulesets.Configuration;
|
using osu.Game.Rulesets.Configuration;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
@ -98,6 +99,14 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
private DrawableRulesetDependencies dependencies;
|
private DrawableRulesetDependencies dependencies;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Audio adjustments which are applied to the playfield.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Does not affect <see cref="Overlays"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public IAdjustableAudioComponent Audio { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a ruleset visualisation for the provided ruleset and beatmap.
|
/// Creates a ruleset visualisation for the provided ruleset and beatmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -155,23 +164,28 @@ namespace osu.Game.Rulesets.UI
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(CancellationToken? cancellationToken)
|
private void load(CancellationToken? cancellationToken)
|
||||||
{
|
{
|
||||||
InternalChildren = new Drawable[]
|
AudioContainer audioContainer;
|
||||||
|
|
||||||
|
InternalChild = frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime)
|
||||||
{
|
{
|
||||||
frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime)
|
FrameStablePlayback = FrameStablePlayback,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
FrameStablePlayback = FrameStablePlayback,
|
FrameStableComponents,
|
||||||
Children = new Drawable[]
|
audioContainer = new AudioContainer
|
||||||
{
|
{
|
||||||
FrameStableComponents,
|
RelativeSizeAxes = Axes.Both,
|
||||||
KeyBindingInputManager
|
Child = KeyBindingInputManager
|
||||||
.WithChild(CreatePlayfieldAdjustmentContainer()
|
.WithChild(CreatePlayfieldAdjustmentContainer()
|
||||||
.WithChild(Playfield)
|
.WithChild(Playfield)
|
||||||
),
|
),
|
||||||
Overlays,
|
},
|
||||||
}
|
Overlays,
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Audio = audioContainer;
|
||||||
|
|
||||||
if ((ResumeOverlay = CreateResumeOverlay()) != null)
|
if ((ResumeOverlay = CreateResumeOverlay()) != null)
|
||||||
{
|
{
|
||||||
AddInternal(CreateInputManager()
|
AddInternal(CreateInputManager()
|
||||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
||||||
|
|
||||||
public override bool AllowRateAdjustments => false;
|
public override bool AllowTrackAdjustments => false;
|
||||||
|
|
||||||
protected bool HasUnsavedChanges => lastSavedHash != changeHandler.CurrentStateHash;
|
protected bool HasUnsavedChanges => lastSavedHash != changeHandler.CurrentStateHash;
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ using osu.Framework.Localisation;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -67,7 +66,6 @@ namespace osu.Game.Screens.Edit
|
|||||||
private EditorClock clock { get; set; }
|
private EditorClock clock { get; set; }
|
||||||
|
|
||||||
public RowBackground(object item)
|
public RowBackground(object item)
|
||||||
: base(HoverSampleSet.Soft)
|
|
||||||
{
|
{
|
||||||
Item = item;
|
Item = item;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
@ -32,7 +33,7 @@ namespace osu.Game.Screens.Edit.Setup
|
|||||||
|
|
||||||
var colours = Beatmap.BeatmapSkin?.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value;
|
var colours = Beatmap.BeatmapSkin?.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value;
|
||||||
if (colours != null)
|
if (colours != null)
|
||||||
comboColours.Colours.AddRange(colours);
|
comboColours.Colours.AddRange(colours.Select(c => (Colour4)c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,9 +59,9 @@ namespace osu.Game.Screens
|
|||||||
Bindable<RulesetInfo> Ruleset { get; }
|
Bindable<RulesetInfo> Ruleset { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether mod rate adjustments are allowed to be applied.
|
/// Whether mod track adjustments are allowed to be applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool AllowRateAdjustments { get; }
|
bool AllowTrackAdjustments { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when the back button has been pressed to close any overlays before exiting this <see cref="IOsuScreen"/>.
|
/// Invoked when the back button has been pressed to close any overlays before exiting this <see cref="IOsuScreen"/>.
|
||||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
public override bool AllowExternalScreenChange => true;
|
public override bool AllowExternalScreenChange => true;
|
||||||
|
|
||||||
public override bool AllowRateAdjustments => false;
|
public override bool AllowTrackAdjustments => false;
|
||||||
|
|
||||||
private Screen songSelect;
|
private Screen songSelect;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
||||||
|
|
||||||
// We are managing our own adjustments. For now, this happens inside the Player instances themselves.
|
// We are managing our own adjustments. For now, this happens inside the Player instances themselves.
|
||||||
public override bool AllowRateAdjustments => false;
|
public override bool AllowTrackAdjustments => false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether all spectating players have finished loading.
|
/// Whether all spectating players have finished loading.
|
||||||
|
@ -81,7 +81,7 @@ namespace osu.Game.Screens
|
|||||||
|
|
||||||
public virtual float BackgroundParallaxAmount => 1;
|
public virtual float BackgroundParallaxAmount => 1;
|
||||||
|
|
||||||
public virtual bool AllowRateAdjustments => true;
|
public virtual bool AllowTrackAdjustments => true;
|
||||||
|
|
||||||
public Bindable<WorkingBeatmap> Beatmap { get; private set; }
|
public Bindable<WorkingBeatmap> Beatmap { get; private set; }
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ namespace osu.Game.Screens.Play
|
|||||||
protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered;
|
protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered;
|
||||||
|
|
||||||
// We are managing our own adjustments (see OnEntering/OnExiting).
|
// We are managing our own adjustments (see OnEntering/OnExiting).
|
||||||
public override bool AllowRateAdjustments => false;
|
public override bool AllowTrackAdjustments => false;
|
||||||
|
|
||||||
private readonly IBindable<bool> gameActive = new Bindable<bool>(true);
|
private readonly IBindable<bool> gameActive = new Bindable<bool>(true);
|
||||||
|
|
||||||
@ -297,11 +297,19 @@ namespace osu.Game.Screens.Play
|
|||||||
ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged);
|
ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged);
|
||||||
HealthProcessor.Failed += onFail;
|
HealthProcessor.Failed += onFail;
|
||||||
|
|
||||||
foreach (var mod in Mods.Value.OfType<IApplicableToScoreProcessor>())
|
// Provide judgement processors to mods after they're loaded so that they're on the gameplay clock,
|
||||||
mod.ApplyToScoreProcessor(ScoreProcessor);
|
// this is required for mods that apply transforms to these processors.
|
||||||
|
ScoreProcessor.OnLoadComplete += _ =>
|
||||||
|
{
|
||||||
|
foreach (var mod in Mods.Value.OfType<IApplicableToScoreProcessor>())
|
||||||
|
mod.ApplyToScoreProcessor(ScoreProcessor);
|
||||||
|
};
|
||||||
|
|
||||||
foreach (var mod in Mods.Value.OfType<IApplicableToHealthProcessor>())
|
HealthProcessor.OnLoadComplete += _ =>
|
||||||
mod.ApplyToHealthProcessor(HealthProcessor);
|
{
|
||||||
|
foreach (var mod in Mods.Value.OfType<IApplicableToHealthProcessor>())
|
||||||
|
mod.ApplyToHealthProcessor(HealthProcessor);
|
||||||
|
};
|
||||||
|
|
||||||
IsBreakTime.BindTo(breakTracker.IsBreakTime);
|
IsBreakTime.BindTo(breakTracker.IsBreakTime);
|
||||||
IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
|
IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
|
||||||
|
@ -178,7 +178,7 @@ namespace osu.Game.Screens.Play
|
|||||||
float barHeight = bottom_bar_height + handle_size.Y;
|
float barHeight = bottom_bar_height + handle_size.Y;
|
||||||
|
|
||||||
bar.ResizeHeightTo(ShowGraph.Value ? barHeight + graph_height : barHeight, transition_duration, Easing.In);
|
bar.ResizeHeightTo(ShowGraph.Value ? barHeight + graph_height : barHeight, transition_duration, Easing.In);
|
||||||
graph.MoveToY(ShowGraph.Value ? 0 : bottom_bar_height + graph_height, transition_duration, Easing.In);
|
graph.FadeTo(ShowGraph.Value ? 1 : 0, transition_duration, Easing.In);
|
||||||
|
|
||||||
updateInfoMargin();
|
updateInfoMargin();
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ using osu.Framework.Graphics.Sprites;
|
|||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
@ -333,7 +334,7 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
Name = "Length",
|
Name = "Length",
|
||||||
CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Length),
|
CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Length),
|
||||||
Content = TimeSpan.FromMilliseconds(beatmap.BeatmapInfo.Length).ToString(@"m\:ss"),
|
Content = beatmap.BeatmapInfo.Length.ToFormattedDuration().ToString(),
|
||||||
}),
|
}),
|
||||||
bpmLabelContainer = new Container
|
bpmLabelContainer = new Container
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Select.Options
|
namespace osu.Game.Screens.Select.Options
|
||||||
{
|
{
|
||||||
@ -76,6 +77,7 @@ namespace osu.Game.Screens.Select.Options
|
|||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => box.ReceivePositionalInputAt(screenSpacePos);
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => box.ReceivePositionalInputAt(screenSpacePos);
|
||||||
|
|
||||||
public BeatmapOptionsButton()
|
public BeatmapOptionsButton()
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
Width = width;
|
Width = width;
|
||||||
RelativeSizeAxes = Axes.Y;
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Screens
|
|||||||
|
|
||||||
public override bool CursorVisible => false;
|
public override bool CursorVisible => false;
|
||||||
|
|
||||||
public override bool AllowRateAdjustments => false;
|
public override bool AllowTrackAdjustments => false;
|
||||||
|
|
||||||
protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled;
|
protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ using osu.Framework.Graphics.Textures;
|
|||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
namespace osu.Game.Users.Drawables
|
namespace osu.Game.Users.Drawables
|
||||||
{
|
{
|
||||||
@ -71,6 +72,11 @@ namespace osu.Game.Users.Drawables
|
|||||||
{
|
{
|
||||||
private LocalisableString tooltip = default_tooltip_text;
|
private LocalisableString tooltip = default_tooltip_text;
|
||||||
|
|
||||||
|
public ClickableArea()
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public override LocalisableString TooltipText
|
public override LocalisableString TooltipText
|
||||||
{
|
{
|
||||||
get => Enabled.Value ? tooltip : default;
|
get => Enabled.Value ? tooltip : default;
|
||||||
|
@ -5,6 +5,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
|
|
||||||
namespace osu.Game.Users.Drawables
|
namespace osu.Game.Users.Drawables
|
||||||
@ -32,9 +33,17 @@ namespace osu.Game.Users.Drawables
|
|||||||
if (country == null && !ShowPlaceholderOnNull)
|
if (country == null && !ShowPlaceholderOnNull)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new DrawableFlag(country)
|
return new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new DrawableFlag(country)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
new HoverClickSounds(HoverSampleSet.Submit)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ namespace osu.Game.Users
|
|||||||
protected Drawable Background { get; private set; }
|
protected Drawable Background { get; private set; }
|
||||||
|
|
||||||
protected UserPanel(User user)
|
protected UserPanel(User user)
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new ArgumentNullException(nameof(user));
|
throw new ArgumentNullException(nameof(user));
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<PackageReference Include="DiffPlex" Version="1.7.0" />
|
<PackageReference Include="DiffPlex" Version="1.7.0" />
|
||||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.34" />
|
<PackageReference Include="HtmlAgilityPack" Version="1.11.34" />
|
||||||
<PackageReference Include="Humanizer" Version="2.11.10" />
|
<PackageReference Include="Humanizer" Version="2.11.10" />
|
||||||
<PackageReference Include="MessagePack" Version="2.2.113" />
|
<PackageReference Include="MessagePack" Version="2.3.75" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.8" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="5.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="5.0.8" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="5.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="5.0.8" />
|
||||||
@ -37,8 +37,8 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Realm" Version="10.3.0" />
|
<PackageReference Include="Realm" Version="10.3.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2021.728.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2021.728.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.722.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.730.0" />
|
||||||
<PackageReference Include="Sentry" Version="3.8.2" />
|
<PackageReference Include="Sentry" Version="3.8.3" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.28.3" />
|
<PackageReference Include="SharpCompress" Version="0.28.3" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.728.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.728.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.722.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.730.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
@ -117,7 +117,7 @@
|
|||||||
</ImageAsset>
|
</ImageAsset>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
<PackageReference Include="Xamarin.Essentials" Version="1.7.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user