1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-20 20:33:21 +08:00

Subclass osu logo instead of adding much code to it

This commit is contained in:
Dean Herbert 2024-12-20 14:46:34 +09:00
parent 8c7af79f96
commit e5dbf9ce45
No known key found for this signature in database
12 changed files with 148 additions and 93 deletions

View File

@ -7,6 +7,7 @@ using osu.Framework.Allocation;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Screens.Menu;
using osu.Game.Seasonal;
namespace osu.Game.Tests.Visual.Menus
{

View File

@ -4,6 +4,7 @@
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Screens.Menu;
using osu.Game.Seasonal;
using osuTK;
namespace osu.Game.Tests.Visual.UserInterface
@ -12,6 +13,19 @@ namespace osu.Game.Tests.Visual.UserInterface
{
private OsuLogo? logo;
private float scale = 1;
protected override void LoadComplete()
{
base.LoadComplete();
AddSliderStep("scale", 0.1, 2, 1, scale =>
{
if (logo != null)
Child.Scale = new Vector2(this.scale = (float)scale);
});
}
[Test]
public void TestBasic()
{
@ -21,13 +35,22 @@ namespace osu.Game.Tests.Visual.UserInterface
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(scale),
};
});
}
AddSliderStep("scale", 0.1, 2, 1, scale =>
[Test]
public void TestChristmas()
{
AddStep("Add logo", () =>
{
if (logo != null)
Child.Scale = new Vector2((float)scale);
Child = logo = new OsuLogoChristmas
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(scale),
};
});
}
}

View File

