mirror of
https://github.com/ppy/osu.git
synced 2025-03-10 03:57:20 +08:00
Merge pull request #29027 from normalid-awa/feature/skin/legacy-input-overlay
Add legacy key counter support
This commit is contained in:
commit
b1488fd5b7
@ -6,6 +6,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||||
@ -28,11 +29,15 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
|
|
||||||
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
||||||
{
|
{
|
||||||
if (lookup is SkinComponentsContainerLookup containerLookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
switch (containerLookup.Target)
|
case SkinComponentsContainerLookup containerLookup:
|
||||||
|
if (containerLookup.Target != SkinComponentsContainerLookup.TargetArea.MainHUDComponents)
|
||||||
|
return base.GetDrawableComponent(lookup);
|
||||||
|
|
||||||
|
// Modifications for global components.
|
||||||
|
if (containerLookup.Ruleset == null)
|
||||||
{
|
{
|
||||||
case SkinComponentsContainerLookup.TargetArea.MainHUDComponents:
|
|
||||||
var components = base.GetDrawableComponent(lookup) as Container;
|
var components = base.GetDrawableComponent(lookup) as Container;
|
||||||
|
|
||||||
if (providesComboCounter && components != null)
|
if (providesComboCounter && components != null)
|
||||||
@ -45,10 +50,34 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
|
|
||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (lookup is CatchSkinComponentLookup catchSkinComponent)
|
// Skin has configuration.
|
||||||
|
if (base.GetDrawableComponent(lookup) is Drawable d)
|
||||||
|
return d;
|
||||||
|
|
||||||
|
// Our own ruleset components default.
|
||||||
|
return new DefaultSkinComponentsContainer(container =>
|
||||||
{
|
{
|
||||||
|
var keyCounter = container.OfType<LegacyKeyCounterDisplay>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (keyCounter != null)
|
||||||
|
{
|
||||||
|
// set the anchor to top right so that it won't squash to the return button to the top
|
||||||
|
keyCounter.Anchor = Anchor.CentreRight;
|
||||||
|
keyCounter.Origin = Anchor.CentreRight;
|
||||||
|
keyCounter.X = 0;
|
||||||
|
// 340px is the default height inherit from stable
|
||||||
|
keyCounter.Y = container.ToLocalSpace(new Vector2(0, container.ScreenSpaceDrawQuad.Centre.Y - 340f)).Y;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new LegacyKeyCounterDisplay(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
case CatchSkinComponentLookup catchSkinComponent:
|
||||||
switch (catchSkinComponent.Component)
|
switch (catchSkinComponent.Component)
|
||||||
{
|
{
|
||||||
case CatchSkinComponents.Fruit:
|
case CatchSkinComponents.Fruit:
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
@ -41,8 +42,46 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
|
|
||||||
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
||||||
{
|
{
|
||||||
if (lookup is OsuSkinComponentLookup osuComponent)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
|
case SkinComponentsContainerLookup containerLookup:
|
||||||
|
// Only handle per ruleset defaults here.
|
||||||
|
if (containerLookup.Ruleset == null)
|
||||||
|
return base.GetDrawableComponent(lookup);
|
||||||
|
|
||||||
|
// Skin has configuration.
|
||||||
|
if (base.GetDrawableComponent(lookup) is Drawable d)
|
||||||
|
return d;
|
||||||
|
|
||||||
|
// Our own ruleset components default.
|
||||||
|
switch (containerLookup.Target)
|
||||||
|
{
|
||||||
|
case SkinComponentsContainerLookup.TargetArea.MainHUDComponents:
|
||||||
|
return new DefaultSkinComponentsContainer(container =>
|
||||||
|
{
|
||||||
|
var keyCounter = container.OfType<LegacyKeyCounterDisplay>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (keyCounter != null)
|
||||||
|
{
|
||||||
|
// set the anchor to top right so that it won't squash to the return button to the top
|
||||||
|
keyCounter.Anchor = Anchor.CentreRight;
|
||||||
|
keyCounter.Origin = Anchor.CentreRight;
|
||||||
|
keyCounter.X = 0;
|
||||||
|
// 340px is the default height inherit from stable
|
||||||
|
keyCounter.Y = container.ToLocalSpace(new Vector2(0, container.ScreenSpaceDrawQuad.Centre.Y - 340f)).Y;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new LegacyKeyCounterDisplay(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
case OsuSkinComponentLookup osuComponent:
|
||||||
switch (osuComponent.Component)
|
switch (osuComponent.Component)
|
||||||
{
|
{
|
||||||
case OsuSkinComponents.FollowPoint:
|
case OsuSkinComponents.FollowPoint:
|
||||||
@ -171,10 +210,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
default:
|
default:
|
||||||
throw new UnsupportedSkinComponentException(lookup);
|
throw new UnsupportedSkinComponentException(lookup);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
default:
|
||||||
return base.GetDrawableComponent(lookup);
|
return base.GetDrawableComponent(lookup);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override IBindable<TValue>? GetConfig<TLookup, TValue>(TLookup lookup)
|
public override IBindable<TValue>? GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
{
|
{
|
||||||
|
BIN
osu.Game.Tests/Resources/Archives/modified-classic-20240724.osk
Normal file
BIN
osu.Game.Tests/Resources/Archives/modified-classic-20240724.osk
Normal file
Binary file not shown.
@ -65,7 +65,9 @@ namespace osu.Game.Tests.Skins
|
|||||||
// Covers default rank display
|
// Covers default rank display
|
||||||
"Archives/modified-default-20230809.osk",
|
"Archives/modified-default-20230809.osk",
|
||||||
// Covers legacy rank display
|
// Covers legacy rank display
|
||||||
"Archives/modified-classic-20230809.osk"
|
"Archives/modified-classic-20230809.osk",
|
||||||
|
// Covers legacy key counter
|
||||||
|
"Archives/modified-classic-20240724.osk"
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -9,7 +9,6 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Extensions.ObjectExtensions;
|
using osu.Framework.Extensions.ObjectExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
@ -45,7 +44,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
// best way to check without exposing.
|
// best way to check without exposing.
|
||||||
private Drawable hideTarget => hudOverlay.ChildrenOfType<SkinComponentsContainer>().First();
|
private Drawable hideTarget => hudOverlay.ChildrenOfType<SkinComponentsContainer>().First();
|
||||||
private Drawable keyCounterFlow => hudOverlay.ChildrenOfType<KeyCounterDisplay>().First().ChildrenOfType<FillFlowContainer<KeyCounter>>().Single();
|
private Drawable keyCounterContent => hudOverlay.ChildrenOfType<KeyCounterDisplay>().First().ChildrenOfType<Drawable>().Skip(1).First();
|
||||||
|
|
||||||
public TestSceneHUDOverlay()
|
public TestSceneHUDOverlay()
|
||||||
{
|
{
|
||||||
@ -79,7 +78,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddAssert("showhud is set", () => hudOverlay.ShowHud.Value);
|
AddAssert("showhud is set", () => hudOverlay.ShowHud.Value);
|
||||||
|
|
||||||
AddAssert("hidetarget is visible", () => hideTarget.Alpha, () => Is.GreaterThan(0));
|
AddAssert("hidetarget is visible", () => hideTarget.Alpha, () => Is.GreaterThan(0));
|
||||||
AddAssert("key counter flow is visible", () => keyCounterFlow.IsPresent);
|
AddAssert("key counter flow is visible", () => keyCounterContent.IsPresent);
|
||||||
AddAssert("pause button is visible", () => hudOverlay.HoldToQuit.IsPresent);
|
AddAssert("pause button is visible", () => hudOverlay.HoldToQuit.IsPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +103,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddAssert("pause button is still visible", () => hudOverlay.HoldToQuit.IsPresent);
|
AddAssert("pause button is still visible", () => hudOverlay.HoldToQuit.IsPresent);
|
||||||
|
|
||||||
// Key counter flow container should not be affected by this, only the key counter display will be hidden as checked above.
|
// Key counter flow container should not be affected by this, only the key counter display will be hidden as checked above.
|
||||||
AddAssert("key counter flow not affected", () => keyCounterFlow.IsPresent);
|
AddAssert("key counter flow not affected", () => keyCounterContent.IsPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -150,11 +149,11 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false);
|
AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false);
|
||||||
AddUntilStep("hidetarget is hidden", () => hideTarget.Alpha, () => Is.LessThanOrEqualTo(0));
|
AddUntilStep("hidetarget is hidden", () => hideTarget.Alpha, () => Is.LessThanOrEqualTo(0));
|
||||||
AddUntilStep("key counters hidden", () => !keyCounterFlow.IsPresent);
|
AddUntilStep("key counters hidden", () => !keyCounterContent.IsPresent);
|
||||||
|
|
||||||
AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true);
|
AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true);
|
||||||
AddUntilStep("hidetarget is visible", () => hideTarget.Alpha, () => Is.GreaterThan(0));
|
AddUntilStep("hidetarget is visible", () => hideTarget.Alpha, () => Is.GreaterThan(0));
|
||||||
AddUntilStep("key counters still hidden", () => !keyCounterFlow.IsPresent);
|
AddUntilStep("key counters still hidden", () => !keyCounterContent.IsPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Play.HUD;
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
@ -56,6 +57,11 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Scale = new Vector2(1, -1)
|
Scale = new Vector2(1, -1)
|
||||||
},
|
},
|
||||||
|
new LegacyKeyCounterDisplay
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
},
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
@ -89,6 +95,12 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Rotation = 90,
|
Rotation = 90,
|
||||||
},
|
},
|
||||||
|
new LegacyKeyCounterDisplay
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Rotation = 90,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,13 @@ using osu.Framework.Testing;
|
|||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Play.HUD;
|
using osu.Game.Screens.Play.HUD;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Tests.Gameplay;
|
using osu.Game.Tests.Gameplay;
|
||||||
using osuTK.Input;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
@ -91,10 +92,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
SetContents(_ =>
|
SetContents(_ =>
|
||||||
{
|
{
|
||||||
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
|
hudOverlay = new HUDOverlay(new DrawableOsuRuleset(new OsuRuleset(), new OsuBeatmap()), Array.Empty<Mod>());
|
||||||
|
|
||||||
// Add any key just to display the key counter visually.
|
|
||||||
hudOverlay.InputCountController.Add(new KeyCounterKeyboardTrigger(Key.Space));
|
|
||||||
|
|
||||||
action?.Invoke(hudOverlay);
|
action?.Invoke(hudOverlay);
|
||||||
|
|
||||||
|
@ -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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
|
{
|
||||||
|
public partial class TestSceneSkinnableKeyCounter : SkinnableHUDComponentTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private readonly InputCountController controller = new InputCountController();
|
||||||
|
|
||||||
|
public override void SetUpSteps()
|
||||||
|
{
|
||||||
|
AddStep("create dependencies", () =>
|
||||||
|
{
|
||||||
|
Add(controller);
|
||||||
|
controller.Add(new KeyCounterKeyboardTrigger(Key.Z));
|
||||||
|
controller.Add(new KeyCounterKeyboardTrigger(Key.X));
|
||||||
|
controller.Add(new KeyCounterKeyboardTrigger(Key.C));
|
||||||
|
controller.Add(new KeyCounterKeyboardTrigger(Key.V));
|
||||||
|
|
||||||
|
foreach (var trigger in controller.Triggers)
|
||||||
|
Add(trigger);
|
||||||
|
});
|
||||||
|
base.SetUpSteps();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
|
||||||
|
|
||||||
|
protected override Drawable CreateDefaultImplementation() => new ArgonKeyCounterDisplay();
|
||||||
|
|
||||||
|
protected override Drawable CreateLegacyImplementation() => new LegacyKeyCounterDisplay();
|
||||||
|
}
|
||||||
|
}
|
@ -93,14 +93,8 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void HandleColours<TModel>(TModel output, string line, bool allowAlpha)
|
private Color4 convertSettingStringToColor4(string[] split, bool allowAlpha, KeyValuePair<string, string> pair)
|
||||||
{
|
{
|
||||||
var pair = SplitKeyVal(line);
|
|
||||||
|
|
||||||
bool isCombo = pair.Key.StartsWith(@"Combo", StringComparison.Ordinal);
|
|
||||||
|
|
||||||
string[] split = pair.Value.Split(',');
|
|
||||||
|
|
||||||
if (split.Length != 3 && split.Length != 4)
|
if (split.Length != 3 && split.Length != 4)
|
||||||
throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B or R,G,B,A): {pair.Value}");
|
throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B or R,G,B,A): {pair.Value}");
|
||||||
|
|
||||||
@ -116,6 +110,18 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
|
throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void HandleColours<TModel>(TModel output, string line, bool allowAlpha)
|
||||||
|
{
|
||||||
|
var pair = SplitKeyVal(line);
|
||||||
|
|
||||||
|
string[] split = pair.Value.Split(',');
|
||||||
|
Color4 colour = convertSettingStringToColor4(split, allowAlpha, pair);
|
||||||
|
|
||||||
|
bool isCombo = pair.Key.StartsWith(@"Combo", StringComparison.Ordinal);
|
||||||
|
|
||||||
if (isCombo)
|
if (isCombo)
|
||||||
{
|
{
|
||||||
if (!(output is IHasComboColours tHasComboColours)) return;
|
if (!(output is IHasComboColours tHasComboColours)) return;
|
||||||
|
@ -14,11 +14,10 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public ArgonKeyCounterDisplay()
|
public ArgonKeyCounterDisplay()
|
||||||
{
|
{
|
||||||
InternalChild = KeyFlow = new FillFlowContainer<KeyCounter>
|
Child = KeyFlow = new FillFlowContainer<KeyCounter>
|
||||||
{
|
{
|
||||||
Direction = FillDirection.Horizontal,
|
Direction = FillDirection.Horizontal,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Alpha = 0,
|
|
||||||
Spacing = new Vector2(2),
|
Spacing = new Vector2(2),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,10 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
public DefaultKeyCounterDisplay()
|
public DefaultKeyCounterDisplay()
|
||||||
{
|
{
|
||||||
InternalChild = KeyFlow = new FillFlowContainer<KeyCounter>
|
Child = KeyFlow = new FillFlowContainer<KeyCounter>
|
||||||
{
|
{
|
||||||
Direction = FillDirection.Horizontal,
|
Direction = FillDirection.Horizontal,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Alpha = 0,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A flowing display of all gameplay keys. Individual keys can be added using <see cref="InputTrigger"/> implementations.
|
/// A flowing display of all gameplay keys. Individual keys can be added using <see cref="InputTrigger"/> implementations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract partial class KeyCounterDisplay : CompositeDrawable, ISerialisableDrawable
|
public abstract partial class KeyCounterDisplay : Container, ISerialisableDrawable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the key counter should be visible regardless of the configuration value.
|
/// Whether the key counter should be visible regardless of the configuration value.
|
||||||
@ -29,25 +29,22 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
private readonly IBindableList<InputTrigger> triggers = new BindableList<InputTrigger>();
|
private readonly IBindableList<InputTrigger> triggers = new BindableList<InputTrigger>();
|
||||||
|
|
||||||
|
protected override Container<Drawable> Content { get; } = new Container
|
||||||
|
{
|
||||||
|
Alpha = 0,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
};
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private InputCountController controller { get; set; } = null!;
|
private InputCountController controller { get; set; } = null!;
|
||||||
|
|
||||||
private const int duration = 100;
|
private const int duration = 100;
|
||||||
|
|
||||||
protected void UpdateVisibility()
|
protected KeyCounterDisplay()
|
||||||
{
|
{
|
||||||
bool visible = AlwaysVisible.Value || ConfigVisibility.Value;
|
AddInternal(Content);
|
||||||
|
|
||||||
// Isolate changing visibility of the key counters from fading this component.
|
|
||||||
KeyFlow.FadeTo(visible ? 1 : 0, duration);
|
|
||||||
|
|
||||||
// Ensure a valid size is immediately obtained even if partially off-screen
|
|
||||||
// See https://github.com/ppy/osu/issues/14793.
|
|
||||||
KeyFlow.AlwaysPresent = visible;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract KeyCounter CreateCounter(InputTrigger trigger);
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuConfigManager config, DrawableRuleset? drawableRuleset)
|
private void load(OsuConfigManager config, DrawableRuleset? drawableRuleset)
|
||||||
{
|
{
|
||||||
@ -70,6 +67,20 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
ConfigVisibility.BindValueChanged(_ => UpdateVisibility(), true);
|
ConfigVisibility.BindValueChanged(_ => UpdateVisibility(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void UpdateVisibility()
|
||||||
|
{
|
||||||
|
bool visible = AlwaysVisible.Value || ConfigVisibility.Value;
|
||||||
|
|
||||||
|
// Isolate changing visibility of the key counters from fading this component.
|
||||||
|
Content.FadeTo(visible ? 1 : 0, duration);
|
||||||
|
|
||||||
|
// Ensure a valid size is immediately obtained even if partially off-screen
|
||||||
|
// See https://github.com/ppy/osu/issues/14793.
|
||||||
|
Content.AlwaysPresent = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract KeyCounter CreateCounter(InputTrigger trigger);
|
||||||
|
|
||||||
private void triggersChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
private void triggersChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
KeyFlow.Clear();
|
KeyFlow.Clear();
|
||||||
|
@ -47,6 +47,9 @@ namespace osu.Game.Skinning
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieve a configuration value.
|
/// Retrieve a configuration value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Note that while this returns a bindable value, it is not actually updated.
|
||||||
|
/// Until the API is fixed, just use the received bindable's <see cref="IBindable{TValue}.Value"/> immediately.</remarks>
|
||||||
/// <param name="lookup">The requested configuration value.</param>
|
/// <param name="lookup">The requested configuration value.</param>
|
||||||
/// <returns>A matching value boxed in an <see cref="IBindable{TValue}"/>, or null if unavailable.</returns>
|
/// <returns>A matching value boxed in an <see cref="IBindable{TValue}"/>, or null if unavailable.</returns>
|
||||||
IBindable<TValue>? GetConfig<TLookup, TValue>(TLookup lookup)
|
IBindable<TValue>? GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
|
101
osu.Game/Skinning/LegacyKeyCounter.cs
Normal file
101
osu.Game/Skinning/LegacyKeyCounter.cs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// 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.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
|
||||||
|
namespace osu.Game.Skinning
|
||||||
|
{
|
||||||
|
public partial class LegacyKeyCounter : KeyCounter
|
||||||
|
{
|
||||||
|
private const float transition_duration = 160;
|
||||||
|
|
||||||
|
public Colour4 ActiveColour { get; set; }
|
||||||
|
|
||||||
|
private Colour4 textColour;
|
||||||
|
|
||||||
|
public Colour4 TextColour
|
||||||
|
{
|
||||||
|
get => textColour;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
textColour = value;
|
||||||
|
overlayKeyText.Colour = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Container keyContainer;
|
||||||
|
private readonly OsuSpriteText overlayKeyText;
|
||||||
|
private readonly Sprite keySprite;
|
||||||
|
|
||||||
|
public LegacyKeyCounter(InputTrigger trigger)
|
||||||
|
: base(trigger)
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Child = keyContainer = new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
keySprite = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
new UprightAspectMaintainingContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Child = overlayKeyText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Text = trigger.Name,
|
||||||
|
Colour = textColour,
|
||||||
|
Font = OsuFont.GetFont(weight: FontWeight.SemiBold),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// matches longest dimension of default skin asset
|
||||||
|
Height = Width = 46;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource source)
|
||||||
|
{
|
||||||
|
Texture? keyTexture = source.GetTexture(@"inputoverlay-key");
|
||||||
|
|
||||||
|
if (keyTexture != null)
|
||||||
|
keySprite.Texture = keyTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Activate(bool forwardPlayback = true)
|
||||||
|
{
|
||||||
|
base.Activate(forwardPlayback);
|
||||||
|
keyContainer.ScaleTo(0.75f, transition_duration, Easing.Out);
|
||||||
|
keySprite.Colour = ActiveColour;
|
||||||
|
overlayKeyText.Text = CountPresses.Value.ToString();
|
||||||
|
overlayKeyText.Font = overlayKeyText.Font.With(weight: FontWeight.SemiBold);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Deactivate(bool forwardPlayback = true)
|
||||||
|
{
|
||||||
|
base.Deactivate(forwardPlayback);
|
||||||
|
keyContainer.ScaleTo(1f, transition_duration, Easing.Out);
|
||||||
|
keySprite.Colour = Colour4.White;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
92
osu.Game/Skinning/LegacyKeyCounterDisplay.cs
Normal file
92
osu.Game/Skinning/LegacyKeyCounterDisplay.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// 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 osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Skinning
|
||||||
|
{
|
||||||
|
public partial class LegacyKeyCounterDisplay : KeyCounterDisplay
|
||||||
|
{
|
||||||
|
private static readonly Colour4 active_colour_top = Colour4.FromHex(@"#ffde00");
|
||||||
|
private static readonly Colour4 active_colour_bottom = Colour4.FromHex(@"#f8009e");
|
||||||
|
|
||||||
|
protected override FillFlowContainer<KeyCounter> KeyFlow { get; }
|
||||||
|
|
||||||
|
private readonly Sprite backgroundSprite;
|
||||||
|
|
||||||
|
public LegacyKeyCounterDisplay()
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
backgroundSprite = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
|
Scale = new Vector2(1.05f, 1),
|
||||||
|
Rotation = 90,
|
||||||
|
},
|
||||||
|
KeyFlow = new FillFlowContainer<KeyCounter>
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
X = -1.5f,
|
||||||
|
Y = 7,
|
||||||
|
Spacing = new Vector2(1.8f),
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private ISkinSource source { get; set; } = null!;
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
KeyTextColor = source.GetConfig<SkinCustomColourLookup, Color4>(new SkinCustomColourLookup(SkinConfiguration.LegacySetting.InputOverlayText))?.Value ?? Color4.Black;
|
||||||
|
|
||||||
|
Texture? backgroundTexture = source.GetTexture(@"inputoverlay-background");
|
||||||
|
|
||||||
|
if (backgroundTexture != null)
|
||||||
|
backgroundSprite.Texture = backgroundTexture;
|
||||||
|
|
||||||
|
for (int i = 0; i < KeyFlow.Count; ++i)
|
||||||
|
{
|
||||||
|
((LegacyKeyCounter)KeyFlow[i]).ActiveColour = i < 2 ? active_colour_top : active_colour_bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override KeyCounter CreateCounter(InputTrigger trigger) => new LegacyKeyCounter(trigger)
|
||||||
|
{
|
||||||
|
TextColour = keyTextColor,
|
||||||
|
};
|
||||||
|
|
||||||
|
private Colour4 keyTextColor = Colour4.White;
|
||||||
|
|
||||||
|
public Colour4 KeyTextColor
|
||||||
|
{
|
||||||
|
get => keyTextColor;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != keyTextColor)
|
||||||
|
{
|
||||||
|
keyTextColor = value;
|
||||||
|
foreach (var child in KeyFlow.Cast<LegacyKeyCounter>())
|
||||||
|
child.TextColour = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,6 @@ using osu.Game.Rulesets.Objects.Types;
|
|||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Screens.Play.HUD;
|
using osu.Game.Screens.Play.HUD;
|
||||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
@ -310,6 +309,9 @@ namespace osu.Game.Skinning
|
|||||||
case SkinConfiguration.LegacySetting.Version:
|
case SkinConfiguration.LegacySetting.Version:
|
||||||
return SkinUtils.As<TValue>(new Bindable<decimal>(Configuration.LegacyVersion ?? SkinConfiguration.LATEST_VERSION));
|
return SkinUtils.As<TValue>(new Bindable<decimal>(Configuration.LegacyVersion ?? SkinConfiguration.LATEST_VERSION));
|
||||||
|
|
||||||
|
case SkinConfiguration.LegacySetting.InputOverlayText:
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<Colour4>(Configuration.CustomColours.TryGetValue(@"InputOverlayText", out var colour) ? colour : Colour4.Black));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return genericLookup<SkinConfiguration.LegacySetting, TValue>(legacySetting);
|
return genericLookup<SkinConfiguration.LegacySetting, TValue>(legacySetting);
|
||||||
}
|
}
|
||||||
@ -381,22 +383,12 @@ namespace osu.Game.Skinning
|
|||||||
}
|
}
|
||||||
|
|
||||||
var hitError = container.OfType<HitErrorMeter>().FirstOrDefault();
|
var hitError = container.OfType<HitErrorMeter>().FirstOrDefault();
|
||||||
var keyCounter = container.OfType<DefaultKeyCounterDisplay>().FirstOrDefault();
|
|
||||||
|
|
||||||
if (hitError != null)
|
if (hitError != null)
|
||||||
{
|
{
|
||||||
hitError.Anchor = Anchor.BottomCentre;
|
hitError.Anchor = Anchor.BottomCentre;
|
||||||
hitError.Origin = Anchor.CentreLeft;
|
hitError.Origin = Anchor.CentreLeft;
|
||||||
hitError.Rotation = -90;
|
hitError.Rotation = -90;
|
||||||
|
|
||||||
if (keyCounter != null)
|
|
||||||
{
|
|
||||||
const float padding = 10;
|
|
||||||
|
|
||||||
keyCounter.Anchor = Anchor.BottomRight;
|
|
||||||
keyCounter.Origin = Anchor.BottomRight;
|
|
||||||
keyCounter.Position = new Vector2(-padding, -(padding + hitError.Width));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
@ -408,7 +400,6 @@ namespace osu.Game.Skinning
|
|||||||
new LegacySongProgress(),
|
new LegacySongProgress(),
|
||||||
new LegacyHealthDisplay(),
|
new LegacyHealthDisplay(),
|
||||||
new BarHitErrorMeter(),
|
new BarHitErrorMeter(),
|
||||||
new DefaultKeyCounterDisplay()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ namespace osu.Game.Skinning
|
|||||||
AnimationFramerate,
|
AnimationFramerate,
|
||||||
LayeredHitSounds,
|
LayeredHitSounds,
|
||||||
AllowSliderBallTint,
|
AllowSliderBallTint,
|
||||||
|
InputOverlayText,
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Color4> DefaultComboColours { get; } = new List<Color4>
|
public static List<Color4> DefaultComboColours { get; } = new List<Color4>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user