osu/osu.Game/Screens/Menu/OsuLogo.cs

384 lines
17 KiB
C#
Raw Normal View History

2018-01-05 11:21:19 +00:00
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
2016-10-07 08:07:23 +00:00
using System;
2016-11-14 08:23:33 +00:00
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
2017-05-23 16:17:09 +00:00
using osu.Framework.Audio.Track;
2016-10-07 08:07:23 +00:00
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
2016-10-07 08:07:23 +00:00
using osu.Framework.Graphics.Sprites;
2016-11-14 08:23:33 +00:00
using osu.Framework.Graphics.Textures;
2016-10-07 08:07:23 +00:00
using osu.Framework.Input;
using osu.Framework.MathUtils;
2017-05-23 16:17:09 +00:00
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics;
2016-12-01 11:21:14 +00:00
using osu.Game.Graphics.Backgrounds;
2017-05-23 03:29:43 +00:00
using osu.Game.Graphics.Containers;
using OpenTK;
2016-12-01 11:21:14 +00:00
using OpenTK.Graphics;
2016-10-07 08:07:23 +00:00
2016-11-14 08:23:33 +00:00
namespace osu.Game.Screens.Menu
2016-10-07 08:07:23 +00:00
{
/// <summary>
/// osu! logo and its attachments (pulsing, visualiser etc.)
/// </summary>
2017-05-23 03:29:43 +00:00
public class OsuLogo : BeatSyncedContainer
2016-10-07 08:07:23 +00:00
{
2017-05-08 10:56:04 +00:00
public readonly Color4 OsuPink = OsuColour.FromHex(@"e967a1");
private const double transition_length = 300;
private readonly Sprite logo;
private readonly CircularContainer logoContainer;
private readonly Container logoBounceContainer;
2017-05-23 03:29:43 +00:00
private readonly Container logoBeatContainer;
2017-05-23 16:45:01 +00:00
private readonly Container logoAmplitudeContainer;
private readonly Container logoHoverContainer;
2017-06-19 00:33:50 +00:00
private readonly LogoVisualisation visualizer;
2016-10-07 08:07:23 +00:00
2017-11-03 08:54:35 +00:00
private readonly IntroSequence intro;
private SampleChannel sampleClick;
2017-06-19 14:37:00 +00:00
private SampleChannel sampleBeat;
private readonly Container colourAndTriangles;
2016-12-01 11:21:14 +00:00
2017-05-24 04:29:12 +00:00
private readonly Triangles triangles;
/// <summary>
/// Return value decides whether the logo should play its own sample for the click action.
/// </summary>
public Func<bool> Action;
2016-10-07 08:07:23 +00:00
public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X * 0.74f;
2016-10-07 08:07:23 +00:00
private readonly Sprite ripple;
2016-10-07 08:07:23 +00:00
private readonly Container rippleContainer;
2016-10-07 08:07:23 +00:00
2016-12-01 11:21:14 +00:00
public bool Triangles
{
set { colourAndTriangles.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); }
2016-12-01 11:21:14 +00:00
}
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => logoContainer.ReceiveMouseInputAt(screenSpacePos);
2016-10-07 08:07:23 +00:00
public bool Ripple
{
get { return rippleContainer.Alpha > 0; }
set { rippleContainer.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); }
2016-10-07 08:07:23 +00:00
}
private readonly Box flashLayer;
2016-10-07 08:07:23 +00:00
private readonly Container impactContainer;
private const float default_size = 480;
private const double early_activation = 60;
2017-05-23 03:29:43 +00:00
2016-10-07 08:07:23 +00:00
public OsuLogo()
{
// Required to make Schedule calls run in OsuScreen even when we are not visible.
AlwaysPresent = true;
EarlyActivationMilliseconds = early_activation;
2017-05-23 03:29:43 +00:00
Size = new Vector2(default_size);
2016-10-07 08:07:23 +00:00
Origin = Anchor.Centre;
2016-10-22 08:50:42 +00:00
AutoSizeAxes = Axes.Both;
2016-10-07 08:07:23 +00:00
Children = new Drawable[]
{
2017-11-03 08:54:35 +00:00
intro = new IntroSequence
{
RelativeSizeAxes = Axes.Both,
},
logoHoverContainer = new Container
2016-10-07 08:07:23 +00:00
{
2016-10-22 08:50:42 +00:00
AutoSizeAxes = Axes.Both,
2016-10-07 08:07:23 +00:00
Children = new Drawable[]
{
2017-05-23 03:29:43 +00:00
logoBounceContainer = new Container
2016-10-07 08:07:23 +00:00
{
2016-10-22 09:40:04 +00:00
AutoSizeAxes = Axes.Both,
2016-12-01 11:21:14 +00:00
Children = new Drawable[]
{
rippleContainer = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
ripple = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
2017-09-07 13:46:21 +00:00
Blending = BlendingMode.Additive,
Alpha = 0
}
}
},
2017-05-23 16:45:01 +00:00
logoAmplitudeContainer = new Container
2016-12-01 11:21:14 +00:00
{
AutoSizeAxes = Axes.Both,
2016-12-01 11:21:14 +00:00
Children = new Drawable[]
{
2017-05-23 16:45:01 +00:00
logoBeatContainer = new Container
2016-12-01 11:21:14 +00:00
{
2017-05-23 03:29:43 +00:00
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
2017-06-19 00:33:50 +00:00
visualizer = new LogoVisualisation
{
RelativeSizeAxes = Axes.Both,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Alpha = 0.5f,
Size = new Vector2(0.96f)
},
new Container
{
2017-05-23 16:45:01 +00:00
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
2017-05-23 16:45:01 +00:00
logoContainer = new CircularContainer
{
2017-05-23 03:29:43 +00:00
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
2017-05-23 16:45:01 +00:00
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.88f),
Masking = true,
2017-05-23 03:29:43 +00:00
Children = new Drawable[]
{
2017-05-23 16:45:01 +00:00
colourAndTriangles = new Container
2017-05-23 03:29:43 +00:00
{
RelativeSizeAxes = Axes.Both,
2017-05-23 16:45:01 +00:00
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuPink,
},
triangles = new Triangles
2017-05-23 16:45:01 +00:00
{
TriangleScale = 4,
ColourLight = OsuColour.FromHex(@"ff7db7"),
ColourDark = OsuColour.FromHex(@"de5b95"),
RelativeSizeAxes = Axes.Both,
},
}
2017-05-23 03:29:43 +00:00
},
2017-05-23 16:45:01 +00:00
flashLayer = new Box
2017-05-23 03:29:43 +00:00
{
RelativeSizeAxes = Axes.Both,
2017-09-07 13:46:21 +00:00
Blending = BlendingMode.Additive,
2017-05-23 16:45:01 +00:00
Colour = Color4.White,
Alpha = 0,
2017-05-23 03:29:43 +00:00
},
2017-05-23 16:45:01 +00:00
},
},
2017-05-23 16:45:01 +00:00
logo = new Sprite
{
2017-05-23 16:45:01 +00:00
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
2017-05-23 16:45:01 +00:00
}
},
2017-05-23 16:45:01 +00:00
impactContainer = new CircularContainer
{
2017-05-23 03:29:43 +00:00
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
2017-05-23 16:45:01 +00:00
Alpha = 0,
BorderColour = Color4.White,
RelativeSizeAxes = Axes.Both,
BorderThickness = 10,
Masking = true,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
AlwaysPresent = true,
Alpha = 0,
}
}
2017-05-23 03:29:43 +00:00
}
}
}
}
2016-10-07 08:07:23 +00:00
}
}
}
}
}
};
}
/// <summary>
/// Schedule a new extenral animation. Handled queueing and finishing previous animations in a sane way.
/// </summary>
/// <param name="action">The animation to be performed</param>
/// <param name="waitForPrevious">If true, the new animation is delayed until all previous transforms finish. If false, existing transformed are cleared.</param>
public void AppendAnimatingAction(Action action, bool waitForPrevious)
{
2018-01-15 18:42:17 +00:00
void runnableAction()
{
if (waitForPrevious)
this.DelayUntilTransformsFinished().Schedule(action);
else
{
ClearTransforms();
action();
}
2018-01-15 18:42:17 +00:00
}
if (IsLoaded)
runnableAction();
else
2018-01-15 20:27:00 +00:00
Schedule(runnableAction);
}
[BackgroundDependencyLoader]
2017-05-23 17:09:31 +00:00
private void load(TextureStore textures, AudioManager audio)
2016-10-07 08:07:23 +00:00
{
2017-11-25 14:11:18 +00:00
sampleClick = audio.Sample.Get(@"Menu/osu-logo-select");
sampleBeat = audio.Sample.Get(@"Menu/osu-logo-heartbeat");
logo.Texture = textures.Get(@"Menu/logo");
ripple.Texture = textures.Get(@"Menu/logo");
2016-11-01 14:24:14 +00:00
}
2017-05-23 16:45:01 +00:00
private int lastBeatIndex;
2017-05-23 16:17:09 +00:00
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
2017-05-23 03:29:43 +00:00
{
2017-05-23 16:17:09 +00:00
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
2017-05-23 03:29:43 +00:00
2017-05-23 16:45:01 +00:00
lastBeatIndex = beatIndex;
2017-05-23 16:17:09 +00:00
var beatLength = timingPoint.BeatLength;
2016-10-07 08:07:23 +00:00
2017-05-23 16:45:01 +00:00
float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum);
2017-05-23 16:17:09 +00:00
if (beatIndex < 0) return;
2017-07-07 05:59:17 +00:00
if (IsHovered)
this.Delay(early_activation).Schedule(() => sampleBeat.Play());
2017-07-16 15:28:20 +00:00
logoBeatContainer
2017-07-22 18:50:25 +00:00
.ScaleTo(1 - 0.02f * amplitudeAdjust, early_activation, Easing.Out)
2017-07-16 15:28:20 +00:00
.Then()
2017-07-22 18:50:25 +00:00
.ScaleTo(1, beatLength * 2, Easing.OutQuint);
ripple.ClearTransforms();
2017-07-16 15:28:20 +00:00
ripple
.ScaleTo(logoAmplitudeContainer.Scale)
2017-07-22 18:50:25 +00:00
.ScaleTo(logoAmplitudeContainer.Scale * (1 + 0.04f * amplitudeAdjust), beatLength, Easing.OutQuint)
.FadeTo(0.15f * amplitudeAdjust).FadeOut(beatLength, Easing.OutQuint);
2017-05-23 07:27:01 +00:00
2017-05-23 16:17:09 +00:00
if (effectPoint.KiaiMode && flashLayer.Alpha < 0.4f)
2017-05-23 07:27:01 +00:00
{
flashLayer.ClearTransforms();
2017-07-16 15:28:20 +00:00
flashLayer
2017-07-22 18:50:25 +00:00
.FadeTo(0.2f * amplitudeAdjust, early_activation, Easing.Out)
2017-07-16 15:28:20 +00:00
.Then()
.FadeOut(beatLength);
2017-05-23 07:27:01 +00:00
2017-07-16 15:28:20 +00:00
visualizer.ClearTransforms();
visualizer
2017-07-22 18:50:25 +00:00
.FadeTo(0.9f * amplitudeAdjust, early_activation, Easing.Out)
2017-07-16 15:28:20 +00:00
.Then()
.FadeTo(0.5f, beatLength);
2017-05-23 07:27:01 +00:00
}
2017-05-23 03:29:43 +00:00
}
2017-11-03 08:54:35 +00:00
public void PlayIntro()
{
2017-11-08 05:31:11 +00:00
const double length = 3150;
const double fade = 200;
2017-11-03 08:54:35 +00:00
logoHoverContainer.FadeOut().Delay(length).FadeIn(fade);
intro.Show();
intro.Start(length);
intro.Delay(length + fade).FadeOut();
}
2017-05-23 16:45:01 +00:00
protected override void Update()
{
base.Update();
2017-05-24 04:05:28 +00:00
const float scale_adjust_cutoff = 0.4f;
const float velocity_adjust_cutoff = 0.98f;
const float paused_velocity = 0.5f;
2017-05-24 04:05:28 +00:00
if (Beatmap.Value.Track.IsRunning)
{
var maxAmplitude = lastBeatIndex >= 0 ? Beatmap.Value.Track.CurrentAmplitudes.Maximum : 0;
logoAmplitudeContainer.ScaleTo(1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 75, Easing.OutQuint);
if (maxAmplitude > velocity_adjust_cutoff)
triangles.Velocity = 1 + Math.Max(0, maxAmplitude - velocity_adjust_cutoff) * 50;
else
triangles.Velocity = (float)Interpolation.Damp(triangles.Velocity, 1, 0.995f, Time.Elapsed);
}
else
{
triangles.Velocity = paused_velocity;
}
2017-05-23 16:45:01 +00:00
}
public override bool HandleMouseInput => base.HandleMouseInput && Action != null && Alpha > 0.2f;
2016-10-07 08:07:23 +00:00
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
2017-07-22 18:50:25 +00:00
logoBounceContainer.ScaleTo(0.9f, 1000, Easing.Out);
2016-10-07 08:07:23 +00:00
return true;
}
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
{
2017-07-22 18:50:25 +00:00
logoBounceContainer.ScaleTo(1f, 500, Easing.OutElastic);
2016-10-07 08:07:23 +00:00
return true;
}
protected override bool OnClick(InputState state)
{
if (Action?.Invoke() ?? true)
sampleClick.Play();
2017-02-25 12:12:39 +00:00
flashLayer.ClearTransforms();
flashLayer.Alpha = 0.4f;
2017-07-22 18:50:25 +00:00
flashLayer.FadeOut(1500, Easing.OutExpo);
2016-10-07 08:07:23 +00:00
return true;
}
protected override bool OnHover(InputState state)
{
2017-07-22 18:50:25 +00:00
logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic);
2016-10-07 08:07:23 +00:00
return true;
}
protected override void OnHoverLost(InputState state)
{
2017-07-22 18:50:25 +00:00
logoHoverContainer.ScaleTo(1, 500, Easing.OutElastic);
2016-10-07 08:07:23 +00:00
}
public void Impact()
{
2017-07-22 18:50:25 +00:00
impactContainer.FadeOutFromOne(250, Easing.In);
impactContainer.ScaleTo(0.96f);
impactContainer.ScaleTo(1.12f, 250);
}
2016-10-07 08:07:23 +00:00
}
2017-05-23 17:53:21 +00:00
}