@ -69,6 +69,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Select;
using osu.Game.Seasonal;
using osu.Game.Skinning;
using osu.Game.Updater;
using osu.Game.Users;
@ -362,7 +363,10 @@ namespace osu.Game
{
SentryLogger.AttachUser(API.LocalUser);
dependencies.Cache(osuLogo = new OsuLogo { Alpha = 0 });
if (SeasonalUIConfig.ENABLED)
dependencies.CacheAs(osuLogo = new OsuLogoChristmas { Alpha = 0 });
else
dependencies.CacheAs(osuLogo = new OsuLogo { Alpha = 0 });
// bind config int to database RulesetInfo
configRuleset = LocalConfig.GetBindable<string>(OsuSetting.Ruleset);

View File

@ -15,6 +15,7 @@ using osu.Framework.Screens;
using osu.Framework.Threading;
using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Seasonal;
using IntroSequence = osu.Game.Configuration.IntroSequence;
namespace osu.Game.Screens
@ -37,7 +38,7 @@ namespace osu.Game.Screens
private IntroScreen getIntroSequence()
{
if (SeasonalUI.ENABLED)
if (SeasonalUIConfig.ENABLED)
return new IntroChristmas(createMainMenu);
if (introSequence == IntroSequence.Random)

View File

@ -15,6 +15,7 @@ using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Seasonal;
using osuTK;
using osuTK.Graphics;
@ -302,7 +303,7 @@ namespace osu.Game.Screens.Menu
float x = 0.5f + 0.5f * randomRadius * (float)Math.Cos(angle);
float y = 0.5f + 0.5f * randomRadius * (float)Math.Sin(angle);
Color4 christmasColour = RNG.NextBool() ? SeasonalUI.PRIMARY_COLOUR_1 : SeasonalUI.PRIMARY_COLOUR_2;
Color4 christmasColour = RNG.NextBool() ? SeasonalUIConfig.PRIMARY_COLOUR_1 : SeasonalUIConfig.PRIMARY_COLOUR_2;
Drawable triangle = new Triangle
{

View File

@ -35,6 +35,7 @@ using osu.Game.Screens.OnlinePlay.DailyChallenge;
using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Screens.Select;
using osu.Game.Seasonal;
using osuTK;
using osuTK.Graphics;
@ -124,7 +125,7 @@ namespace osu.Game.Screens.Menu
AddRangeInternal(new[]
{
SeasonalUI.ENABLED ? new MainMenuSeasonalLighting() : Empty(),
SeasonalUIConfig.ENABLED ? new MainMenuSeasonalLighting() : Empty(),
buttonsContainer = new ParallaxContainer
{
ParallaxAmount = 0.01f,
@ -168,7 +169,7 @@ namespace osu.Game.Screens.Menu
Margin = new MarginPadding { Right = 15, Top = 5 }
},
// For now, this is too much alongside the seasonal lighting.
SeasonalUI.ENABLED ? Empty() : new KiaiMenuFountains(),
SeasonalUIConfig.ENABLED ? Empty() : new KiaiMenuFountains(),
bottomElementsFlow = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,

View File

@ -7,6 +7,7 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Seasonal;
using osu.Game.Skinning;
using osuTK.Graphics;
@ -29,8 +30,8 @@ namespace osu.Game.Screens.Menu
private void updateColour()
{
if (SeasonalUI.ENABLED)
Colour = SeasonalUI.AMBIENT_COLOUR_1;
if (SeasonalUIConfig.ENABLED)
Colour = SeasonalUIConfig.AMBIENT_COLOUR_1;
else if (user.Value?.IsSupporter ?? false)
Colour = skin.Value.GetConfig<GlobalSkinColours, Color4>(GlobalSkinColours.MenuGlow)?.Value ?? Color4.White;
else

View File

@ -18,6 +18,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Seasonal;
using osu.Game.Skinning;
using osuTK.Graphics;
@ -68,7 +69,7 @@ namespace osu.Game.Screens.Menu
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Y,
Width = box_width * (SeasonalUI.ENABLED ? 4 : 2),
Width = box_width * (SeasonalUIConfig.ENABLED ? 4 : 2),
Height = 1.5f,
// align off-screen to make sure our edges don't become visible during parallax.
X = -box_width,
@ -80,7 +81,7 @@ namespace osu.Game.Screens.Menu
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Y,
Width = box_width * (SeasonalUI.ENABLED ? 4 : 2),
Width = box_width * (SeasonalUIConfig.ENABLED ? 4 : 2),
Height = 1.5f,
X = box_width,
Alpha = 0,
@ -105,7 +106,7 @@ namespace osu.Game.Screens.Menu
private void flash(Drawable d, double beatLength, bool kiai, ChannelAmplitudes amplitudes)
{
if (SeasonalUI.ENABLED)
if (SeasonalUIConfig.ENABLED)
updateColour();
d.FadeTo(Math.Clamp(0.1f + ((ReferenceEquals(d, leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier), 0.1f, 1),
@ -118,8 +119,8 @@ namespace osu.Game.Screens.Menu
{
Color4 baseColour = colours.Blue;
if (SeasonalUI.ENABLED)
baseColour = RNG.NextBool() ? SeasonalUI.PRIMARY_COLOUR_1 : SeasonalUI.PRIMARY_COLOUR_2;
if (SeasonalUIConfig.ENABLED)
baseColour = RNG.NextBool() ? SeasonalUIConfig.PRIMARY_COLOUR_1 : SeasonalUIConfig.PRIMARY_COLOUR_2;
else if (user.Value?.IsSupporter ?? false)
baseColour = skin.Value.GetConfig<GlobalSkinColours, Color4>(GlobalSkinColours.MenuGlow)?.Value ?? baseColour;

View File

@ -4,7 +4,6 @@
#nullable disable
using System;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
@ -54,8 +53,10 @@ namespace osu.Game.Screens.Menu
private Sample sampleClick;
private SampleChannel sampleClickChannel;
private Sample sampleBeat;
private Sample sampleDownbeat;
protected virtual double BeatSampleVariance => 0.1;
protected Sample SampleBeat;
protected Sample SampleDownbeat;
private readonly Container colourAndTriangles;
private readonly TrianglesV2 triangles;
@ -160,10 +161,10 @@ namespace osu.Game.Screens.Menu
Alpha = visualizer_default_alpha,
Size = SCALE_ADJUST
},
new Container
LogoElements = new Container
{
AutoSizeAxes = Axes.Both,
Children = new[]
Children = new Drawable[]
{
logoContainer = new CircularContainer
{
@ -212,15 +213,6 @@ namespace osu.Game.Screens.Menu
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
SeasonalUI.ENABLED
? hat = new Sprite
{
BypassAutoSizeAxes = Axes.Both,
Alpha = 0,
Origin = Anchor.BottomCentre,
Scale = new Vector2(-1, 1),
}
: Empty(),
}
},
impactContainer = new CircularContainer
@ -253,6 +245,8 @@ namespace osu.Game.Screens.Menu
};
}
public Container LogoElements { get; private set; }
/// <summary>
/// Schedule a new external animation. Handled queueing and finishing previous animations in a sane way.
/// </summary>
@ -282,20 +276,11 @@ namespace osu.Game.Screens.Menu
{
sampleClick = audio.Samples.Get(@"Menu/osu-logo-select");
if (SeasonalUI.ENABLED)
{
sampleDownbeat = sampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat-bell");
}
else
{
sampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat");
sampleDownbeat = audio.Samples.Get(@"Menu/osu-logo-downbeat");
}
SampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat");
SampleDownbeat = audio.Samples.Get(@"Menu/osu-logo-downbeat");
logo.Texture = textures.Get(@"Menu/logo");
ripple.Texture = textures.Get(@"Menu/logo");
if (hat != null)
hat.Texture = textures.Get(@"Menu/hat");
}
private int lastBeatIndex;
@ -318,15 +303,13 @@ namespace osu.Game.Screens.Menu
{
if (beatIndex % timingPoint.TimeSignature.Numerator == 0)
{
sampleDownbeat?.Play();
SampleDownbeat?.Play();
}
else
{
var channel = sampleBeat.GetChannel();
if (SeasonalUI.ENABLED)
channel.Frequency.Value = 0.99 + RNG.NextDouble(0.02);
else
channel.Frequency.Value = 0.95 + RNG.NextDouble(0.1);
var channel = SampleBeat.GetChannel();
channel.Frequency.Value = 1 - BeatSampleVariance / 2 + RNG.NextDouble(BeatSampleVariance);
channel.Play();
}
});
@ -381,9 +364,6 @@ namespace osu.Game.Screens.Menu
const float scale_adjust_cutoff = 0.4f;
if (SeasonalUI.ENABLED)
updateHat();
if (musicController.CurrentTrack.IsRunning)
{
float maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0;
@ -397,38 +377,6 @@ namespace osu.Game.Screens.Menu
}
}
private bool hasHat;
private void updateHat()
{
if (hat == null)
return;
bool shouldHat = DrawWidth * Scale.X < 400;
if (shouldHat != hasHat)
{
hasHat = shouldHat;
if (hasHat)
{
hat.Delay(400)
.Then()
.MoveTo(new Vector2(120, 160))
.RotateTo(0)
.RotateTo(-20, 500, Easing.OutQuint)
.FadeIn(250, Easing.OutQuint);
}
else
{
hat.Delay(100)
.Then()
.MoveToOffset(new Vector2(0, -5), 500, Easing.OutQuint)
.FadeOut(500, Easing.OutQuint);
}
}
}
public override bool HandlePositionalInput => base.HandlePositionalInput && Alpha > 0.2f;
protected override bool OnMouseDown(MouseDownEvent e)
@ -506,9 +454,6 @@ namespace osu.Game.Screens.Menu
private Container currentProxyTarget;
private Drawable proxy;
[CanBeNull]
private readonly Sprite hat;
public void StopSamplePlayback() => sampleClickChannel?.Stop();
public Drawable ProxyToContainer(Container c)

View File

@ -21,7 +21,7 @@ using osu.Game.Rulesets.Objects.Types;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.Menu
namespace osu.Game.Seasonal
{
public partial class MainMenuSeasonalLighting : CompositeDrawable
{
@ -121,7 +121,7 @@ namespace osu.Game.Screens.Menu
if (h.GetType().Name.Contains("Tick"))
{
light.Colour = SeasonalUI.AMBIENT_COLOUR_1;
light.Colour = SeasonalUIConfig.AMBIENT_COLOUR_1;
light.Scale = new Vector2(0.5f);
light
.FadeInFromZero(250)
@ -133,14 +133,14 @@ namespace osu.Game.Screens.Menu
else
{
// default are green
Color4 col = SeasonalUI.PRIMARY_COLOUR_2;
Color4 col = SeasonalUIConfig.PRIMARY_COLOUR_2;
// whistles are red
if (h.Samples.Any(s => s.Name == HitSampleInfo.HIT_WHISTLE))
col = SeasonalUI.PRIMARY_COLOUR_1;
col = SeasonalUIConfig.PRIMARY_COLOUR_1;
// clap is third ambient (yellow) colour
else if (h.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP))
col = SeasonalUI.AMBIENT_COLOUR_1;
col = SeasonalUIConfig.AMBIENT_COLOUR_1;
light.Colour = col;
@ -184,12 +184,12 @@ namespace osu.Game.Screens.Menu
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(12),
Colour = SeasonalUI.AMBIENT_COLOUR_1,
Colour = SeasonalUIConfig.AMBIENT_COLOUR_1,
Blending = BlendingParameters.Additive,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Glow,
Colour = SeasonalUI.AMBIENT_COLOUR_2,
Colour = SeasonalUIConfig.AMBIENT_COLOUR_2,
Radius = 80,
}
}

View File

@ -0,0 +1,74 @@
// 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.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Screens.Menu;
using osuTK;
namespace osu.Game.Seasonal
{
public partial class OsuLogoChristmas : OsuLogo
{
protected override double BeatSampleVariance => 0.02;
private Sprite? hat;
private bool hasHat;
[BackgroundDependencyLoader]
private void load(TextureStore textures, AudioManager audio)
{
LogoElements.Add(hat = new Sprite
{
BypassAutoSizeAxes = Axes.Both,
Alpha = 0,
Origin = Anchor.BottomCentre,
Scale = new Vector2(-1, 1),
Texture = textures.Get(@"Menu/hat"),
});
// override base samples with our preferred ones.
SampleDownbeat = SampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat-bell");
}
protected override void Update()
{
base.Update();
updateHat();
}
private void updateHat()
{
if (hat == null)
return;
bool shouldHat = DrawWidth * Scale.X < 400;
if (shouldHat != hasHat)
{
hasHat = shouldHat;
if (hasHat)
{
hat.Delay(400)
.Then()
.MoveTo(new Vector2(120, 160))
.RotateTo(0)
.RotateTo(-20, 500, Easing.OutQuint)
.FadeIn(250, Easing.OutQuint);
}
else
{
hat.Delay(100)
.Then()
.MoveToOffset(new Vector2(0, -5), 500, Easing.OutQuint)
.FadeOut(500, Easing.OutQuint);
}
}
}
}
}

View File

@ -4,9 +4,12 @@
using osu.Framework.Extensions.Color4Extensions;
using osuTK.Graphics;
namespace osu.Game.Screens
namespace osu.Game.Seasonal
{
public static class SeasonalUI
/// <summary>
/// General configuration setting for seasonal event adjustments to the game.
/// </summary>
public static class SeasonalUIConfig
{
public static readonly bool ENABLED = true;