mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 13:37:25 +08:00
Merge branch 'master' into localisable-description
This commit is contained in:
commit
8dbcccc350
@ -190,3 +190,5 @@ dotnet_diagnostic.CA2225.severity = none
|
||||
|
||||
# Banned APIs
|
||||
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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.722.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.728.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Transitive Dependencies">
|
||||
|
@ -64,7 +64,7 @@
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.7.0" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
@ -109,15 +109,23 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
comboDisplay.X = Catcher.X;
|
||||
|
||||
if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0)
|
||||
catcherTrails.DisplayHyperDashAfterImage(Catcher.CurrentState, Catcher.X, Catcher.BodyScale);
|
||||
if (Time.Elapsed <= 0)
|
||||
{
|
||||
// This is probably a wrong value, but currently the true value is not recorded.
|
||||
// Setting `true` will prevent generation of false-positive after-images (with more false-negatives).
|
||||
lastHyperDashState = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lastHyperDashState && Catcher.HyperDashing)
|
||||
displayCatcherTrail(CatcherTrailAnimation.HyperDashAfterImage);
|
||||
|
||||
if (Catcher.Dashing || Catcher.HyperDashing)
|
||||
{
|
||||
double generationInterval = Catcher.HyperDashing ? 25 : 50;
|
||||
|
||||
if (Time.Current - catcherTrails.LastDashTrailTime >= generationInterval)
|
||||
catcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing);
|
||||
displayCatcherTrail(Catcher.HyperDashing ? CatcherTrailAnimation.HyperDashing : CatcherTrailAnimation.Dashing);
|
||||
}
|
||||
|
||||
lastHyperDashState = Catcher.HyperDashing;
|
||||
@ -173,5 +181,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void displayCatcherTrail(CatcherTrailAnimation animation) => catcherTrails.Add(new CatcherTrailEntry(Time.Current, Catcher.CurrentState, Catcher.X, Catcher.BodyScale, animation));
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Objects.Pooling;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
@ -12,13 +12,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// A trail of the catcher.
|
||||
/// It also represents a hyper dash afterimage.
|
||||
/// </summary>
|
||||
public class CatcherTrail : PoolableDrawable
|
||||
public class CatcherTrail : PoolableDrawableWithLifetime<CatcherTrailEntry>
|
||||
{
|
||||
public CatcherAnimationState AnimationState
|
||||
{
|
||||
set => body.AnimationState.Value = value;
|
||||
}
|
||||
|
||||
private readonly SkinnableCatcher body;
|
||||
|
||||
public CatcherTrail()
|
||||
@ -34,11 +29,40 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
};
|
||||
}
|
||||
|
||||
protected override void FreeAfterUse()
|
||||
protected override void OnApply(CatcherTrailEntry entry)
|
||||
{
|
||||
Position = new Vector2(entry.Position, 0);
|
||||
Scale = entry.Scale;
|
||||
|
||||
body.AnimationState.Value = entry.CatcherState;
|
||||
|
||||
using (BeginAbsoluteSequence(entry.LifetimeStart, false))
|
||||
applyTransforms(entry.Animation);
|
||||
}
|
||||
|
||||
protected override void OnFree(CatcherTrailEntry entry)
|
||||
{
|
||||
ApplyTransformsAt(double.MinValue);
|
||||
ClearTransforms();
|
||||
Alpha = 1;
|
||||
base.FreeAfterUse();
|
||||
}
|
||||
|
||||
private void applyTransforms(CatcherTrailAnimation animation)
|
||||
{
|
||||
switch (animation)
|
||||
{
|
||||
case CatcherTrailAnimation.Dashing:
|
||||
case CatcherTrailAnimation.HyperDashing:
|
||||
this.FadeTo(0.4f).FadeOut(800, Easing.OutQuint);
|
||||
break;
|
||||
|
||||
case CatcherTrailAnimation.HyperDashAfterImage:
|
||||
this.MoveToOffset(new Vector2(0, -10), 1200, Easing.In);
|
||||
this.ScaleTo(Scale * 0.95f).ScaleTo(Scale * 1.2f, 1200, Easing.In);
|
||||
this.FadeOut(1200);
|
||||
break;
|
||||
}
|
||||
|
||||
Expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
12
osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs
Normal file
12
osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.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.
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public enum CatcherTrailAnimation
|
||||
{
|
||||
Dashing,
|
||||
HyperDashing,
|
||||
HyperDashAfterImage
|
||||
}
|
||||
}
|
@ -2,12 +2,13 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Game.Rulesets.Catch.Skinning;
|
||||
using osu.Game.Rulesets.Objects.Pooling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
@ -16,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// Represents a component responsible for displaying
|
||||
/// the appropriate catcher trails when requested to.
|
||||
/// </summary>
|
||||
public class CatcherTrailDisplay : SkinReloadableDrawable
|
||||
public class CatcherTrailDisplay : PooledDrawableWithLifetimeContainer<CatcherTrailEntry, CatcherTrail>
|
||||
{
|
||||
/// <summary>
|
||||
/// The most recent time a dash trail was added to this container.
|
||||
@ -29,12 +30,17 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
public Color4 HyperDashAfterImageColour => hyperDashAfterImages.Colour;
|
||||
|
||||
protected override bool RemoveRewoundEntry => true;
|
||||
|
||||
private readonly DrawablePool<CatcherTrail> trailPool;
|
||||
|
||||
private readonly Container<CatcherTrail> dashTrails;
|
||||
private readonly Container<CatcherTrail> hyperDashTrails;
|
||||
private readonly Container<CatcherTrail> hyperDashAfterImages;
|
||||
|
||||
[Resolved]
|
||||
private ISkinSource skin { get; set; }
|
||||
|
||||
public CatcherTrailDisplay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
@ -48,50 +54,60 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
};
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin)
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.SkinChanged(skin);
|
||||
base.LoadComplete();
|
||||
|
||||
skin.SourceChanged += skinSourceChanged;
|
||||
skinSourceChanged();
|
||||
}
|
||||
|
||||
private void skinSourceChanged()
|
||||
{
|
||||
hyperDashTrails.Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR;
|
||||
hyperDashAfterImages.Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays a hyper-dash after-image of the catcher.
|
||||
/// </summary>
|
||||
public void DisplayHyperDashAfterImage(CatcherAnimationState animationState, float x, Vector2 scale)
|
||||
protected override void AddDrawable(CatcherTrailEntry entry, CatcherTrail drawable)
|
||||
{
|
||||
var trail = createTrail(animationState, x, scale);
|
||||
switch (entry.Animation)
|
||||
{
|
||||
case CatcherTrailAnimation.Dashing:
|
||||
dashTrails.Add(drawable);
|
||||
break;
|
||||
|
||||
hyperDashAfterImages.Add(trail);
|
||||
case CatcherTrailAnimation.HyperDashing:
|
||||
hyperDashTrails.Add(drawable);
|
||||
break;
|
||||
|
||||
trail.MoveToOffset(new Vector2(0, -10), 1200, Easing.In);
|
||||
trail.ScaleTo(trail.Scale * 0.95f).ScaleTo(trail.Scale * 1.2f, 1200, Easing.In);
|
||||
trail.FadeOut(1200);
|
||||
trail.Expire(true);
|
||||
case CatcherTrailAnimation.HyperDashAfterImage:
|
||||
hyperDashAfterImages.Add(drawable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing)
|
||||
protected override void RemoveDrawable(CatcherTrailEntry entry, CatcherTrail drawable)
|
||||
{
|
||||
var trail = createTrail(animationState, x, scale);
|
||||
switch (entry.Animation)
|
||||
{
|
||||
case CatcherTrailAnimation.Dashing:
|
||||
dashTrails.Remove(drawable);
|
||||
break;
|
||||
|
||||
if (hyperDashing)
|
||||
hyperDashTrails.Add(trail);
|
||||
else
|
||||
dashTrails.Add(trail);
|
||||
case CatcherTrailAnimation.HyperDashing:
|
||||
hyperDashTrails.Remove(drawable);
|
||||
break;
|
||||
|
||||
trail.FadeTo(0.4f).FadeOut(800, Easing.OutQuint);
|
||||
trail.Expire(true);
|
||||
case CatcherTrailAnimation.HyperDashAfterImage:
|
||||
hyperDashAfterImages.Remove(drawable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private CatcherTrail createTrail(CatcherAnimationState animationState, float x, Vector2 scale)
|
||||
protected override CatcherTrail GetDrawable(CatcherTrailEntry entry)
|
||||
{
|
||||
CatcherTrail trail = trailPool.Get();
|
||||
|
||||
trail.AnimationState = animationState;
|
||||
trail.Scale = scale;
|
||||
trail.Position = new Vector2(x, 0);
|
||||
|
||||
trail.Apply(entry);
|
||||
return trail;
|
||||
}
|
||||
|
||||
@ -107,5 +123,13 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
return maxTime;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (skin != null)
|
||||
skin.SourceChanged -= skinSourceChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
31
osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs
Normal file
31
osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// 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.Graphics.Performance;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatcherTrailEntry : LifetimeEntry
|
||||
{
|
||||
public readonly CatcherAnimationState CatcherState;
|
||||
|
||||
public readonly float Position;
|
||||
|
||||
/// <summary>
|
||||
/// The scaling of the catcher body. It also represents a flipped catcher (negative x component).
|
||||
/// </summary>
|
||||
public readonly Vector2 Scale;
|
||||
|
||||
public readonly CatcherTrailAnimation Animation;
|
||||
|
||||
public CatcherTrailEntry(double startTime, CatcherAnimationState catcherState, float position, Vector2 scale, CatcherTrailAnimation animation)
|
||||
{
|
||||
LifetimeStart = startTime;
|
||||
CatcherState = catcherState;
|
||||
Position = position;
|
||||
Scale = scale;
|
||||
Animation = animation;
|
||||
}
|
||||
}
|
||||
}
|
@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
private void onJudgementLoaded(DrawableOsuJudgement judgement)
|
||||
{
|
||||
judgementAboveHitObjectLayer.Add(judgement.GetProxyAboveHitObjectsContent());
|
||||
judgementAboveHitObjectLayer.Add(judgement.ProxiedAboveHitObjectsContent);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
@ -150,6 +150,10 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
DrawableOsuJudgement explosion = poolDictionary[result.Type].Get(doj => doj.Apply(result, judgedObject));
|
||||
|
||||
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);
|
||||
|
@ -2,10 +2,30 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
public class TaikoModClassic : ModClassic
|
||||
public class TaikoModClassic : ModClassic, IApplicableToDrawableRuleset<TaikoHitObject>, IUpdatableByPlayfield
|
||||
{
|
||||
private DrawableTaikoRuleset drawableTaikoRuleset;
|
||||
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<TaikoHitObject> drawableRuleset)
|
||||
{
|
||||
drawableTaikoRuleset = (DrawableTaikoRuleset)drawableRuleset;
|
||||
}
|
||||
|
||||
public void Update(Playfield playfield)
|
||||
{
|
||||
// Classic taiko scrolls at a constant 100px per 1000ms. More notes become visible as the playfield is lengthened.
|
||||
const float scroll_rate = 10;
|
||||
|
||||
// Since the time range will depend on a positional value, it is referenced to the x480 pixel space.
|
||||
float ratio = drawableTaikoRuleset.DrawHeight / 480;
|
||||
|
||||
drawableTaikoRuleset.TimeRange.Value = (playfield.HitObjectContainer.DrawWidth / ratio) * scroll_rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,23 +12,11 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
public class TaikoModHidden : ModHidden, IApplicableToDifficulty
|
||||
public class TaikoModHidden : ModHidden
|
||||
{
|
||||
public override string Description => @"Beats fade out before you hit them!";
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
|
||||
/// <summary>
|
||||
/// In osu-stable, the hit position is 160, so the active playfield is essentially 160 pixels shorter
|
||||
/// than the actual screen width. The normalized playfield height is 480, so on a 4:3 screen the
|
||||
/// playfield ratio of the active area up to the hit position will actually be (640 - 160) / 480 = 1.
|
||||
/// For custom resolutions/aspect ratios (x:y), the screen width given the normalized height becomes 480 * x / y instead,
|
||||
/// and the playfield ratio becomes (480 * x / y - 160) / 480 = x / y - 1/3.
|
||||
/// This constant is equal to the playfield ratio on 4:3 screens divided by the playfield ratio on 16:9 screens.
|
||||
/// </summary>
|
||||
private const double hd_sv_scale = (4.0 / 3.0 - 1.0 / 3.0) / (16.0 / 9.0 - 1.0 / 3.0);
|
||||
|
||||
private double originalSliderMultiplier;
|
||||
|
||||
private ControlPointInfo controlPointInfo;
|
||||
|
||||
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
@ -41,7 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
double beatLength = controlPointInfo.TimingPointAt(position).BeatLength;
|
||||
double speedMultiplier = controlPointInfo.DifficultyPointAt(position).SpeedMultiplier;
|
||||
|
||||
return originalSliderMultiplier * speedMultiplier * TimingControlPoint.DEFAULT_BEAT_LENGTH / beatLength;
|
||||
return speedMultiplier * TimingControlPoint.DEFAULT_BEAT_LENGTH / beatLength;
|
||||
}
|
||||
|
||||
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
@ -69,22 +57,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadFromDifficulty(BeatmapDifficulty difficulty)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyToDifficulty(BeatmapDifficulty difficulty)
|
||||
{
|
||||
// needs to be read after all processing has been run (TaikoBeatmapConverter applies an adjustment which would otherwise be omitted).
|
||||
originalSliderMultiplier = difficulty.SliderMultiplier;
|
||||
|
||||
// osu-stable has an added playfield cover that essentially forces a 4:3 playfield ratio, by cutting off all objects past that size.
|
||||
// This is not yet implemented; instead a playfield adjustment container is present which maintains a 16:9 ratio.
|
||||
// For now, increase the slider multiplier proportionally so that the notes stay on the screen for the same amount of time as on stable.
|
||||
// Note that this means that the notes will scroll faster as they have a longer distance to travel on the screen in that same amount of time.
|
||||
difficulty.SliderMultiplier /= hd_sv_scale;
|
||||
}
|
||||
|
||||
public override void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
controlPointInfo = beatmap.ControlPointInfo;
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -24,12 +25,14 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
public class DrawableTaikoRuleset : DrawableScrollingRuleset<TaikoHitObject>
|
||||
{
|
||||
private SkinnableDrawable scroller;
|
||||
public new BindableDouble TimeRange => base.TimeRange;
|
||||
|
||||
protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping;
|
||||
|
||||
protected override bool UserScrollSpeedAdjustment => false;
|
||||
|
||||
private SkinnableDrawable scroller;
|
||||
|
||||
public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
/// <summary>
|
||||
/// Default height of a <see cref="TaikoPlayfield"/> when inside a <see cref="DrawableTaikoRuleset"/>.
|
||||
/// </summary>
|
||||
public const float DEFAULT_HEIGHT = 178;
|
||||
public const float DEFAULT_HEIGHT = 212;
|
||||
|
||||
private Container<HitExplosion> hitExplosionContainer;
|
||||
private Container<KiaiHitExplosion> kiaiExplosionContainer;
|
||||
|
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)
|
||||
{
|
||||
await AllowImport.Task;
|
||||
return await (CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken));
|
||||
await AllowImport.Task.ConfigureAwait(false);
|
||||
return await (CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestControl()
|
||||
{
|
||||
AddAssert("Front page selected", () => header.Current.Value == "frontpage");
|
||||
AddAssert("Front page selected", () => header.Current.Value == NewsHeader.FrontPageString);
|
||||
AddAssert("1 tab total", () => header.TabCount == 1);
|
||||
|
||||
AddStep("Set article 1", () => header.SetArticle("1"));
|
||||
@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddAssert("2 tabs total", () => header.TabCount == 2);
|
||||
|
||||
AddStep("Set front page", () => header.SetFrontPage());
|
||||
AddAssert("Front page selected", () => header.Current.Value == "frontpage");
|
||||
AddAssert("Front page selected", () => header.Current.Value == NewsHeader.FrontPageString);
|
||||
AddAssert("1 tab total", () => header.TabCount == 1);
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestWikiHeader()
|
||||
{
|
||||
AddAssert("Current is index", () => checkCurrent("index"));
|
||||
AddAssert("Current is index", () => checkCurrent(WikiHeader.IndexPageString));
|
||||
|
||||
AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage
|
||||
{
|
||||
@ -54,8 +54,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddAssert("Current is welcome", () => checkCurrent("Welcome"));
|
||||
AddAssert("Check breadcrumb", checkBreadcrumb);
|
||||
|
||||
AddStep("Change current to index", () => header.Current.Value = "index");
|
||||
AddAssert("Current is index", () => checkCurrent("index"));
|
||||
AddStep("Change current to index", () => header.Current.Value = WikiHeader.IndexPageString);
|
||||
AddAssert("Current is index", () => checkCurrent(WikiHeader.IndexPageString));
|
||||
|
||||
AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage
|
||||
{
|
||||
@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddAssert("Check breadcrumb", checkBreadcrumb);
|
||||
}
|
||||
|
||||
private bool checkCurrent(string expectedCurrent) => header.Current.Value == expectedCurrent;
|
||||
private bool checkCurrent(LocalisableString expectedCurrent) => header.Current.Value == expectedCurrent;
|
||||
|
||||
private bool checkBreadcrumb()
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
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.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneLabelledColourPalette : OsuTestScene
|
||||
public class TestSceneLabelledColourPalette : OsuManualInputManagerTestScene
|
||||
{
|
||||
private LabelledColourPalette component;
|
||||
|
||||
@ -30,21 +35,41 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
}, 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)
|
||||
{
|
||||
AddStep("create component", () =>
|
||||
{
|
||||
Child = new Container
|
||||
Child = new OsuContextMenuContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Width = 500,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = component = new LabelledColourPalette
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = 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 #"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -66,5 +91,36 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
RNG.NextSingle(),
|
||||
RNG.NextSingle(),
|
||||
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,7 +1,6 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@ -11,6 +10,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Menu;
|
||||
@ -198,8 +198,8 @@ namespace osu.Game.Tournament.Components
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new DiffPiece(("Length", TimeSpan.FromMilliseconds(length).ToString(@"mm\:ss"))),
|
||||
new DiffPiece(("BPM", $"{bpm:0.#}"))
|
||||
new DiffPiece(("Length", length.ToFormattedDuration().ToString())),
|
||||
new DiffPiece(("BPM", $"{bpm:0.#}")),
|
||||
}
|
||||
},
|
||||
new Container
|
||||
|
@ -1,2 +1,3 @@
|
||||
[*.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");
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -59,33 +60,37 @@ namespace osu.Game.Graphics.Containers
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new GridContainer
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Content = new[]
|
||||
new GridContainer
|
||||
{
|
||||
new[]
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Content = new[]
|
||||
{
|
||||
handleContainer = new Container
|
||||
new[]
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Horizontal = 5 },
|
||||
Child = handle = new PlaylistItemHandle
|
||||
handleContainer = new Container
|
||||
{
|
||||
Size = new Vector2(12),
|
||||
Colour = HandleColour,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0
|
||||
}
|
||||
},
|
||||
CreateContent()
|
||||
}
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Horizontal = 5 },
|
||||
Child = handle = new PlaylistItemHandle
|
||||
{
|
||||
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) },
|
||||
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }
|
||||
new HoverClickSounds()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
Size = TwoLayerButton.SIZE_EXTENDED;
|
||||
|
||||
Child = button = new TwoLayerButton
|
||||
Child = button = new TwoLayerButton(HoverSampleSet.Submit)
|
||||
{
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
|
@ -56,6 +56,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
private Vector2 hoverSpacing => new Vector2(3f, 0f);
|
||||
|
||||
public DialogButton()
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
|
@ -23,14 +23,20 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[Resolved]
|
||||
private GameHost host { get; set; }
|
||||
|
||||
private readonly SpriteIcon linkIcon;
|
||||
|
||||
public ExternalLinkButton(string link = null)
|
||||
{
|
||||
Link = link;
|
||||
Size = new Vector2(12);
|
||||
InternalChild = new SpriteIcon
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
Icon = FontAwesome.Solid.ExternalLinkAlt,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
linkIcon = new SpriteIcon
|
||||
{
|
||||
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)
|
||||
{
|
||||
InternalChild.FadeColour(hoverColour, 500, Easing.OutQuint);
|
||||
linkIcon.FadeColour(hoverColour, 500, Easing.OutQuint);
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
InternalChild.FadeColour(Color4.White, 500, Easing.OutQuint);
|
||||
linkIcon.FadeColour(Color4.White, 500, Easing.OutQuint);
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[Description("default")]
|
||||
Default,
|
||||
|
||||
[Description("soft")]
|
||||
Soft,
|
||||
[Description("submit")]
|
||||
Submit,
|
||||
|
||||
[Description("button")]
|
||||
Button,
|
||||
|
@ -71,7 +71,8 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
public TwoLayerButton()
|
||||
public TwoLayerButton(HoverSampleSet sampleSet = HoverSampleSet.Default)
|
||||
: base(sampleSet)
|
||||
{
|
||||
Size = SIZE_RETRACTED;
|
||||
Shear = shear;
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
@ -12,6 +13,7 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterfaceV2
|
||||
@ -19,12 +21,16 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
/// <summary>
|
||||
/// A component which displays a colour along with related description text.
|
||||
/// </summary>
|
||||
public class ColourDisplay : CompositeDrawable, IHasCurrentValue<Colour4>, IHasPopover
|
||||
public class ColourDisplay : CompositeDrawable, IHasCurrentValue<Colour4>
|
||||
{
|
||||
/// <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;
|
||||
|
||||
public Bindable<Colour4> Current
|
||||
@ -63,26 +69,10 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
Spacing = new Vector2(0, 10),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuClickableContainer
|
||||
new ColourCircle
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 100,
|
||||
CornerRadius = 50,
|
||||
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)
|
||||
}
|
||||
},
|
||||
Action = this.ShowPopover
|
||||
Current = { BindTarget = Current },
|
||||
DeleteRequested = () => DeleteRequested?.Invoke(this)
|
||||
},
|
||||
colourName = new OsuSpriteText
|
||||
{
|
||||
@ -93,26 +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()
|
||||
{
|
||||
fill.Colour = current.Value;
|
||||
colourHexCode.Text = current.Value.ToHex();
|
||||
colourHexCode.Colour = OsuColour.ForegroundTextColourFor(current.Value);
|
||||
}
|
||||
private readonly Box fill;
|
||||
private readonly OsuSpriteText colourHexCode;
|
||||
|
||||
public Popover GetPopover() => new OsuPopover(false)
|
||||
{
|
||||
Child = new OsuColourPicker
|
||||
public ColourCircle()
|
||||
{
|
||||
Current = { BindTarget = Current }
|
||||
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,12 +1,17 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
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 osuTK;
|
||||
|
||||
@ -36,36 +41,24 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
}
|
||||
}
|
||||
|
||||
private FillFlowContainer<ColourDisplay> palette;
|
||||
private Container placeholder;
|
||||
private FillFlowContainer palette;
|
||||
|
||||
private IEnumerable<ColourDisplay> colourDisplays => palette.OfType<ColourDisplay>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
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,
|
||||
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)
|
||||
}
|
||||
}
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(10),
|
||||
Direction = FillDirection.Full
|
||||
};
|
||||
}
|
||||
|
||||
@ -73,30 +66,20 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Colours.BindCollectionChanged((_, args) => updatePalette(args), true);
|
||||
Colours.BindCollectionChanged((_, args) =>
|
||||
{
|
||||
if (args.Action != NotifyCollectionChangedAction.Replace)
|
||||
updatePalette();
|
||||
}, true);
|
||||
FinishTransforms(true);
|
||||
}
|
||||
|
||||
private const int fade_duration = 200;
|
||||
|
||||
private void updatePalette(NotifyCollectionChangedEventArgs args)
|
||||
private void updatePalette()
|
||||
{
|
||||
if (args.Action == NotifyCollectionChangedAction.Replace)
|
||||
return;
|
||||
|
||||
palette.Clear();
|
||||
|
||||
if (Colours.Any())
|
||||
{
|
||||
palette.FadeIn(fade_duration, Easing.OutQuint);
|
||||
placeholder.FadeOut(fade_duration, Easing.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
palette.FadeOut(fade_duration, Easing.OutQuint);
|
||||
placeholder.FadeIn(fade_duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Colours.Count; ++i)
|
||||
{
|
||||
// copy to avoid accesses to modified closure.
|
||||
@ -109,20 +92,91 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
});
|
||||
|
||||
display.Current.BindValueChanged(colour => Colours[colourIndex] = colour.NewValue);
|
||||
display.DeleteRequested += colourDeletionRequested;
|
||||
}
|
||||
|
||||
palette.Add(new AddColourButton
|
||||
{
|
||||
Action = () => Colours.Add(Colour4.White)
|
||||
});
|
||||
|
||||
reindexItems();
|
||||
}
|
||||
|
||||
private void colourDeletionRequested(ColourDisplay display) => Colours.RemoveAt(palette.IndexOf(display));
|
||||
|
||||
private void reindexItems()
|
||||
{
|
||||
int index = 1;
|
||||
|
||||
foreach (var colour in palette)
|
||||
foreach (var colourDisplay in colourDisplays)
|
||||
{
|
||||
colour.ColourName = $"{colourNamePrefix} {index}";
|
||||
colourDisplay.ColourName = $"{colourNamePrefix} {index}";
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
Depth = 1
|
||||
},
|
||||
new HoverClickSounds(HoverSampleSet.Soft)
|
||||
new HoverClickSounds()
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
Depth = 1
|
||||
},
|
||||
new HoverClickSounds(HoverSampleSet.Soft)
|
||||
new HoverClickSounds()
|
||||
});
|
||||
}
|
||||
|
||||
|
44
osu.Game/Localisation/NamedOverlayComponentStrings.cs
Normal file
44
osu.Game/Localisation/NamedOverlayComponentStrings.cs
Normal file
@ -0,0 +1,44 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class NamedOverlayComponentStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.NamedOverlayComponent";
|
||||
|
||||
/// <summary>
|
||||
/// "browse for new beatmaps"
|
||||
/// </summary>
|
||||
public static LocalisableString BeatmapListingDescription => new TranslatableString(getKey(@"beatmap_listing_description"), @"browse for new beatmaps");
|
||||
|
||||
/// <summary>
|
||||
/// "track recent dev updates in the osu! ecosystem"
|
||||
/// </summary>
|
||||
public static LocalisableString ChangelogDescription => new TranslatableString(getKey(@"changelog_description"), @"track recent dev updates in the osu! ecosystem");
|
||||
|
||||
/// <summary>
|
||||
/// "view your friends and other information"
|
||||
/// </summary>
|
||||
public static LocalisableString DashboardDescription => new TranslatableString(getKey(@"dashboard_description"), @"view your friends and other information");
|
||||
|
||||
/// <summary>
|
||||
/// "find out who's the best right now"
|
||||
/// </summary>
|
||||
public static LocalisableString RankingsDescription => new TranslatableString(getKey(@"rankings_description"), @"find out who's the best right now");
|
||||
|
||||
/// <summary>
|
||||
/// "get up-to-date on community happenings"
|
||||
/// </summary>
|
||||
public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news_description"), @"get up-to-date on community happenings");
|
||||
|
||||
/// <summary>
|
||||
/// "knowledge base"
|
||||
/// </summary>
|
||||
public static LocalisableString WikiDescription => new TranslatableString(getKey(@"wiki_description"), @"knowledge base");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
@ -150,7 +150,7 @@ namespace osu.Game.Online.API
|
||||
|
||||
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");
|
||||
Logout();
|
||||
|
@ -31,6 +31,7 @@ namespace osu.Game.Online.Chat
|
||||
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new LinkHoverSounds(sampleSet, Parts);
|
||||
|
||||
public DrawableLinkCompiler(IEnumerable<Drawable> parts)
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
Parts = parts.ToList();
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
// 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.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.BeatmapListing
|
||||
{
|
||||
public class BeatmapListingHeader : OverlayHeader
|
||||
@ -11,8 +14,8 @@ namespace osu.Game.Overlays.BeatmapListing
|
||||
{
|
||||
public BeatmapListingTitle()
|
||||
{
|
||||
Title = "beatmap listing";
|
||||
Description = "browse for new beatmaps";
|
||||
Title = PageTitleStrings.MainBeatmapsetsControllerIndex;
|
||||
Description = NamedOverlayComponentStrings.BeatmapListingDescription;
|
||||
IconTexture = "Icons/Hexacons/beatmap";
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
||||
protected Action ViewBeatmap;
|
||||
|
||||
protected BeatmapPanel(BeatmapSetInfo setInfo)
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
Debug.Assert(setInfo.OnlineBeatmapSetID != null);
|
||||
|
||||
|
@ -10,6 +10,7 @@ using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osuTK;
|
||||
@ -62,7 +63,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
}
|
||||
else
|
||||
{
|
||||
length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToString(@"m\:ss");
|
||||
length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToFormattedDuration();
|
||||
circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString();
|
||||
sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToString();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Rulesets;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -54,7 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
public BeatmapHeaderTitle()
|
||||
{
|
||||
Title = "beatmap info";
|
||||
Title = PageTitleStrings.MainBeatmapsetsControllerShow;
|
||||
IconTexture = "Icons/Hexacons/beatmap";
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,10 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
@ -21,16 +24,16 @@ namespace osu.Game.Overlays.Changelog
|
||||
|
||||
public ChangelogUpdateStreamControl Streams;
|
||||
|
||||
private const string listing_string = "listing";
|
||||
public static LocalisableString ListingString => LayoutStrings.HeaderChangelogIndex;
|
||||
|
||||
private Box streamsBackground;
|
||||
|
||||
public ChangelogHeader()
|
||||
{
|
||||
TabControl.AddItem(listing_string);
|
||||
TabControl.AddItem(ListingString);
|
||||
Current.ValueChanged += e =>
|
||||
{
|
||||
if (e.NewValue == listing_string)
|
||||
if (e.NewValue == ListingString)
|
||||
ListingSelected?.Invoke();
|
||||
};
|
||||
|
||||
@ -63,7 +66,7 @@ namespace osu.Game.Overlays.Changelog
|
||||
}
|
||||
else
|
||||
{
|
||||
Current.Value = listing_string;
|
||||
Current.Value = ListingString;
|
||||
Streams.Current.Value = null;
|
||||
}
|
||||
}
|
||||
@ -114,8 +117,8 @@ namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
public ChangelogHeaderTitle()
|
||||
{
|
||||
Title = "changelog";
|
||||
Description = "track recent dev updates in the osu! ecosystem";
|
||||
Title = PageTitleStrings.MainChangelogControllerDefault;
|
||||
Description = NamedOverlayComponentStrings.ChangelogDescription;
|
||||
IconTexture = "Icons/Hexacons/devtools";
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
using System;
|
||||
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.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -13,6 +16,7 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Chat;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -39,6 +43,8 @@ namespace osu.Game.Overlays.Chat.Tabs
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
private Sample sampleTabSwitched;
|
||||
|
||||
public ChannelTabItem(Channel 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]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OsuColour colours, AudioManager audio)
|
||||
{
|
||||
BackgroundActive = colours.ChatBlue;
|
||||
BackgroundInactive = colours.Gray4;
|
||||
backgroundHover = colours.Gray7;
|
||||
sampleTabSwitched = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select");
|
||||
|
||||
highlightBox.Colour = colours.Yellow;
|
||||
}
|
||||
@ -217,7 +225,14 @@ namespace osu.Game.Overlays.Chat.Tabs
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Chat.Tabs
|
||||
if (value.Type != ChannelType.PM)
|
||||
throw new ArgumentException("Argument value needs to have the targettype user!");
|
||||
|
||||
ClickableAvatar avatar;
|
||||
DrawableAvatar avatar;
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
@ -48,10 +48,9 @@ namespace osu.Game.Overlays.Chat.Tabs
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Masking = true,
|
||||
Child = new DelayedLoadWrapper(avatar = new ClickableAvatar(value.Users.First())
|
||||
Child = new DelayedLoadWrapper(avatar = new DrawableAvatar(value.Users.First())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
OpenOnClick = false,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
})
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.Dashboard
|
||||
@ -15,8 +16,8 @@ namespace osu.Game.Overlays.Dashboard
|
||||
{
|
||||
public DashboardTitle()
|
||||
{
|
||||
Title = HomeStrings.UserTitle;
|
||||
Description = "view your friends and other information";
|
||||
Title = PageTitleStrings.MainHomeControllerIndex;
|
||||
Description = NamedOverlayComponentStrings.DashboardDescription;
|
||||
IconTexture = "Icons/Hexacons/social";
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Overlays.News
|
||||
@ -28,6 +29,7 @@ namespace osu.Game.Overlays.News
|
||||
private TextFlowContainer main;
|
||||
|
||||
public NewsCard(APINewsPost post)
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
this.post = post;
|
||||
|
||||
|
@ -4,12 +4,15 @@
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.News
|
||||
{
|
||||
public class NewsHeader : BreadcrumbControlOverlayHeader
|
||||
{
|
||||
private const string front_page_string = "frontpage";
|
||||
public static LocalisableString FrontPageString => NewsStrings.IndexTitleInfo;
|
||||
|
||||
public Action ShowFrontPage;
|
||||
|
||||
@ -17,7 +20,7 @@ namespace osu.Game.Overlays.News
|
||||
|
||||
public NewsHeader()
|
||||
{
|
||||
TabControl.AddItem(front_page_string);
|
||||
TabControl.AddItem(FrontPageString);
|
||||
|
||||
article.BindValueChanged(onArticleChanged, true);
|
||||
}
|
||||
@ -28,7 +31,7 @@ namespace osu.Game.Overlays.News
|
||||
|
||||
Current.BindValueChanged(e =>
|
||||
{
|
||||
if (e.NewValue == front_page_string)
|
||||
if (e.NewValue == FrontPageString)
|
||||
ShowFrontPage?.Invoke();
|
||||
});
|
||||
}
|
||||
@ -49,7 +52,7 @@ namespace osu.Game.Overlays.News
|
||||
}
|
||||
else
|
||||
{
|
||||
Current.Value = front_page_string;
|
||||
Current.Value = FrontPageString;
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,8 +64,8 @@ namespace osu.Game.Overlays.News
|
||||
{
|
||||
public NewsHeaderTitle()
|
||||
{
|
||||
Title = "news";
|
||||
Description = "get up-to-date on community happenings";
|
||||
Title = PageTitleStrings.MainNewsControllerDefault;
|
||||
Description = NamedOverlayComponentStrings.NewsDescription;
|
||||
IconTexture = "Icons/Hexacons/news";
|
||||
}
|
||||
}
|
||||
|
@ -15,13 +15,18 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.News.Sidebar
|
||||
{
|
||||
public class MonthSection : CompositeDrawable
|
||||
{
|
||||
private const int animation_duration = 250;
|
||||
private Sample sampleOpen;
|
||||
private Sample sampleClose;
|
||||
|
||||
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
|
||||
@ -59,6 +79,8 @@ namespace osu.Game.Overlays.News.Sidebar
|
||||
|
||||
private readonly SpriteIcon icon;
|
||||
|
||||
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds();
|
||||
|
||||
public DropdownHeader(int month, int year)
|
||||
{
|
||||
var date = new DateTime(year, month, 1);
|
||||
@ -104,6 +126,7 @@ namespace osu.Game.Overlays.News.Sidebar
|
||||
private readonly APINewsPost post;
|
||||
|
||||
public PostButton(APINewsPost post)
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
this.post = post;
|
||||
|
||||
|
@ -6,6 +6,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.Profile.Sections
|
||||
{
|
||||
@ -17,6 +18,7 @@ namespace osu.Game.Overlays.Profile.Sections
|
||||
private readonly BeatmapInfo beatmap;
|
||||
|
||||
protected BeatmapMetadataContainer(BeatmapInfo beatmap)
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
this.beatmap = beatmap;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
@ -52,7 +53,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 12),
|
||||
Text = UsersStrings.ShowExtraTopRanksPpWeight(weight.ToString("0%"))
|
||||
Text = UsersStrings.ShowExtraTopRanksPpWeight(weight.ToLocalisableString("0%"))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Users;
|
||||
|
||||
@ -29,18 +31,10 @@ namespace osu.Game.Overlays.Rankings
|
||||
{
|
||||
public RankingsTitle()
|
||||
{
|
||||
Title = "ranking";
|
||||
Description = "find out who's the best right now";
|
||||
Title = PageTitleStrings.MainRankingControllerDefault;
|
||||
Description = NamedOverlayComponentStrings.RankingsDescription;
|
||||
IconTexture = "Icons/Hexacons/rankings";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum RankingsScope
|
||||
{
|
||||
Performance,
|
||||
Spotlights,
|
||||
Score,
|
||||
Country
|
||||
}
|
||||
}
|
||||
|
42
osu.Game/Overlays/Rankings/RankingsScope.cs
Normal file
42
osu.Game/Overlays/Rankings/RankingsScope.cs
Normal file
@ -0,0 +1,42 @@
|
||||
// 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;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings
|
||||
{
|
||||
[LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))]
|
||||
public enum RankingsScope
|
||||
{
|
||||
Performance,
|
||||
Spotlights,
|
||||
Score,
|
||||
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.
|
||||
// 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
|
||||
{
|
||||
public class RankingsSortTabControl : OverlaySortTabControl<RankingsSortCriteria>
|
||||
{
|
||||
public RankingsSortTabControl()
|
||||
{
|
||||
Title = "Show";
|
||||
Title = RankingsStrings.FilterTitle.ToUpper();
|
||||
}
|
||||
}
|
||||
|
||||
[LocalisableEnum(typeof(RankingsSortCriteriaEnumLocalisationMapper))]
|
||||
public enum RankingsSortCriteria
|
||||
{
|
||||
All,
|
||||
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.Game.Online.API.Requests;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings
|
||||
{
|
||||
@ -92,10 +94,10 @@ namespace osu.Game.Overlays.Rankings
|
||||
Margin = new MarginPadding { Bottom = 5 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
startDateColumn = new InfoColumn(@"Start Date"),
|
||||
endDateColumn = new InfoColumn(@"End Date"),
|
||||
mapCountColumn = new InfoColumn(@"Map Count"),
|
||||
participantsColumn = new InfoColumn(@"Participants")
|
||||
startDateColumn = new InfoColumn(RankingsStrings.SpotlightStartDate),
|
||||
endDateColumn = new InfoColumn(RankingsStrings.SpotlightEndDate),
|
||||
mapCountColumn = new InfoColumn(RankingsStrings.SpotlightMapCount),
|
||||
participantsColumn = new InfoColumn(RankingsStrings.SpotlightParticipants)
|
||||
}
|
||||
},
|
||||
new RankingsSortTabControl
|
||||
@ -122,22 +124,22 @@ namespace osu.Game.Overlays.Rankings
|
||||
{
|
||||
startDateColumn.Value = dateToString(response.Spotlight.StartDate);
|
||||
endDateColumn.Value = dateToString(response.Spotlight.EndDate);
|
||||
mapCountColumn.Value = response.BeatmapSets.Count.ToString();
|
||||
participantsColumn.Value = response.Spotlight.Participants?.ToString("N0");
|
||||
mapCountColumn.Value = response.BeatmapSets.Count.ToLocalisableString(@"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
|
||||
{
|
||||
public string Value
|
||||
public LocalisableString Value
|
||||
{
|
||||
set => valueText.Text = value;
|
||||
}
|
||||
|
||||
private readonly OsuSpriteText valueText;
|
||||
|
||||
public InfoColumn(string name)
|
||||
public InfoColumn(LocalisableString name)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Direction = FillDirection.Vertical;
|
||||
|
@ -9,6 +9,8 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Framework.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings.Tables
|
||||
{
|
||||
@ -21,12 +23,12 @@ namespace osu.Game.Overlays.Rankings.Tables
|
||||
|
||||
protected override RankingsTableColumn[] CreateAdditionalHeaders() => new[]
|
||||
{
|
||||
new RankingsTableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn("Avg. Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true),
|
||||
new RankingsTableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn(RankingsStrings.StatActiveUsers, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn(RankingsStrings.StatPlayCount, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn(RankingsStrings.StatRankedScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn(RankingsStrings.StatAverageScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn(RankingsStrings.StatPerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true),
|
||||
new RankingsTableColumn(RankingsStrings.StatAveragePerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
};
|
||||
|
||||
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[]
|
||||
{
|
||||
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
|
||||
{
|
||||
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 osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings.Tables
|
||||
@ -17,12 +19,12 @@ namespace osu.Game.Overlays.Rankings.Tables
|
||||
|
||||
protected override RankingsTableColumn[] CreateUniqueHeaders() => new[]
|
||||
{
|
||||
new RankingsTableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true),
|
||||
new RankingsTableColumn(RankingsStrings.StatPerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true),
|
||||
};
|
||||
|
||||
protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[]
|
||||
{
|
||||
new RowText { Text = $@"{item.PP:N0}", }
|
||||
new RowText { Text = item.PP.ToLocalisableString(@"N0"), }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Rankings.Tables
|
||||
|
||||
private OsuSpriteText createIndexDrawable(int index) => new RowText
|
||||
{
|
||||
Text = $"#{index + 1}",
|
||||
Text = (index + 1).ToLocalisableString(@"\##"),
|
||||
Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.SemiBold)
|
||||
};
|
||||
|
||||
@ -144,7 +144,7 @@ namespace osu.Game.Overlays.Rankings.Tables
|
||||
}
|
||||
}
|
||||
|
||||
protected class ColoredRowText : RowText
|
||||
protected class ColouredRowText : RowText
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
|
@ -4,6 +4,8 @@
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings.Tables
|
||||
@ -17,19 +19,19 @@ namespace osu.Game.Overlays.Rankings.Tables
|
||||
|
||||
protected override RankingsTableColumn[] CreateUniqueHeaders() => new[]
|
||||
{
|
||||
new RankingsTableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true)
|
||||
new RankingsTableColumn(RankingsStrings.StatTotalScore, 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[]
|
||||
{
|
||||
new ColoredRowText
|
||||
new ColouredRowText
|
||||
{
|
||||
Text = $@"{item.TotalScore:N0}",
|
||||
Text = item.TotalScore.ToLocalisableString(@"N0"),
|
||||
},
|
||||
new RowText
|
||||
{
|
||||
Text = $@"{item.RankedScore:N0}",
|
||||
Text = item.RankedScore.ToLocalisableString(@"N0")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.Rankings.Tables
|
||||
{
|
||||
@ -20,12 +21,12 @@ 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 RankingsTableColumn[] CreateAdditionalHeaders() => new[]
|
||||
{
|
||||
new RankingsTableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn(RankingsStrings.StatAccuracy, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
new RankingsTableColumn(RankingsStrings.StatPlayCount, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)),
|
||||
}.Concat(CreateUniqueHeaders())
|
||||
.Concat(GradeColumns.Select(grade => new GradeTableColumn(grade, Anchor.Centre, new Dimension(GridSizeMode.AutoSize))))
|
||||
.ToArray();
|
||||
@ -46,13 +47,13 @@ namespace osu.Game.Overlays.Rankings.Tables
|
||||
|
||||
protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[]
|
||||
{
|
||||
new ColoredRowText { Text = item.DisplayAccuracy, },
|
||||
new ColoredRowText { Text = $@"{item.PlayCount:N0}", },
|
||||
new ColouredRowText { Text = item.DisplayAccuracy, },
|
||||
new ColouredRowText { Text = item.PlayCount.ToLocalisableString(@"N0") },
|
||||
}.Concat(CreateUniqueContent(item)).Concat(new[]
|
||||
{
|
||||
new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]:N0}", },
|
||||
new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]:N0}", },
|
||||
new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.A]:N0}", }
|
||||
new ColouredRowText { Text = (item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]).ToLocalisableString(@"N0"), },
|
||||
new ColouredRowText { Text = (item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]).ToLocalisableString(@"N0"), },
|
||||
new ColouredRowText { Text = item.GradesCount[ScoreRank.A].ToLocalisableString(@"N0"), }
|
||||
}).ToArray();
|
||||
|
||||
protected abstract RankingsTableColumn[] CreateUniqueHeaders();
|
||||
|
@ -138,7 +138,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new HoverClickSounds()
|
||||
};
|
||||
|
||||
foreach (var b in bindings)
|
||||
@ -458,6 +459,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
Origin = Anchor.Centre,
|
||||
Text = keyBinding.KeyCombination.ReadableString(),
|
||||
},
|
||||
new HoverSounds()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,15 +6,18 @@ using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.Wiki
|
||||
{
|
||||
public class WikiHeader : BreadcrumbControlOverlayHeader
|
||||
{
|
||||
private const string index_page_string = "index";
|
||||
private const string index_path = "Main_Page";
|
||||
|
||||
public static LocalisableString IndexPageString => LayoutStrings.HeaderHelpIndex;
|
||||
|
||||
public readonly Bindable<APIWikiPage> WikiPageData = new Bindable<APIWikiPage>();
|
||||
|
||||
public Action ShowIndexPage;
|
||||
@ -22,8 +25,8 @@ namespace osu.Game.Overlays.Wiki
|
||||
|
||||
public WikiHeader()
|
||||
{
|
||||
TabControl.AddItem(index_page_string);
|
||||
Current.Value = index_page_string;
|
||||
TabControl.AddItem(IndexPageString);
|
||||
Current.Value = IndexPageString;
|
||||
|
||||
WikiPageData.BindValueChanged(onWikiPageChange);
|
||||
Current.BindValueChanged(onCurrentChange);
|
||||
@ -37,11 +40,11 @@ namespace osu.Game.Overlays.Wiki
|
||||
TabControl.Clear();
|
||||
Current.Value = null;
|
||||
|
||||
TabControl.AddItem(index_page_string);
|
||||
TabControl.AddItem(IndexPageString);
|
||||
|
||||
if (e.NewValue.Path == index_path)
|
||||
{
|
||||
Current.Value = index_page_string;
|
||||
Current.Value = IndexPageString;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -57,7 +60,7 @@ namespace osu.Game.Overlays.Wiki
|
||||
if (e.NewValue == TabControl.Items.LastOrDefault())
|
||||
return;
|
||||
|
||||
if (e.NewValue == index_page_string)
|
||||
if (e.NewValue == IndexPageString)
|
||||
{
|
||||
ShowIndexPage?.Invoke();
|
||||
return;
|
||||
@ -74,8 +77,8 @@ namespace osu.Game.Overlays.Wiki
|
||||
{
|
||||
public WikiHeaderTitle()
|
||||
{
|
||||
Title = "wiki";
|
||||
Description = "knowledge base";
|
||||
Title = PageTitleStrings.MainWikiControllerDefault;
|
||||
Description = NamedOverlayComponentStrings.WikiDescription;
|
||||
IconTexture = "Icons/Hexacons/wiki";
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.Diagnostics;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
@ -31,6 +32,9 @@ namespace osu.Game.Rulesets.Judgements
|
||||
|
||||
private readonly Container aboveHitObjectsContent;
|
||||
|
||||
private readonly Lazy<Drawable> proxiedAboveHitObjectsContent;
|
||||
public Drawable ProxiedAboveHitObjectsContent => proxiedAboveHitObjectsContent.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a drawable which visualises a <see cref="Judgements.Judgement"/>.
|
||||
/// </summary>
|
||||
@ -52,6 +56,8 @@ namespace osu.Game.Rulesets.Judgements
|
||||
Depth = float.MinValue,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
});
|
||||
|
||||
proxiedAboveHitObjectsContent = new Lazy<Drawable>(() => aboveHitObjectsContent.CreateProxy());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -60,8 +66,6 @@ namespace osu.Game.Rulesets.Judgements
|
||||
prepareDrawables();
|
||||
}
|
||||
|
||||
public Drawable GetProxyAboveHitObjectsContent() => aboveHitObjectsContent.CreateProxy();
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
|
@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
public interface IApplicableToHealthProcessor : IApplicableMod
|
||||
{
|
||||
/// <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>
|
||||
void ApplyToHealthProcessor(HealthProcessor healthProcessor);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
public interface IApplicableToScoreProcessor : IApplicableMod
|
||||
{
|
||||
/// <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>
|
||||
void ApplyToScoreProcessor(ScoreProcessor scoreProcessor);
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@ -11,11 +11,11 @@ using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public class Metronome : BeatSyncedContainer
|
||||
public class Metronome : BeatSyncedContainer, IAdjustableAudioComponent
|
||||
{
|
||||
private readonly double firstHitTime;
|
||||
|
||||
private PausableSkinnableSound sample;
|
||||
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)
|
||||
@ -23,15 +23,8 @@ namespace osu.Game.Rulesets.Mods
|
||||
this.firstHitTime = firstHitTime;
|
||||
AllowMistimedEventFiring = false;
|
||||
Divisor = 1;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana"))
|
||||
};
|
||||
InternalChild = sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana"));
|
||||
}
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
||||
@ -49,5 +42,50 @@ namespace osu.Game.Rulesets.Mods
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,18 @@
|
||||
// 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
|
||||
{
|
||||
@ -22,27 +26,79 @@ namespace osu.Game.Rulesets.Mods
|
||||
public override double ScoreMultiplier => 1;
|
||||
}
|
||||
|
||||
public abstract class ModMuted<TObject> : ModMuted, IApplicableToDrawableRuleset<TObject>, IApplicableToTrack
|
||||
public abstract class ModMuted<TObject> : ModMuted, IApplicableToDrawableRuleset<TObject>, IApplicableToTrack, IApplicableToScoreProcessor
|
||||
where TObject : HitObject
|
||||
{
|
||||
private readonly BindableNumber<double> volumeAdjust = new BindableDouble();
|
||||
private readonly BindableNumber<double> mainVolumeAdjust = new BindableDouble(0.5);
|
||||
private readonly BindableNumber<double> metronomeVolumeAdjust = new BindableDouble(0.5);
|
||||
|
||||
[SettingSource("Enable metronome", "Add a metronome to help you keep track of the rhythm.")]
|
||||
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, volumeAdjust);
|
||||
track.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust);
|
||||
}
|
||||
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<TObject> drawableRuleset)
|
||||
{
|
||||
if (EnableMetronome.Value)
|
||||
drawableRuleset.Overlays.Add(new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime));
|
||||
{
|
||||
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.
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Input.Handlers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Replays;
|
||||
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.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
@ -98,6 +99,14 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
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>
|
||||
/// Creates a ruleset visualisation for the provided ruleset and beatmap.
|
||||
/// </summary>
|
||||
@ -155,23 +164,28 @@ namespace osu.Game.Rulesets.UI
|
||||
[BackgroundDependencyLoader]
|
||||
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,
|
||||
Children = new Drawable[]
|
||||
FrameStableComponents,
|
||||
audioContainer = new AudioContainer
|
||||
{
|
||||
FrameStableComponents,
|
||||
KeyBindingInputManager
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = KeyBindingInputManager
|
||||
.WithChild(CreatePlayfieldAdjustmentContainer()
|
||||
.WithChild(Playfield)
|
||||
),
|
||||
Overlays,
|
||||
}
|
||||
},
|
||||
},
|
||||
Overlays,
|
||||
}
|
||||
};
|
||||
|
||||
Audio = audioContainer;
|
||||
|
||||
if ((ResumeOverlay = CreateResumeOverlay()) != null)
|
||||
{
|
||||
AddInternal(CreateInputManager()
|
||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
/// <summary>
|
||||
/// The maximum span of time that may be visible by the length of the scrolling axes.
|
||||
/// </summary>
|
||||
private const double time_span_max = 10000;
|
||||
private const double time_span_max = 20000;
|
||||
|
||||
/// <summary>
|
||||
/// The step increase/decrease of the span of time visible by the length of the scrolling axes.
|
||||
|
@ -11,7 +11,6 @@ using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -67,7 +66,6 @@ namespace osu.Game.Screens.Edit
|
||||
private EditorClock clock { get; set; }
|
||||
|
||||
public RowBackground(object item)
|
||||
: base(HoverSampleSet.Soft)
|
||||
{
|
||||
Item = item;
|
||||
|
||||
|
@ -297,11 +297,19 @@ namespace osu.Game.Screens.Play
|
||||
ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged);
|
||||
HealthProcessor.Failed += onFail;
|
||||
|
||||
foreach (var mod in Mods.Value.OfType<IApplicableToScoreProcessor>())
|
||||
mod.ApplyToScoreProcessor(ScoreProcessor);
|
||||
// Provide judgement processors to mods after they're loaded so that they're on the gameplay clock,
|
||||
// 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>())
|
||||
mod.ApplyToHealthProcessor(HealthProcessor);
|
||||
HealthProcessor.OnLoadComplete += _ =>
|
||||
{
|
||||
foreach (var mod in Mods.Value.OfType<IApplicableToHealthProcessor>())
|
||||
mod.ApplyToHealthProcessor(HealthProcessor);
|
||||
};
|
||||
|
||||
IsBreakTime.BindTo(breakTracker.IsBreakTime);
|
||||
IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
|
||||
|
@ -178,7 +178,7 @@ namespace osu.Game.Screens.Play
|
||||
float barHeight = bottom_bar_height + handle_size.Y;
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@ -333,7 +334,7 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
Name = "Length",
|
||||
CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Length),
|
||||
Content = TimeSpan.FromMilliseconds(beatmap.BeatmapInfo.Length).ToString(@"m\:ss"),
|
||||
Content = beatmap.BeatmapInfo.Length.ToFormattedDuration().ToString(),
|
||||
}),
|
||||
bpmLabelContainer = new Container
|
||||
{
|
||||
|
@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
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 BeatmapOptionsButton()
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
Width = width;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
|
@ -8,6 +8,7 @@ using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Users.Drawables
|
||||
{
|
||||
@ -71,6 +72,11 @@ namespace osu.Game.Users.Drawables
|
||||
{
|
||||
private LocalisableString tooltip = default_tooltip_text;
|
||||
|
||||
public ClickableArea()
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
}
|
||||
|
||||
public override LocalisableString TooltipText
|
||||
{
|
||||
get => Enabled.Value ? tooltip : default;
|
||||
|
@ -5,6 +5,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Users.Drawables
|
||||
@ -32,9 +33,17 @@ namespace osu.Game.Users.Drawables
|
||||
if (country == null && !ShowPlaceholderOnNull)
|
||||
return null;
|
||||
|
||||
return new DrawableFlag(country)
|
||||
return new Container
|
||||
{
|
||||
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 UserPanel(User user)
|
||||
: base(HoverSampleSet.Submit)
|
||||
{
|
||||
if (user == null)
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
|
@ -22,7 +22,7 @@
|
||||
<PackageReference Include="DiffPlex" Version="1.7.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.34" />
|
||||
<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.Protocols.MessagePack" Version="5.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="5.0.8" />
|
||||
@ -37,8 +37,8 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="10.3.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2021.728.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.722.0" />
|
||||
<PackageReference Include="Sentry" Version="3.8.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
|
||||
<PackageReference Include="Sentry" Version="3.8.3" />
|
||||
<PackageReference Include="SharpCompress" Version="0.28.3" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
|
@ -71,7 +71,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<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.803.0" />
|
||||
</ItemGroup>
|
||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
||||
<PropertyGroup>
|
||||
|
@ -117,7 +117,7 @@
|
||||
</ImageAsset>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.7.0" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||
</Project>
|
||||
|
Loading…
Reference in New Issue
Block a user