mirror of https://github.com/ppy/osu
196 lines
6.2 KiB
C#
196 lines
6.2 KiB
C#
// 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.Audio;
|
|
using osu.Framework.Audio.Sample;
|
|
using osu.Framework.Extensions.Color4Extensions;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Graphics.Effects;
|
|
using osu.Framework.Graphics.Shapes;
|
|
using osuTK.Graphics;
|
|
|
|
namespace osu.Game.Graphics.Containers
|
|
{
|
|
public partial class WaveContainer : VisibilityContainer
|
|
{
|
|
public const float APPEAR_DURATION = 800;
|
|
public const float DISAPPEAR_DURATION = 500;
|
|
public const float SHADOW_OPACITY = 0.2f;
|
|
|
|
private const Easing easing_show = Easing.OutSine;
|
|
private const Easing easing_hide = Easing.InSine;
|
|
|
|
private readonly Wave firstWave;
|
|
private readonly Wave secondWave;
|
|
private readonly Wave thirdWave;
|
|
private readonly Wave fourthWave;
|
|
|
|
private readonly Container<Wave> wavesContainer;
|
|
private readonly Container contentContainer;
|
|
|
|
protected override Container<Drawable> Content => contentContainer;
|
|
|
|
protected override bool StartHidden => true;
|
|
|
|
private Sample? samplePopIn;
|
|
private Sample? samplePopOut;
|
|
|
|
// required due to LoadAsyncComplete() in `VisibilityContainer` calling PopOut() during load - similar workaround to `OsuDropdownMenu`
|
|
private bool wasShown;
|
|
|
|
public Color4 FirstWaveColour
|
|
{
|
|
get => firstWave.Colour;
|
|
set => firstWave.Colour = value;
|
|
}
|
|
|
|
public Color4 SecondWaveColour
|
|
{
|
|
get => secondWave.Colour;
|
|
set => secondWave.Colour = value;
|
|
}
|
|
|
|
public Color4 ThirdWaveColour
|
|
{
|
|
get => thirdWave.Colour;
|
|
set => thirdWave.Colour = value;
|
|
}
|
|
|
|
public Color4 FourthWaveColour
|
|
{
|
|
get => fourthWave.Colour;
|
|
set => fourthWave.Colour = value;
|
|
}
|
|
|
|
[BackgroundDependencyLoader(true)]
|
|
private void load(AudioManager audio)
|
|
{
|
|
samplePopIn = audio.Samples.Get("UI/wave-pop-in");
|
|
samplePopOut = audio.Samples.Get("UI/overlay-big-pop-out");
|
|
}
|
|
|
|
public WaveContainer()
|
|
{
|
|
Masking = true;
|
|
|
|
AddInternal(wavesContainer = new Container<Wave>
|
|
{
|
|
RelativeSizeAxes = Axes.X,
|
|
Origin = Anchor.TopCentre,
|
|
Anchor = Anchor.TopCentre,
|
|
Masking = true,
|
|
Children = new[]
|
|
{
|
|
firstWave = new Wave
|
|
{
|
|
Rotation = 13,
|
|
FinalPosition = -930,
|
|
},
|
|
secondWave = new Wave
|
|
{
|
|
Origin = Anchor.TopRight,
|
|
Anchor = Anchor.TopRight,
|
|
Rotation = -7,
|
|
FinalPosition = -560,
|
|
},
|
|
thirdWave = new Wave
|
|
{
|
|
Rotation = 4,
|
|
FinalPosition = -390,
|
|
},
|
|
fourthWave = new Wave
|
|
{
|
|
Origin = Anchor.TopRight,
|
|
Anchor = Anchor.TopRight,
|
|
Rotation = -2,
|
|
FinalPosition = -220,
|
|
},
|
|
},
|
|
});
|
|
|
|
AddInternal(contentContainer = new Container
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
RelativePositionAxes = Axes.Both,
|
|
Anchor = Anchor.BottomCentre,
|
|
Origin = Anchor.BottomCentre,
|
|
});
|
|
}
|
|
|
|
protected override void PopIn()
|
|
{
|
|
foreach (var w in wavesContainer)
|
|
w.Show();
|
|
|
|
contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint);
|
|
samplePopIn?.Play();
|
|
wasShown = true;
|
|
}
|
|
|
|
protected override void PopOut()
|
|
{
|
|
foreach (var w in wavesContainer)
|
|
w.Hide();
|
|
|
|
contentContainer.MoveToY(2, DISAPPEAR_DURATION, Easing.In);
|
|
|
|
if (wasShown)
|
|
samplePopOut?.Play();
|
|
}
|
|
|
|
protected override void UpdateAfterChildren()
|
|
{
|
|
base.UpdateAfterChildren();
|
|
|
|
// This is done as an optimization, such that invisible parts of the waves
|
|
// are masked away, and thus do not consume fill rate.
|
|
// todo: revert https://github.com/ppy/osu/commit/aff9e3617da0c8fe252169fae287e39b44575b5e after FTB is fixed on iOS.
|
|
wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y * DrawHeight));
|
|
}
|
|
|
|
private partial class Wave : VisibilityContainer
|
|
{
|
|
public float FinalPosition;
|
|
|
|
protected override bool StartHidden => true;
|
|
|
|
public Wave()
|
|
{
|
|
RelativeSizeAxes = Axes.X;
|
|
Width = 1.5f;
|
|
Masking = true;
|
|
EdgeEffect = new EdgeEffectParameters
|
|
{
|
|
Type = EdgeEffectType.Shadow,
|
|
Colour = Color4.Black.Opacity(50),
|
|
Radius = 20f,
|
|
};
|
|
|
|
Child = new Box { RelativeSizeAxes = Axes.Both };
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
base.Update();
|
|
|
|
// We can not use RelativeSizeAxes for Height, because the height
|
|
// of our parent diminishes as the content moves up.
|
|
Height = Parent!.Parent!.DrawSize.Y * 1.5f;
|
|
}
|
|
|
|
protected override void PopIn() => Schedule(() => this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show));
|
|
|
|
protected override void PopOut()
|
|
{
|
|
double duration = IsLoaded ? DISAPPEAR_DURATION : 0;
|
|
|
|
// scheduling is required as parent may not be present at the time this is called.
|
|
Schedule(() => this.MoveToY(Parent!.Parent!.DrawSize.Y, duration, easing_hide));
|
|
}
|
|
}
|
|
}
|
|
}
|