mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 07:06:35 +09:00
Normalize all the line endings
This commit is contained in:
@ -1,287 +1,287 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
/// <summary>
|
||||
/// Button designed specifically for the osu!next main menu.
|
||||
/// In order to correctly flow, we have to use a negative margin on the parent container (due to the parallelogram shape).
|
||||
/// </summary>
|
||||
public class Button : BeatSyncedContainer, IStateful<ButtonState>
|
||||
{
|
||||
public event Action<ButtonState> StateChanged;
|
||||
|
||||
private readonly Container iconText;
|
||||
private readonly Container box;
|
||||
private readonly Box boxHoverLayer;
|
||||
private readonly SpriteIcon icon;
|
||||
private readonly string sampleName;
|
||||
private readonly Action clickAction;
|
||||
private readonly Key triggerKey;
|
||||
private SampleChannel sampleClick;
|
||||
private SampleChannel sampleHover;
|
||||
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => box.ReceiveMouseInputAt(screenSpacePos);
|
||||
|
||||
public Button(string text, string sampleName, FontAwesome symbol, Color4 colour, Action clickAction = null, float extraWidth = 0, Key triggerKey = Key.Unknown)
|
||||
{
|
||||
this.sampleName = sampleName;
|
||||
this.clickAction = clickAction;
|
||||
this.triggerKey = triggerKey;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Alpha = 0;
|
||||
|
||||
Vector2 boxSize = new Vector2(ButtonSystem.BUTTON_WIDTH + Math.Abs(extraWidth), ButtonSystem.BUTTON_AREA_HEIGHT);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
box = new Container
|
||||
{
|
||||
Masking = true,
|
||||
MaskingSmoothness = 2,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.Black.Opacity(0.2f),
|
||||
Roundness = 5,
|
||||
Radius = 8,
|
||||
},
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Scale = new Vector2(0, 1),
|
||||
Size = boxSize,
|
||||
Shear = new Vector2(ButtonSystem.WEDGE_WIDTH / boxSize.Y, 0),
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colour,
|
||||
},
|
||||
boxHoverLayer = new Box
|
||||
{
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
iconText = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Position = new Vector2(extraWidth / 2, 0),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
icon = new SpriteIcon
|
||||
{
|
||||
Shadow = true,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(30),
|
||||
Position = new Vector2(0, 0),
|
||||
Icon = symbol
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Shadow = true,
|
||||
AllowMultiline = false,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
TextSize = 16,
|
||||
Position = new Vector2(0, 35),
|
||||
Text = text
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private bool rightward;
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||
|
||||
if (!IsHovered) return;
|
||||
|
||||
double duration = timingPoint.BeatLength / 2;
|
||||
|
||||
icon.RotateTo(rightward ? 10 : -10, duration * 2, Easing.InOutSine);
|
||||
|
||||
icon.Animate(
|
||||
i => i.MoveToY(-10, duration, Easing.Out),
|
||||
i => i.ScaleTo(1, duration, Easing.Out)
|
||||
).Then(
|
||||
i => i.MoveToY(0, duration, Easing.In),
|
||||
i => i.ScaleTo(new Vector2(1, 0.9f), duration, Easing.In)
|
||||
);
|
||||
|
||||
rightward = !rightward;
|
||||
}
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
if (State != ButtonState.Expanded) return true;
|
||||
|
||||
sampleHover?.Play();
|
||||
|
||||
box.ScaleTo(new Vector2(1.5f, 1), 500, Easing.OutElastic);
|
||||
|
||||
double duration = TimeUntilNextBeat;
|
||||
|
||||
icon.ClearTransforms();
|
||||
icon.RotateTo(rightward ? -10 : 10, duration, Easing.InOutSine);
|
||||
icon.ScaleTo(new Vector2(1, 0.9f), duration, Easing.Out);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
icon.ClearTransforms();
|
||||
icon.RotateTo(0, 500, Easing.Out);
|
||||
icon.MoveTo(Vector2.Zero, 500, Easing.Out);
|
||||
icon.ScaleTo(Vector2.One, 200, Easing.Out);
|
||||
|
||||
if (State == ButtonState.Expanded)
|
||||
box.ScaleTo(new Vector2(1, 1), 500, Easing.OutElastic);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = audio.Sample.Get(@"Menu/button-hover");
|
||||
if (!string.IsNullOrEmpty(sampleName))
|
||||
sampleClick = audio.Sample.Get($@"Menu/{sampleName}");
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
{
|
||||
boxHoverLayer.FadeTo(0.1f, 1000, Easing.OutQuint);
|
||||
return base.OnMouseDown(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||
{
|
||||
boxHoverLayer.FadeTo(0, 1000, Easing.OutQuint);
|
||||
return base.OnMouseUp(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
trigger();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Repeat || state.Keyboard.ControlPressed || state.Keyboard.ShiftPressed || state.Keyboard.AltPressed)
|
||||
return false;
|
||||
|
||||
if (triggerKey == args.Key && triggerKey != Key.Unknown)
|
||||
{
|
||||
trigger();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void trigger()
|
||||
{
|
||||
sampleClick?.Play();
|
||||
|
||||
clickAction?.Invoke();
|
||||
|
||||
boxHoverLayer.ClearTransforms();
|
||||
boxHoverLayer.Alpha = 0.9f;
|
||||
boxHoverLayer.FadeOut(800, Easing.OutExpo);
|
||||
}
|
||||
|
||||
public override bool HandleKeyboardInput => state != ButtonState.Exploded;
|
||||
public override bool HandleMouseInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1);
|
||||
base.Update();
|
||||
}
|
||||
|
||||
public int ContractStyle;
|
||||
|
||||
private ButtonState state;
|
||||
|
||||
public ButtonState State
|
||||
{
|
||||
get { return state; }
|
||||
|
||||
set
|
||||
{
|
||||
if (state == value)
|
||||
return;
|
||||
|
||||
state = value;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ButtonState.Contracted:
|
||||
switch (ContractStyle)
|
||||
{
|
||||
default:
|
||||
box.ScaleTo(new Vector2(0, 1), 500, Easing.OutExpo);
|
||||
this.FadeOut(500);
|
||||
break;
|
||||
case 1:
|
||||
box.ScaleTo(new Vector2(0, 1), 400, Easing.InSine);
|
||||
this.FadeOut(800);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ButtonState.Expanded:
|
||||
const int expand_duration = 500;
|
||||
box.ScaleTo(new Vector2(1, 1), expand_duration, Easing.OutExpo);
|
||||
this.FadeIn(expand_duration / 6f);
|
||||
break;
|
||||
case ButtonState.Exploded:
|
||||
const int explode_duration = 200;
|
||||
box.ScaleTo(new Vector2(2, 1), explode_duration, Easing.OutExpo);
|
||||
this.FadeOut(explode_duration / 4f * 3);
|
||||
break;
|
||||
}
|
||||
|
||||
StateChanged?.Invoke(State);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ButtonState
|
||||
{
|
||||
Contracted,
|
||||
Expanded,
|
||||
Exploded
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
/// <summary>
|
||||
/// Button designed specifically for the osu!next main menu.
|
||||
/// In order to correctly flow, we have to use a negative margin on the parent container (due to the parallelogram shape).
|
||||
/// </summary>
|
||||
public class Button : BeatSyncedContainer, IStateful<ButtonState>
|
||||
{
|
||||
public event Action<ButtonState> StateChanged;
|
||||
|
||||
private readonly Container iconText;
|
||||
private readonly Container box;
|
||||
private readonly Box boxHoverLayer;
|
||||
private readonly SpriteIcon icon;
|
||||
private readonly string sampleName;
|
||||
private readonly Action clickAction;
|
||||
private readonly Key triggerKey;
|
||||
private SampleChannel sampleClick;
|
||||
private SampleChannel sampleHover;
|
||||
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => box.ReceiveMouseInputAt(screenSpacePos);
|
||||
|
||||
public Button(string text, string sampleName, FontAwesome symbol, Color4 colour, Action clickAction = null, float extraWidth = 0, Key triggerKey = Key.Unknown)
|
||||
{
|
||||
this.sampleName = sampleName;
|
||||
this.clickAction = clickAction;
|
||||
this.triggerKey = triggerKey;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Alpha = 0;
|
||||
|
||||
Vector2 boxSize = new Vector2(ButtonSystem.BUTTON_WIDTH + Math.Abs(extraWidth), ButtonSystem.BUTTON_AREA_HEIGHT);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
box = new Container
|
||||
{
|
||||
Masking = true,
|
||||
MaskingSmoothness = 2,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.Black.Opacity(0.2f),
|
||||
Roundness = 5,
|
||||
Radius = 8,
|
||||
},
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Scale = new Vector2(0, 1),
|
||||
Size = boxSize,
|
||||
Shear = new Vector2(ButtonSystem.WEDGE_WIDTH / boxSize.Y, 0),
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colour,
|
||||
},
|
||||
boxHoverLayer = new Box
|
||||
{
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
iconText = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Position = new Vector2(extraWidth / 2, 0),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
icon = new SpriteIcon
|
||||
{
|
||||
Shadow = true,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(30),
|
||||
Position = new Vector2(0, 0),
|
||||
Icon = symbol
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Shadow = true,
|
||||
AllowMultiline = false,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
TextSize = 16,
|
||||
Position = new Vector2(0, 35),
|
||||
Text = text
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private bool rightward;
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||
|
||||
if (!IsHovered) return;
|
||||
|
||||
double duration = timingPoint.BeatLength / 2;
|
||||
|
||||
icon.RotateTo(rightward ? 10 : -10, duration * 2, Easing.InOutSine);
|
||||
|
||||
icon.Animate(
|
||||
i => i.MoveToY(-10, duration, Easing.Out),
|
||||
i => i.ScaleTo(1, duration, Easing.Out)
|
||||
).Then(
|
||||
i => i.MoveToY(0, duration, Easing.In),
|
||||
i => i.ScaleTo(new Vector2(1, 0.9f), duration, Easing.In)
|
||||
);
|
||||
|
||||
rightward = !rightward;
|
||||
}
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
if (State != ButtonState.Expanded) return true;
|
||||
|
||||
sampleHover?.Play();
|
||||
|
||||
box.ScaleTo(new Vector2(1.5f, 1), 500, Easing.OutElastic);
|
||||
|
||||
double duration = TimeUntilNextBeat;
|
||||
|
||||
icon.ClearTransforms();
|
||||
icon.RotateTo(rightward ? -10 : 10, duration, Easing.InOutSine);
|
||||
icon.ScaleTo(new Vector2(1, 0.9f), duration, Easing.Out);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
icon.ClearTransforms();
|
||||
icon.RotateTo(0, 500, Easing.Out);
|
||||
icon.MoveTo(Vector2.Zero, 500, Easing.Out);
|
||||
icon.ScaleTo(Vector2.One, 200, Easing.Out);
|
||||
|
||||
if (State == ButtonState.Expanded)
|
||||
box.ScaleTo(new Vector2(1, 1), 500, Easing.OutElastic);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = audio.Sample.Get(@"Menu/button-hover");
|
||||
if (!string.IsNullOrEmpty(sampleName))
|
||||
sampleClick = audio.Sample.Get($@"Menu/{sampleName}");
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
{
|
||||
boxHoverLayer.FadeTo(0.1f, 1000, Easing.OutQuint);
|
||||
return base.OnMouseDown(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||
{
|
||||
boxHoverLayer.FadeTo(0, 1000, Easing.OutQuint);
|
||||
return base.OnMouseUp(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
trigger();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Repeat || state.Keyboard.ControlPressed || state.Keyboard.ShiftPressed || state.Keyboard.AltPressed)
|
||||
return false;
|
||||
|
||||
if (triggerKey == args.Key && triggerKey != Key.Unknown)
|
||||
{
|
||||
trigger();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void trigger()
|
||||
{
|
||||
sampleClick?.Play();
|
||||
|
||||
clickAction?.Invoke();
|
||||
|
||||
boxHoverLayer.ClearTransforms();
|
||||
boxHoverLayer.Alpha = 0.9f;
|
||||
boxHoverLayer.FadeOut(800, Easing.OutExpo);
|
||||
}
|
||||
|
||||
public override bool HandleKeyboardInput => state != ButtonState.Exploded;
|
||||
public override bool HandleMouseInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1);
|
||||
base.Update();
|
||||
}
|
||||
|
||||
public int ContractStyle;
|
||||
|
||||
private ButtonState state;
|
||||
|
||||
public ButtonState State
|
||||
{
|
||||
get { return state; }
|
||||
|
||||
set
|
||||
{
|
||||
if (state == value)
|
||||
return;
|
||||
|
||||
state = value;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ButtonState.Contracted:
|
||||
switch (ContractStyle)
|
||||
{
|
||||
default:
|
||||
box.ScaleTo(new Vector2(0, 1), 500, Easing.OutExpo);
|
||||
this.FadeOut(500);
|
||||
break;
|
||||
case 1:
|
||||
box.ScaleTo(new Vector2(0, 1), 400, Easing.InSine);
|
||||
this.FadeOut(800);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ButtonState.Expanded:
|
||||
const int expand_duration = 500;
|
||||
box.ScaleTo(new Vector2(1, 1), expand_duration, Easing.OutExpo);
|
||||
this.FadeIn(expand_duration / 6f);
|
||||
break;
|
||||
case ButtonState.Exploded:
|
||||
const int explode_duration = 200;
|
||||
box.ScaleTo(new Vector2(2, 1), explode_duration, Easing.OutExpo);
|
||||
this.FadeOut(explode_duration / 4f * 3);
|
||||
break;
|
||||
}
|
||||
|
||||
StateChanged?.Invoke(State);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ButtonState
|
||||
{
|
||||
Contracted,
|
||||
Expanded,
|
||||
Exploded
|
||||
}
|
||||
}
|
||||
|
@ -1,376 +1,376 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Threading;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class ButtonSystem : Container, IStateful<MenuState>
|
||||
{
|
||||
public event Action<MenuState> StateChanged;
|
||||
|
||||
private readonly BindableBool showOverlays = new BindableBool();
|
||||
|
||||
public Action OnEdit;
|
||||
public Action OnExit;
|
||||
public Action OnDirect;
|
||||
public Action OnSolo;
|
||||
public Action OnSettings;
|
||||
public Action OnMulti;
|
||||
public Action OnChart;
|
||||
public Action OnTest;
|
||||
|
||||
private readonly FlowContainerWithOrigin buttonFlow;
|
||||
|
||||
//todo: make these non-internal somehow.
|
||||
public const float BUTTON_AREA_HEIGHT = 100;
|
||||
|
||||
public const float BUTTON_WIDTH = 140f;
|
||||
public const float WEDGE_WIDTH = 20;
|
||||
|
||||
private OsuLogo logo;
|
||||
|
||||
public void SetOsuLogo(OsuLogo logo)
|
||||
{
|
||||
this.logo = logo;
|
||||
|
||||
if (this.logo != null)
|
||||
{
|
||||
this.logo.Action = onOsuLogo;
|
||||
|
||||
// osuLogo.SizeForFlow relies on loading to be complete.
|
||||
buttonFlow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0);
|
||||
|
||||
updateLogoState();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Drawable iconFacade;
|
||||
private readonly Container buttonArea;
|
||||
private readonly Box buttonAreaBackground;
|
||||
|
||||
private readonly Button backButton;
|
||||
private readonly Button settingsButton;
|
||||
|
||||
private readonly List<Button> buttonsTopLevel = new List<Button>();
|
||||
private readonly List<Button> buttonsPlay = new List<Button>();
|
||||
|
||||
private SampleChannel sampleBack;
|
||||
|
||||
public ButtonSystem()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
buttonArea = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Size = new Vector2(1, BUTTON_AREA_HEIGHT),
|
||||
Alpha = 0,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
buttonAreaBackground = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(2, 1),
|
||||
Colour = OsuColour.Gray(50),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
buttonFlow = new FlowContainerWithOrigin
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(-WEDGE_WIDTH, 0),
|
||||
Anchor = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
settingsButton = new Button(@"settings", string.Empty, FontAwesome.fa_gear, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O),
|
||||
backButton = new Button(@"back", string.Empty, FontAwesome.fa_osu_left_o, new Color4(51, 58, 94, 255), onBack, -WEDGE_WIDTH),
|
||||
iconFacade = new Container //need a container to make the osu! icon flow properly.
|
||||
{
|
||||
Size = new Vector2(0, BUTTON_AREA_HEIGHT)
|
||||
}
|
||||
},
|
||||
CentreTarget = iconFacade
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
buttonsPlay.Add(new Button(@"solo", @"button-solo-select", FontAwesome.fa_user, new Color4(102, 68, 204, 255), () => OnSolo?.Invoke(), WEDGE_WIDTH, Key.P));
|
||||
buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), () => OnMulti?.Invoke(), 0, Key.M));
|
||||
buttonsPlay.Add(new Button(@"chart", @"button-generic-select", FontAwesome.fa_osu_charts, new Color4(80, 53, 160, 255), () => OnChart?.Invoke()));
|
||||
|
||||
buttonsTopLevel.Add(new Button(@"play", @"button-play-select", FontAwesome.fa_osu_logo, new Color4(102, 68, 204, 255), onPlay, WEDGE_WIDTH, Key.P));
|
||||
buttonsTopLevel.Add(new Button(@"osu!editor", @"button-generic-select", FontAwesome.fa_osu_edit_o, new Color4(238, 170, 0, 255), () => OnEdit?.Invoke(), 0, Key.E));
|
||||
buttonsTopLevel.Add(new Button(@"osu!direct", @"button-direct-select", FontAwesome.fa_osu_chevron_down_o, new Color4(165, 204, 0, 255), () => OnDirect?.Invoke(), 0, Key.D));
|
||||
buttonsTopLevel.Add(new Button(@"exit", string.Empty, FontAwesome.fa_osu_cross_o, new Color4(238, 51, 153, 255), onExit, 0, Key.Q));
|
||||
|
||||
buttonFlow.AddRange(buttonsPlay);
|
||||
buttonFlow.AddRange(buttonsTopLevel);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(AudioManager audio, OsuGame game)
|
||||
{
|
||||
if (game != null) showOverlays.BindTo(game.ShowOverlays);
|
||||
sampleBack = audio.Sample.Get(@"Menu/button-back-select");
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Repeat) return false;
|
||||
|
||||
switch (args.Key)
|
||||
{
|
||||
case Key.Space:
|
||||
logo?.TriggerOnClick(state);
|
||||
return true;
|
||||
case Key.Escape:
|
||||
switch (State)
|
||||
{
|
||||
case MenuState.TopLevel:
|
||||
State = MenuState.Initial;
|
||||
return true;
|
||||
case MenuState.Play:
|
||||
backButton.TriggerOnClick();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void onPlay()
|
||||
{
|
||||
State = MenuState.Play;
|
||||
}
|
||||
|
||||
private void onExit()
|
||||
{
|
||||
OnExit?.Invoke();
|
||||
}
|
||||
|
||||
private void onBack()
|
||||
{
|
||||
sampleBack?.Play();
|
||||
State = MenuState.TopLevel;
|
||||
}
|
||||
|
||||
private bool onOsuLogo()
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
default:
|
||||
return true;
|
||||
case MenuState.Initial:
|
||||
State = MenuState.TopLevel;
|
||||
return true;
|
||||
case MenuState.TopLevel:
|
||||
buttonsTopLevel.First().TriggerOnClick();
|
||||
return false;
|
||||
case MenuState.Play:
|
||||
buttonsPlay.First().TriggerOnClick();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private MenuState state;
|
||||
|
||||
public override bool HandleKeyboardInput => state != MenuState.Exit;
|
||||
public override bool HandleMouseInput => state != MenuState.Exit;
|
||||
|
||||
public MenuState State
|
||||
{
|
||||
get { return state; }
|
||||
|
||||
set
|
||||
{
|
||||
if (state == value) return;
|
||||
|
||||
MenuState lastState = state;
|
||||
state = value;
|
||||
|
||||
//todo: figure a more elegant way of doing this.
|
||||
buttonsTopLevel.ForEach(b => b.ContractStyle = 0);
|
||||
buttonsPlay.ForEach(b => b.ContractStyle = 0);
|
||||
backButton.ContractStyle = 0;
|
||||
settingsButton.ContractStyle = 0;
|
||||
|
||||
if (state == MenuState.TopLevel)
|
||||
buttonArea.FinishTransforms(true);
|
||||
|
||||
updateLogoState(lastState);
|
||||
|
||||
using (buttonArea.BeginDelayedSequence(lastState == MenuState.Initial ? 150 : 0, true))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case MenuState.Exit:
|
||||
case MenuState.Initial:
|
||||
buttonAreaBackground.ScaleTo(Vector2.One, 500, Easing.Out);
|
||||
buttonArea.FadeOut(300);
|
||||
|
||||
foreach (Button b in buttonsTopLevel)
|
||||
b.State = ButtonState.Contracted;
|
||||
|
||||
foreach (Button b in buttonsPlay)
|
||||
b.State = ButtonState.Contracted;
|
||||
|
||||
if (state != MenuState.Exit && lastState == MenuState.TopLevel)
|
||||
sampleBack?.Play();
|
||||
break;
|
||||
case MenuState.TopLevel:
|
||||
buttonAreaBackground.ScaleTo(Vector2.One, 200, Easing.Out);
|
||||
|
||||
buttonArea.FadeIn(300);
|
||||
|
||||
foreach (Button b in buttonsTopLevel)
|
||||
b.State = ButtonState.Expanded;
|
||||
|
||||
foreach (Button b in buttonsPlay)
|
||||
b.State = ButtonState.Contracted;
|
||||
break;
|
||||
case MenuState.Play:
|
||||
foreach (Button b in buttonsTopLevel)
|
||||
b.State = ButtonState.Exploded;
|
||||
|
||||
foreach (Button b in buttonsPlay)
|
||||
b.State = ButtonState.Expanded;
|
||||
break;
|
||||
case MenuState.EnteringMode:
|
||||
buttonAreaBackground.ScaleTo(new Vector2(2, 0), 300, Easing.InSine);
|
||||
|
||||
buttonsTopLevel.ForEach(b => b.ContractStyle = 1);
|
||||
buttonsPlay.ForEach(b => b.ContractStyle = 1);
|
||||
backButton.ContractStyle = 1;
|
||||
settingsButton.ContractStyle = 1;
|
||||
|
||||
foreach (Button b in buttonsTopLevel)
|
||||
b.State = ButtonState.Contracted;
|
||||
|
||||
foreach (Button b in buttonsPlay)
|
||||
b.State = ButtonState.Contracted;
|
||||
break;
|
||||
}
|
||||
|
||||
backButton.State = state == MenuState.Play ? ButtonState.Expanded : ButtonState.Contracted;
|
||||
settingsButton.State = state == MenuState.TopLevel ? ButtonState.Expanded : ButtonState.Contracted;
|
||||
}
|
||||
|
||||
StateChanged?.Invoke(State);
|
||||
}
|
||||
}
|
||||
|
||||
private ScheduledDelegate logoDelayedAction;
|
||||
|
||||
private void updateLogoState(MenuState lastState = MenuState.Initial)
|
||||
{
|
||||
if (logo == null) return;
|
||||
|
||||
logoDelayedAction?.Cancel();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case MenuState.Exit:
|
||||
case MenuState.Initial:
|
||||
logoTracking = false;
|
||||
|
||||
logoDelayedAction = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
showOverlays.Value = false;
|
||||
|
||||
logo.ClearTransforms(targetMember: nameof(Position));
|
||||
logo.RelativePositionAxes = Axes.Both;
|
||||
|
||||
logo.MoveTo(new Vector2(0.5f), 800, Easing.OutExpo);
|
||||
logo.ScaleTo(1, 800, Easing.OutExpo);
|
||||
}, 150);
|
||||
|
||||
break;
|
||||
case MenuState.TopLevel:
|
||||
case MenuState.Play:
|
||||
logo.ClearTransforms(targetMember: nameof(Position));
|
||||
logo.RelativePositionAxes = Axes.None;
|
||||
|
||||
switch (lastState)
|
||||
{
|
||||
case MenuState.TopLevel: // coming from toplevel to play
|
||||
case MenuState.Initial:
|
||||
logoTracking = false;
|
||||
logo.ScaleTo(0.5f, 200, Easing.In);
|
||||
|
||||
logo.MoveTo(logoTrackingPosition, lastState == MenuState.EnteringMode ? 0 : 200, Easing.In);
|
||||
|
||||
logoDelayedAction = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
logoTracking = true;
|
||||
|
||||
logo.Impact();
|
||||
showOverlays.Value = true;
|
||||
}, 200);
|
||||
break;
|
||||
default:
|
||||
logoTracking = true;
|
||||
logo.ScaleTo(0.5f, 200, Easing.OutQuint);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MenuState.EnteringMode:
|
||||
logoTracking = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(iconFacade.ScreenSpaceDrawQuad.Centre);
|
||||
|
||||
private bool logoTracking;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
//if (OsuGame.IdleTime > 6000 && State != MenuState.Exit)
|
||||
// State = MenuState.Initial;
|
||||
|
||||
base.Update();
|
||||
|
||||
if (logo != null)
|
||||
{
|
||||
if (logoTracking)
|
||||
logo.Position = logoTrackingPosition;
|
||||
|
||||
iconFacade.Width = logo.SizeForFlow * 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MenuState
|
||||
{
|
||||
Initial,
|
||||
TopLevel,
|
||||
Play,
|
||||
EnteringMode,
|
||||
Exit,
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Threading;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class ButtonSystem : Container, IStateful<MenuState>
|
||||
{
|
||||
public event Action<MenuState> StateChanged;
|
||||
|
||||
private readonly BindableBool showOverlays = new BindableBool();
|
||||
|
||||
public Action OnEdit;
|
||||
public Action OnExit;
|
||||
public Action OnDirect;
|
||||
public Action OnSolo;
|
||||
public Action OnSettings;
|
||||
public Action OnMulti;
|
||||
public Action OnChart;
|
||||
public Action OnTest;
|
||||
|
||||
private readonly FlowContainerWithOrigin buttonFlow;
|
||||
|
||||
//todo: make these non-internal somehow.
|
||||
public const float BUTTON_AREA_HEIGHT = 100;
|
||||
|
||||
public const float BUTTON_WIDTH = 140f;
|
||||
public const float WEDGE_WIDTH = 20;
|
||||
|
||||
private OsuLogo logo;
|
||||
|
||||
public void SetOsuLogo(OsuLogo logo)
|
||||
{
|
||||
this.logo = logo;
|
||||
|
||||
if (this.logo != null)
|
||||
{
|
||||
this.logo.Action = onOsuLogo;
|
||||
|
||||
// osuLogo.SizeForFlow relies on loading to be complete.
|
||||
buttonFlow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0);
|
||||
|
||||
updateLogoState();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Drawable iconFacade;
|
||||
private readonly Container buttonArea;
|
||||
private readonly Box buttonAreaBackground;
|
||||
|
||||
private readonly Button backButton;
|
||||
private readonly Button settingsButton;
|
||||
|
||||
private readonly List<Button> buttonsTopLevel = new List<Button>();
|
||||
private readonly List<Button> buttonsPlay = new List<Button>();
|
||||
|
||||
private SampleChannel sampleBack;
|
||||
|
||||
public ButtonSystem()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
buttonArea = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Size = new Vector2(1, BUTTON_AREA_HEIGHT),
|
||||
Alpha = 0,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
buttonAreaBackground = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(2, 1),
|
||||
Colour = OsuColour.Gray(50),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
buttonFlow = new FlowContainerWithOrigin
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(-WEDGE_WIDTH, 0),
|
||||
Anchor = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
settingsButton = new Button(@"settings", string.Empty, FontAwesome.fa_gear, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O),
|
||||
backButton = new Button(@"back", string.Empty, FontAwesome.fa_osu_left_o, new Color4(51, 58, 94, 255), onBack, -WEDGE_WIDTH),
|
||||
iconFacade = new Container //need a container to make the osu! icon flow properly.
|
||||
{
|
||||
Size = new Vector2(0, BUTTON_AREA_HEIGHT)
|
||||
}
|
||||
},
|
||||
CentreTarget = iconFacade
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
buttonsPlay.Add(new Button(@"solo", @"button-solo-select", FontAwesome.fa_user, new Color4(102, 68, 204, 255), () => OnSolo?.Invoke(), WEDGE_WIDTH, Key.P));
|
||||
buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), () => OnMulti?.Invoke(), 0, Key.M));
|
||||
buttonsPlay.Add(new Button(@"chart", @"button-generic-select", FontAwesome.fa_osu_charts, new Color4(80, 53, 160, 255), () => OnChart?.Invoke()));
|
||||
|
||||
buttonsTopLevel.Add(new Button(@"play", @"button-play-select", FontAwesome.fa_osu_logo, new Color4(102, 68, 204, 255), onPlay, WEDGE_WIDTH, Key.P));
|
||||
buttonsTopLevel.Add(new Button(@"osu!editor", @"button-generic-select", FontAwesome.fa_osu_edit_o, new Color4(238, 170, 0, 255), () => OnEdit?.Invoke(), 0, Key.E));
|
||||
buttonsTopLevel.Add(new Button(@"osu!direct", @"button-direct-select", FontAwesome.fa_osu_chevron_down_o, new Color4(165, 204, 0, 255), () => OnDirect?.Invoke(), 0, Key.D));
|
||||
buttonsTopLevel.Add(new Button(@"exit", string.Empty, FontAwesome.fa_osu_cross_o, new Color4(238, 51, 153, 255), onExit, 0, Key.Q));
|
||||
|
||||
buttonFlow.AddRange(buttonsPlay);
|
||||
buttonFlow.AddRange(buttonsTopLevel);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(AudioManager audio, OsuGame game)
|
||||
{
|
||||
if (game != null) showOverlays.BindTo(game.ShowOverlays);
|
||||
sampleBack = audio.Sample.Get(@"Menu/button-back-select");
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Repeat) return false;
|
||||
|
||||
switch (args.Key)
|
||||
{
|
||||
case Key.Space:
|
||||
logo?.TriggerOnClick(state);
|
||||
return true;
|
||||
case Key.Escape:
|
||||
switch (State)
|
||||
{
|
||||
case MenuState.TopLevel:
|
||||
State = MenuState.Initial;
|
||||
return true;
|
||||
case MenuState.Play:
|
||||
backButton.TriggerOnClick();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void onPlay()
|
||||
{
|
||||
State = MenuState.Play;
|
||||
}
|
||||
|
||||
private void onExit()
|
||||
{
|
||||
OnExit?.Invoke();
|
||||
}
|
||||
|
||||
private void onBack()
|
||||
{
|
||||
sampleBack?.Play();
|
||||
State = MenuState.TopLevel;
|
||||
}
|
||||
|
||||
private bool onOsuLogo()
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
default:
|
||||
return true;
|
||||
case MenuState.Initial:
|
||||
State = MenuState.TopLevel;
|
||||
return true;
|
||||
case MenuState.TopLevel:
|
||||
buttonsTopLevel.First().TriggerOnClick();
|
||||
return false;
|
||||
case MenuState.Play:
|
||||
buttonsPlay.First().TriggerOnClick();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private MenuState state;
|
||||
|
||||
public override bool HandleKeyboardInput => state != MenuState.Exit;
|
||||
public override bool HandleMouseInput => state != MenuState.Exit;
|
||||
|
||||
public MenuState State
|
||||
{
|
||||
get { return state; }
|
||||
|
||||
set
|
||||
{
|
||||
if (state == value) return;
|
||||
|
||||
MenuState lastState = state;
|
||||
state = value;
|
||||
|
||||
//todo: figure a more elegant way of doing this.
|
||||
buttonsTopLevel.ForEach(b => b.ContractStyle = 0);
|
||||
buttonsPlay.ForEach(b => b.ContractStyle = 0);
|
||||
backButton.ContractStyle = 0;
|
||||
settingsButton.ContractStyle = 0;
|
||||
|
||||
if (state == MenuState.TopLevel)
|
||||
buttonArea.FinishTransforms(true);
|
||||
|
||||
updateLogoState(lastState);
|
||||
|
||||
using (buttonArea.BeginDelayedSequence(lastState == MenuState.Initial ? 150 : 0, true))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case MenuState.Exit:
|
||||
case MenuState.Initial:
|
||||
buttonAreaBackground.ScaleTo(Vector2.One, 500, Easing.Out);
|
||||
buttonArea.FadeOut(300);
|
||||
|
||||
foreach (Button b in buttonsTopLevel)
|
||||
b.State = ButtonState.Contracted;
|
||||
|
||||
foreach (Button b in buttonsPlay)
|
||||
b.State = ButtonState.Contracted;
|
||||
|
||||
if (state != MenuState.Exit && lastState == MenuState.TopLevel)
|
||||
sampleBack?.Play();
|
||||
break;
|
||||
case MenuState.TopLevel:
|
||||
buttonAreaBackground.ScaleTo(Vector2.One, 200, Easing.Out);
|
||||
|
||||
buttonArea.FadeIn(300);
|
||||
|
||||
foreach (Button b in buttonsTopLevel)
|
||||
b.State = ButtonState.Expanded;
|
||||
|
||||
foreach (Button b in buttonsPlay)
|
||||
b.State = ButtonState.Contracted;
|
||||
break;
|
||||
case MenuState.Play:
|
||||
foreach (Button b in buttonsTopLevel)
|
||||
b.State = ButtonState.Exploded;
|
||||
|
||||
foreach (Button b in buttonsPlay)
|
||||
b.State = ButtonState.Expanded;
|
||||
break;
|
||||
case MenuState.EnteringMode:
|
||||
buttonAreaBackground.ScaleTo(new Vector2(2, 0), 300, Easing.InSine);
|
||||
|
||||
buttonsTopLevel.ForEach(b => b.ContractStyle = 1);
|
||||
buttonsPlay.ForEach(b => b.ContractStyle = 1);
|
||||
backButton.ContractStyle = 1;
|
||||
settingsButton.ContractStyle = 1;
|
||||
|
||||
foreach (Button b in buttonsTopLevel)
|
||||
b.State = ButtonState.Contracted;
|
||||
|
||||
foreach (Button b in buttonsPlay)
|
||||
b.State = ButtonState.Contracted;
|
||||
break;
|
||||
}
|
||||
|
||||
backButton.State = state == MenuState.Play ? ButtonState.Expanded : ButtonState.Contracted;
|
||||
settingsButton.State = state == MenuState.TopLevel ? ButtonState.Expanded : ButtonState.Contracted;
|
||||
}
|
||||
|
||||
StateChanged?.Invoke(State);
|
||||
}
|
||||
}
|
||||
|
||||
private ScheduledDelegate logoDelayedAction;
|
||||
|
||||
private void updateLogoState(MenuState lastState = MenuState.Initial)
|
||||
{
|
||||
if (logo == null) return;
|
||||
|
||||
logoDelayedAction?.Cancel();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case MenuState.Exit:
|
||||
case MenuState.Initial:
|
||||
logoTracking = false;
|
||||
|
||||
logoDelayedAction = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
showOverlays.Value = false;
|
||||
|
||||
logo.ClearTransforms(targetMember: nameof(Position));
|
||||
logo.RelativePositionAxes = Axes.Both;
|
||||
|
||||
logo.MoveTo(new Vector2(0.5f), 800, Easing.OutExpo);
|
||||
logo.ScaleTo(1, 800, Easing.OutExpo);
|
||||
}, 150);
|
||||
|
||||
break;
|
||||
case MenuState.TopLevel:
|
||||
case MenuState.Play:
|
||||
logo.ClearTransforms(targetMember: nameof(Position));
|
||||
logo.RelativePositionAxes = Axes.None;
|
||||
|
||||
switch (lastState)
|
||||
{
|
||||
case MenuState.TopLevel: // coming from toplevel to play
|
||||
case MenuState.Initial:
|
||||
logoTracking = false;
|
||||
logo.ScaleTo(0.5f, 200, Easing.In);
|
||||
|
||||
logo.MoveTo(logoTrackingPosition, lastState == MenuState.EnteringMode ? 0 : 200, Easing.In);
|
||||
|
||||
logoDelayedAction = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
logoTracking = true;
|
||||
|
||||
logo.Impact();
|
||||
showOverlays.Value = true;
|
||||
}, 200);
|
||||
break;
|
||||
default:
|
||||
logoTracking = true;
|
||||
logo.ScaleTo(0.5f, 200, Easing.OutQuint);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MenuState.EnteringMode:
|
||||
logoTracking = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(iconFacade.ScreenSpaceDrawQuad.Centre);
|
||||
|
||||
private bool logoTracking;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
//if (OsuGame.IdleTime > 6000 && State != MenuState.Exit)
|
||||
// State = MenuState.Initial;
|
||||
|
||||
base.Update();
|
||||
|
||||
if (logo != null)
|
||||
{
|
||||
if (logoTracking)
|
||||
logo.Position = logoTrackingPosition;
|
||||
|
||||
iconFacade.Width = logo.SizeForFlow * 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MenuState
|
||||
{
|
||||
Initial,
|
||||
TopLevel,
|
||||
Play,
|
||||
EnteringMode,
|
||||
Exit,
|
||||
}
|
||||
}
|
||||
|
@ -1,109 +1,109 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class Disclaimer : OsuScreen
|
||||
{
|
||||
private Intro intro;
|
||||
private readonly SpriteIcon icon;
|
||||
private Color4 iconColour;
|
||||
|
||||
public override bool ShowOverlaysOnEnter => false;
|
||||
public override bool CursorVisible => false;
|
||||
|
||||
public Disclaimer()
|
||||
{
|
||||
ValidForResume = false;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 2),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
icon = new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Icon = FontAwesome.fa_warning,
|
||||
Size = new Vector2(30),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
TextSize = 30,
|
||||
Text = "This is a development build",
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Bottom = 20
|
||||
},
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Don't expect shit to work perfectly as this is very much a work in progress."
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Don't report bugs because we are aware. Don't complain about missing features because we are adding them."
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Sit back and enjoy. Visit discord.gg/ppy if you want to help out!",
|
||||
Margin = new MarginPadding { Bottom = 20 },
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
TextSize = 12,
|
||||
Text = "oh and yes, you will get seizures.",
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
LoadComponentAsync(intro = new Intro());
|
||||
|
||||
iconColour = colours.Yellow;
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
|
||||
icon.Delay(1500).FadeColour(iconColour, 200);
|
||||
|
||||
Content
|
||||
.FadeInFromZero(500)
|
||||
.Then(5500)
|
||||
.FadeOut(250)
|
||||
.Finally(d => Push(intro));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class Disclaimer : OsuScreen
|
||||
{
|
||||
private Intro intro;
|
||||
private readonly SpriteIcon icon;
|
||||
private Color4 iconColour;
|
||||
|
||||
public override bool ShowOverlaysOnEnter => false;
|
||||
public override bool CursorVisible => false;
|
||||
|
||||
public Disclaimer()
|
||||
{
|
||||
ValidForResume = false;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 2),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
icon = new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Icon = FontAwesome.fa_warning,
|
||||
Size = new Vector2(30),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
TextSize = 30,
|
||||
Text = "This is a development build",
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Bottom = 20
|
||||
},
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Don't expect shit to work perfectly as this is very much a work in progress."
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Don't report bugs because we are aware. Don't complain about missing features because we are adding them."
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Sit back and enjoy. Visit discord.gg/ppy if you want to help out!",
|
||||
Margin = new MarginPadding { Bottom = 20 },
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
TextSize = 12,
|
||||
Text = "oh and yes, you will get seizures.",
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
LoadComponentAsync(intro = new Intro());
|
||||
|
||||
iconColour = colours.Yellow;
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
|
||||
icon.Delay(1500).FadeColour(iconColour, 200);
|
||||
|
||||
Content
|
||||
.FadeInFromZero(500)
|
||||
.Then(5500)
|
||||
.FadeOut(250)
|
||||
.Finally(d => Push(intro));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +1,36 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
/// <summary>
|
||||
/// A flow container with an origin based on one of its contained drawables.
|
||||
/// </summary>
|
||||
public class FlowContainerWithOrigin : FillFlowContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// A target drawable which this flowcontainer should be centered around.
|
||||
/// This target should be a direct child of this FlowContainer.
|
||||
/// </summary>
|
||||
public Drawable CentreTarget;
|
||||
|
||||
protected override int Compare(Drawable x, Drawable y) => CompareReverseChildID(x, y);
|
||||
|
||||
public override Anchor Origin => Anchor.Custom;
|
||||
|
||||
public override Vector2 OriginPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CentreTarget == null)
|
||||
return base.OriginPosition;
|
||||
|
||||
return CentreTarget.DrawPosition + CentreTarget.DrawSize / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
/// <summary>
|
||||
/// A flow container with an origin based on one of its contained drawables.
|
||||
/// </summary>
|
||||
public class FlowContainerWithOrigin : FillFlowContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// A target drawable which this flowcontainer should be centered around.
|
||||
/// This target should be a direct child of this FlowContainer.
|
||||
/// </summary>
|
||||
public Drawable CentreTarget;
|
||||
|
||||
protected override int Compare(Drawable x, Drawable y) => CompareReverseChildID(x, y);
|
||||
|
||||
public override Anchor Origin => Anchor.Custom;
|
||||
|
||||
public override Vector2 OriginPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CentreTarget == null)
|
||||
return base.OriginPosition;
|
||||
|
||||
return CentreTarget.DrawPosition + CentreTarget.DrawSize / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,173 +1,173 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class Intro : OsuScreen
|
||||
{
|
||||
private const string menu_music_beatmap_hash = "3c8b1fcc9434dbb29e2fb613d3b9eada9d7bb6c125ceb32396c3b53437280c83";
|
||||
|
||||
/// <summary>
|
||||
/// Whether we have loaded the menu previously.
|
||||
/// </summary>
|
||||
public bool DidLoadMenu;
|
||||
|
||||
private MainMenu mainMenu;
|
||||
private SampleChannel welcome;
|
||||
private SampleChannel seeya;
|
||||
|
||||
public override bool ShowOverlaysOnEnter => false;
|
||||
public override bool CursorVisible => false;
|
||||
|
||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenEmpty();
|
||||
|
||||
private Bindable<bool> menuVoice;
|
||||
private Bindable<bool> menuMusic;
|
||||
private Track track;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game)
|
||||
{
|
||||
menuVoice = config.GetBindable<bool>(OsuSetting.MenuVoice);
|
||||
menuMusic = config.GetBindable<bool>(OsuSetting.MenuMusic);
|
||||
|
||||
BeatmapSetInfo setInfo = null;
|
||||
|
||||
if (!menuMusic)
|
||||
{
|
||||
var sets = beatmaps.GetAllUsableBeatmapSets();
|
||||
if (sets.Count > 0)
|
||||
setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID);
|
||||
}
|
||||
|
||||
if (setInfo == null)
|
||||
{
|
||||
setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == menu_music_beatmap_hash);
|
||||
|
||||
if (setInfo == null)
|
||||
{
|
||||
// we need to import the default menu background beatmap
|
||||
setInfo = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream(@"Tracks/circles.osz"), "circles.osz"));
|
||||
|
||||
setInfo.Protected = true;
|
||||
beatmaps.Update(setInfo);
|
||||
}
|
||||
}
|
||||
|
||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]);
|
||||
|
||||
track = Beatmap.Value.Track;
|
||||
|
||||
welcome = audio.Sample.Get(@"welcome");
|
||||
seeya = audio.Sample.Get(@"seeya");
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
|
||||
if (menuVoice)
|
||||
welcome.Play();
|
||||
|
||||
Scheduler.AddDelayed(delegate
|
||||
{
|
||||
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu.
|
||||
if (menuMusic)
|
||||
track.Start();
|
||||
|
||||
LoadComponentAsync(mainMenu = new MainMenu());
|
||||
|
||||
Scheduler.AddDelayed(delegate
|
||||
{
|
||||
DidLoadMenu = true;
|
||||
Push(mainMenu);
|
||||
}, delay_step_one);
|
||||
}, delay_step_two);
|
||||
}
|
||||
|
||||
private const double delay_step_one = 2300;
|
||||
private const double delay_step_two = 600;
|
||||
|
||||
public const int EXIT_DELAY = 3000;
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
{
|
||||
base.LogoArriving(logo, resuming);
|
||||
|
||||
logo.RelativePositionAxes = Axes.Both;
|
||||
logo.Colour = Color4.White;
|
||||
logo.Ripple = false;
|
||||
|
||||
const int quick_appear = 350;
|
||||
|
||||
int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0;
|
||||
|
||||
logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint);
|
||||
|
||||
if (!resuming)
|
||||
{
|
||||
logo.ScaleTo(1);
|
||||
logo.FadeIn();
|
||||
logo.PlayIntro();
|
||||
}
|
||||
else
|
||||
{
|
||||
logo.Triangles = false;
|
||||
|
||||
logo
|
||||
.ScaleTo(1, initialMovementTime, Easing.OutQuint)
|
||||
.FadeIn(quick_appear, Easing.OutQuint)
|
||||
.Then()
|
||||
.RotateTo(20, EXIT_DELAY * 1.5f)
|
||||
.FadeOut(EXIT_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSuspending(Screen next)
|
||||
{
|
||||
Content.FadeOut(300);
|
||||
base.OnSuspending(next);
|
||||
}
|
||||
|
||||
protected override bool OnExiting(Screen next)
|
||||
{
|
||||
//cancel exiting if we haven't loaded the menu yet.
|
||||
return !DidLoadMenu;
|
||||
}
|
||||
|
||||
protected override void OnResuming(Screen last)
|
||||
{
|
||||
if (!(last is MainMenu))
|
||||
Content.FadeIn(300);
|
||||
|
||||
double fadeOutTime = EXIT_DELAY;
|
||||
//we also handle the exit transition.
|
||||
if (menuVoice)
|
||||
seeya.Play();
|
||||
else
|
||||
fadeOutTime = 500;
|
||||
|
||||
Scheduler.AddDelayed(Exit, fadeOutTime);
|
||||
|
||||
//don't want to fade out completely else we will stop running updates and shit will hit the fan.
|
||||
Game.FadeTo(0.01f, fadeOutTime);
|
||||
|
||||
base.OnResuming(last);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class Intro : OsuScreen
|
||||
{
|
||||
private const string menu_music_beatmap_hash = "3c8b1fcc9434dbb29e2fb613d3b9eada9d7bb6c125ceb32396c3b53437280c83";
|
||||
|
||||
/// <summary>
|
||||
/// Whether we have loaded the menu previously.
|
||||
/// </summary>
|
||||
public bool DidLoadMenu;
|
||||
|
||||
private MainMenu mainMenu;
|
||||
private SampleChannel welcome;
|
||||
private SampleChannel seeya;
|
||||
|
||||
public override bool ShowOverlaysOnEnter => false;
|
||||
public override bool CursorVisible => false;
|
||||
|
||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenEmpty();
|
||||
|
||||
private Bindable<bool> menuVoice;
|
||||
private Bindable<bool> menuMusic;
|
||||
private Track track;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game)
|
||||
{
|
||||
menuVoice = config.GetBindable<bool>(OsuSetting.MenuVoice);
|
||||
menuMusic = config.GetBindable<bool>(OsuSetting.MenuMusic);
|
||||
|
||||
BeatmapSetInfo setInfo = null;
|
||||
|
||||
if (!menuMusic)
|
||||
{
|
||||
var sets = beatmaps.GetAllUsableBeatmapSets();
|
||||
if (sets.Count > 0)
|
||||
setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID);
|
||||
}
|
||||
|
||||
if (setInfo == null)
|
||||
{
|
||||
setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == menu_music_beatmap_hash);
|
||||
|
||||
if (setInfo == null)
|
||||
{
|
||||
// we need to import the default menu background beatmap
|
||||
setInfo = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream(@"Tracks/circles.osz"), "circles.osz"));
|
||||
|
||||
setInfo.Protected = true;
|
||||
beatmaps.Update(setInfo);
|
||||
}
|
||||
}
|
||||
|
||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]);
|
||||
|
||||
track = Beatmap.Value.Track;
|
||||
|
||||
welcome = audio.Sample.Get(@"welcome");
|
||||
seeya = audio.Sample.Get(@"seeya");
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
|
||||
if (menuVoice)
|
||||
welcome.Play();
|
||||
|
||||
Scheduler.AddDelayed(delegate
|
||||
{
|
||||
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu.
|
||||
if (menuMusic)
|
||||
track.Start();
|
||||
|
||||
LoadComponentAsync(mainMenu = new MainMenu());
|
||||
|
||||
Scheduler.AddDelayed(delegate
|
||||
{
|
||||
DidLoadMenu = true;
|
||||
Push(mainMenu);
|
||||
}, delay_step_one);
|
||||
}, delay_step_two);
|
||||
}
|
||||
|
||||
private const double delay_step_one = 2300;
|
||||
private const double delay_step_two = 600;
|
||||
|
||||
public const int EXIT_DELAY = 3000;
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
{
|
||||
base.LogoArriving(logo, resuming);
|
||||
|
||||
logo.RelativePositionAxes = Axes.Both;
|
||||
logo.Colour = Color4.White;
|
||||
logo.Ripple = false;
|
||||
|
||||
const int quick_appear = 350;
|
||||
|
||||
int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0;
|
||||
|
||||
logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint);
|
||||
|
||||
if (!resuming)
|
||||
{
|
||||
logo.ScaleTo(1);
|
||||
logo.FadeIn();
|
||||
logo.PlayIntro();
|
||||
}
|
||||
else
|
||||
{
|
||||
logo.Triangles = false;
|
||||
|
||||
logo
|
||||
.ScaleTo(1, initialMovementTime, Easing.OutQuint)
|
||||
.FadeIn(quick_appear, Easing.OutQuint)
|
||||
.Then()
|
||||
.RotateTo(20, EXIT_DELAY * 1.5f)
|
||||
.FadeOut(EXIT_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSuspending(Screen next)
|
||||
{
|
||||
Content.FadeOut(300);
|
||||
base.OnSuspending(next);
|
||||
}
|
||||
|
||||
protected override bool OnExiting(Screen next)
|
||||
{
|
||||
//cancel exiting if we haven't loaded the menu yet.
|
||||
return !DidLoadMenu;
|
||||
}
|
||||
|
||||
protected override void OnResuming(Screen last)
|
||||
{
|
||||
if (!(last is MainMenu))
|
||||
Content.FadeIn(300);
|
||||
|
||||
double fadeOutTime = EXIT_DELAY;
|
||||
//we also handle the exit transition.
|
||||
if (menuVoice)
|
||||
seeya.Play();
|
||||
else
|
||||
fadeOutTime = 500;
|
||||
|
||||
Scheduler.AddDelayed(Exit, fadeOutTime);
|
||||
|
||||
//don't want to fade out completely else we will stop running updates and shit will hit the fan.
|
||||
Game.FadeTo(0.01f, fadeOutTime);
|
||||
|
||||
base.OnResuming(last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,296 +1,296 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class IntroSequence : Container
|
||||
{
|
||||
private const float logo_size = 460; //todo: this should probably be 480
|
||||
|
||||
private OsuSpriteText welcomeText;
|
||||
|
||||
private Container<Box> lines;
|
||||
|
||||
private Box lineTopLeft;
|
||||
private Box lineBottomLeft;
|
||||
private Box lineTopRight;
|
||||
private Box lineBottomRight;
|
||||
|
||||
private Ring smallRing;
|
||||
private Ring mediumRing;
|
||||
private Ring bigRing;
|
||||
|
||||
private Box backgroundFill;
|
||||
private Box foregroundFill;
|
||||
|
||||
private CircularContainer pinkCircle;
|
||||
private CircularContainer blueCircle;
|
||||
private CircularContainer yellowCircle;
|
||||
private CircularContainer purpleCircle;
|
||||
|
||||
public IntroSequence()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
const int line_offset = 80;
|
||||
const int circle_offset = 250;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
lines = new Container<Box>
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new []
|
||||
{
|
||||
lineTopLeft = new Box
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(-line_offset, -line_offset),
|
||||
Rotation = 45,
|
||||
Colour = Color4.White.Opacity(180),
|
||||
},
|
||||
lineTopRight = new Box
|
||||
{
|
||||
Origin = Anchor.CentreRight,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(line_offset, -line_offset),
|
||||
Rotation = -45,
|
||||
Colour = Color4.White.Opacity(80),
|
||||
},
|
||||
lineBottomLeft = new Box
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(-line_offset, line_offset),
|
||||
Rotation = -45,
|
||||
Colour = Color4.White.Opacity(230),
|
||||
},
|
||||
lineBottomRight = new Box
|
||||
{
|
||||
Origin = Anchor.CentreRight,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(line_offset, line_offset),
|
||||
Rotation = 45,
|
||||
Colour = Color4.White.Opacity(130),
|
||||
},
|
||||
}
|
||||
},
|
||||
bigRing = new Ring(OsuColour.FromHex(@"B6C5E9"), 0.85f),
|
||||
mediumRing = new Ring(Color4.White.Opacity(130), 0.7f),
|
||||
smallRing = new Ring(Color4.White, 0.6f),
|
||||
welcomeText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = "welcome",
|
||||
Padding = new MarginPadding { Bottom = 10 },
|
||||
Font = @"Exo2.0-Light",
|
||||
Alpha = 0,
|
||||
TextSize = 42,
|
||||
Spacing = new Vector2(5),
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(logo_size),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
backgroundFill = new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0,
|
||||
Colour = OsuColour.FromHex(@"C6D8FF").Opacity(160),
|
||||
},
|
||||
foregroundFill = new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = Vector2.Zero,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0,
|
||||
Colour = Color4.White,
|
||||
},
|
||||
}
|
||||
},
|
||||
purpleCircle = new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Position = new Vector2(0, circle_offset),
|
||||
Colour = OsuColour.FromHex(@"AA92FF"),
|
||||
},
|
||||
blueCircle = new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.CentreRight,
|
||||
Position = new Vector2(-circle_offset, 0),
|
||||
Colour = OsuColour.FromHex(@"8FE5FE"),
|
||||
},
|
||||
yellowCircle = new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Position = new Vector2(0, -circle_offset),
|
||||
Colour = OsuColour.FromHex(@"FFD64C"),
|
||||
},
|
||||
pinkCircle = new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Position = new Vector2(circle_offset, 0),
|
||||
Colour = OsuColour.FromHex(@"e967a1"),
|
||||
},
|
||||
};
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
line.Size = new Vector2(105, 1.5f);
|
||||
line.Alpha = 0;
|
||||
}
|
||||
|
||||
Scale = new Vector2(0.5f);
|
||||
}
|
||||
|
||||
public void Start(double length)
|
||||
{
|
||||
if (Children.Any())
|
||||
{
|
||||
// restart if we were already run previously.
|
||||
FinishTransforms(true);
|
||||
load();
|
||||
}
|
||||
|
||||
smallRing.ResizeTo(logo_size * 0.086f, 400, Easing.InOutQuint);
|
||||
|
||||
mediumRing.ResizeTo(130, 340, Easing.OutQuad);
|
||||
mediumRing.Foreground.ResizeTo(1, 880, Easing.Out);
|
||||
|
||||
double remainingTime() => length - TransformDelay;
|
||||
|
||||
using (BeginDelayedSequence(250, true))
|
||||
{
|
||||
welcomeText.FadeIn(700);
|
||||
welcomeText.TransformSpacingTo(new Vector2(20, 0), remainingTime(), Easing.Out);
|
||||
|
||||
const int line_duration = 700;
|
||||
const int line_resize = 150;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
line.FadeIn(40).ResizeWidthTo(0, line_duration - line_resize, Easing.OutQuint);
|
||||
}
|
||||
|
||||
const int line_end_offset = 120;
|
||||
|
||||
smallRing.Foreground.ResizeTo(1, line_duration, Easing.OutQuint);
|
||||
|
||||
lineTopLeft.MoveTo(new Vector2(-line_end_offset, -line_end_offset), line_duration, Easing.OutQuint);
|
||||
lineTopRight.MoveTo(new Vector2(line_end_offset, -line_end_offset), line_duration, Easing.OutQuint);
|
||||
lineBottomLeft.MoveTo(new Vector2(-line_end_offset, line_end_offset), line_duration, Easing.OutQuint);
|
||||
lineBottomRight.MoveTo(new Vector2(line_end_offset, line_end_offset), line_duration, Easing.OutQuint);
|
||||
|
||||
using (BeginDelayedSequence(length * 0.56, true))
|
||||
{
|
||||
bigRing.ResizeTo(logo_size, 500, Easing.InOutQuint);
|
||||
bigRing.Foreground.Delay(250).ResizeTo(1, 850, Easing.OutQuint);
|
||||
|
||||
using (BeginDelayedSequence(250, true))
|
||||
{
|
||||
backgroundFill.ResizeHeightTo(1, remainingTime(), Easing.InOutQuart);
|
||||
backgroundFill.RotateTo(-90, remainingTime(), Easing.InOutQuart);
|
||||
|
||||
using (BeginDelayedSequence(50, true))
|
||||
{
|
||||
foregroundFill.ResizeWidthTo(1, remainingTime(), Easing.InOutQuart);
|
||||
foregroundFill.RotateTo(-90, remainingTime(), Easing.InOutQuart);
|
||||
}
|
||||
|
||||
this.ScaleTo(1, remainingTime(), Easing.InOutCubic);
|
||||
|
||||
const float circle_size = logo_size * 0.9f;
|
||||
|
||||
const int rotation_delay = 110;
|
||||
const int appear_delay = 80;
|
||||
|
||||
purpleCircle.MoveToY(circle_size / 2, remainingTime(), Easing.InOutQuart);
|
||||
purpleCircle.Delay(rotation_delay).RotateTo(-180, remainingTime() - rotation_delay, Easing.InOutQuart);
|
||||
purpleCircle.ResizeTo(circle_size, remainingTime(), Easing.InOutQuart);
|
||||
|
||||
using (BeginDelayedSequence(appear_delay, true))
|
||||
{
|
||||
yellowCircle.MoveToY(-circle_size / 2, remainingTime(), Easing.InOutQuart);
|
||||
yellowCircle.Delay(rotation_delay).RotateTo(-180, remainingTime() - rotation_delay, Easing.InOutQuart);
|
||||
yellowCircle.ResizeTo(circle_size, remainingTime(), Easing.InOutQuart);
|
||||
|
||||
using (BeginDelayedSequence(appear_delay, true))
|
||||
{
|
||||
blueCircle.MoveToX(-circle_size / 2, remainingTime(), Easing.InOutQuart);
|
||||
blueCircle.Delay(rotation_delay).RotateTo(-180, remainingTime() - rotation_delay, Easing.InOutQuart);
|
||||
blueCircle.ResizeTo(circle_size, remainingTime(), Easing.InOutQuart);
|
||||
|
||||
using (BeginDelayedSequence(appear_delay, true))
|
||||
{
|
||||
pinkCircle.MoveToX(circle_size / 2, remainingTime(), Easing.InOutQuart);
|
||||
pinkCircle.Delay(rotation_delay).RotateTo(-180, remainingTime() - rotation_delay, Easing.InOutQuart);
|
||||
pinkCircle.ResizeTo(circle_size, remainingTime(), Easing.InOutQuart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Ring : Container<Circle>
|
||||
{
|
||||
public readonly Circle Foreground;
|
||||
|
||||
public Ring(Color4 ringColour, float foregroundSize)
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Children = new[]
|
||||
{
|
||||
new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.98f),
|
||||
Colour = ringColour,
|
||||
},
|
||||
Foreground = new Circle
|
||||
{
|
||||
Size = new Vector2(foregroundSize),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class IntroSequence : Container
|
||||
{
|
||||
private const float logo_size = 460; //todo: this should probably be 480
|
||||
|
||||
private OsuSpriteText welcomeText;
|
||||
|
||||
private Container<Box> lines;
|
||||
|
||||
private Box lineTopLeft;
|
||||
private Box lineBottomLeft;
|
||||
private Box lineTopRight;
|
||||
private Box lineBottomRight;
|
||||
|
||||
private Ring smallRing;
|
||||
private Ring mediumRing;
|
||||
private Ring bigRing;
|
||||
|
||||
private Box backgroundFill;
|
||||
private Box foregroundFill;
|
||||
|
||||
private CircularContainer pinkCircle;
|
||||
private CircularContainer blueCircle;
|
||||
private CircularContainer yellowCircle;
|
||||
private CircularContainer purpleCircle;
|
||||
|
||||
public IntroSequence()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
const int line_offset = 80;
|
||||
const int circle_offset = 250;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
lines = new Container<Box>
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new []
|
||||
{
|
||||
lineTopLeft = new Box
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(-line_offset, -line_offset),
|
||||
Rotation = 45,
|
||||
Colour = Color4.White.Opacity(180),
|
||||
},
|
||||
lineTopRight = new Box
|
||||
{
|
||||
Origin = Anchor.CentreRight,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(line_offset, -line_offset),
|
||||
Rotation = -45,
|
||||
Colour = Color4.White.Opacity(80),
|
||||
},
|
||||
lineBottomLeft = new Box
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(-line_offset, line_offset),
|
||||
Rotation = -45,
|
||||
Colour = Color4.White.Opacity(230),
|
||||
},
|
||||
lineBottomRight = new Box
|
||||
{
|
||||
Origin = Anchor.CentreRight,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(line_offset, line_offset),
|
||||
Rotation = 45,
|
||||
Colour = Color4.White.Opacity(130),
|
||||
},
|
||||
}
|
||||
},
|
||||
bigRing = new Ring(OsuColour.FromHex(@"B6C5E9"), 0.85f),
|
||||
mediumRing = new Ring(Color4.White.Opacity(130), 0.7f),
|
||||
smallRing = new Ring(Color4.White, 0.6f),
|
||||
welcomeText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = "welcome",
|
||||
Padding = new MarginPadding { Bottom = 10 },
|
||||
Font = @"Exo2.0-Light",
|
||||
Alpha = 0,
|
||||
TextSize = 42,
|
||||
Spacing = new Vector2(5),
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(logo_size),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
backgroundFill = new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0,
|
||||
Colour = OsuColour.FromHex(@"C6D8FF").Opacity(160),
|
||||
},
|
||||
foregroundFill = new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = Vector2.Zero,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0,
|
||||
Colour = Color4.White,
|
||||
},
|
||||
}
|
||||
},
|
||||
purpleCircle = new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Position = new Vector2(0, circle_offset),
|
||||
Colour = OsuColour.FromHex(@"AA92FF"),
|
||||
},
|
||||
blueCircle = new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.CentreRight,
|
||||
Position = new Vector2(-circle_offset, 0),
|
||||
Colour = OsuColour.FromHex(@"8FE5FE"),
|
||||
},
|
||||
yellowCircle = new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Position = new Vector2(0, -circle_offset),
|
||||
Colour = OsuColour.FromHex(@"FFD64C"),
|
||||
},
|
||||
pinkCircle = new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Position = new Vector2(circle_offset, 0),
|
||||
Colour = OsuColour.FromHex(@"e967a1"),
|
||||
},
|
||||
};
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
line.Size = new Vector2(105, 1.5f);
|
||||
line.Alpha = 0;
|
||||
}
|
||||
|
||||
Scale = new Vector2(0.5f);
|
||||
}
|
||||
|
||||
public void Start(double length)
|
||||
{
|
||||
if (Children.Any())
|
||||
{
|
||||
// restart if we were already run previously.
|
||||
FinishTransforms(true);
|
||||
load();
|
||||
}
|
||||
|
||||
smallRing.ResizeTo(logo_size * 0.086f, 400, Easing.InOutQuint);
|
||||
|
||||
mediumRing.ResizeTo(130, 340, Easing.OutQuad);
|
||||
mediumRing.Foreground.ResizeTo(1, 880, Easing.Out);
|
||||
|
||||
double remainingTime() => length - TransformDelay;
|
||||
|
||||
using (BeginDelayedSequence(250, true))
|
||||
{
|
||||
welcomeText.FadeIn(700);
|
||||
welcomeText.TransformSpacingTo(new Vector2(20, 0), remainingTime(), Easing.Out);
|
||||
|
||||
const int line_duration = 700;
|
||||
const int line_resize = 150;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
line.FadeIn(40).ResizeWidthTo(0, line_duration - line_resize, Easing.OutQuint);
|
||||
}
|
||||
|
||||
const int line_end_offset = 120;
|
||||
|
||||
smallRing.Foreground.ResizeTo(1, line_duration, Easing.OutQuint);
|
||||
|
||||
lineTopLeft.MoveTo(new Vector2(-line_end_offset, -line_end_offset), line_duration, Easing.OutQuint);
|
||||
lineTopRight.MoveTo(new Vector2(line_end_offset, -line_end_offset), line_duration, Easing.OutQuint);
|
||||
lineBottomLeft.MoveTo(new Vector2(-line_end_offset, line_end_offset), line_duration, Easing.OutQuint);
|
||||
lineBottomRight.MoveTo(new Vector2(line_end_offset, line_end_offset), line_duration, Easing.OutQuint);
|
||||
|
||||
using (BeginDelayedSequence(length * 0.56, true))
|
||||
{
|
||||
bigRing.ResizeTo(logo_size, 500, Easing.InOutQuint);
|
||||
bigRing.Foreground.Delay(250).ResizeTo(1, 850, Easing.OutQuint);
|
||||
|
||||
using (BeginDelayedSequence(250, true))
|
||||
{
|
||||
backgroundFill.ResizeHeightTo(1, remainingTime(), Easing.InOutQuart);
|
||||
backgroundFill.RotateTo(-90, remainingTime(), Easing.InOutQuart);
|
||||
|
||||
using (BeginDelayedSequence(50, true))
|
||||
{
|
||||
foregroundFill.ResizeWidthTo(1, remainingTime(), Easing.InOutQuart);
|
||||
foregroundFill.RotateTo(-90, remainingTime(), Easing.InOutQuart);
|
||||
}
|
||||
|
||||
this.ScaleTo(1, remainingTime(), Easing.InOutCubic);
|
||||
|
||||
const float circle_size = logo_size * 0.9f;
|
||||
|
||||
const int rotation_delay = 110;
|
||||
const int appear_delay = 80;
|
||||
|
||||
purpleCircle.MoveToY(circle_size / 2, remainingTime(), Easing.InOutQuart);
|
||||
purpleCircle.Delay(rotation_delay).RotateTo(-180, remainingTime() - rotation_delay, Easing.InOutQuart);
|
||||
purpleCircle.ResizeTo(circle_size, remainingTime(), Easing.InOutQuart);
|
||||
|
||||
using (BeginDelayedSequence(appear_delay, true))
|
||||
{
|
||||
yellowCircle.MoveToY(-circle_size / 2, remainingTime(), Easing.InOutQuart);
|
||||
yellowCircle.Delay(rotation_delay).RotateTo(-180, remainingTime() - rotation_delay, Easing.InOutQuart);
|
||||
yellowCircle.ResizeTo(circle_size, remainingTime(), Easing.InOutQuart);
|
||||
|
||||
using (BeginDelayedSequence(appear_delay, true))
|
||||
{
|
||||
blueCircle.MoveToX(-circle_size / 2, remainingTime(), Easing.InOutQuart);
|
||||
blueCircle.Delay(rotation_delay).RotateTo(-180, remainingTime() - rotation_delay, Easing.InOutQuart);
|
||||
blueCircle.ResizeTo(circle_size, remainingTime(), Easing.InOutQuart);
|
||||
|
||||
using (BeginDelayedSequence(appear_delay, true))
|
||||
{
|
||||
pinkCircle.MoveToX(circle_size / 2, remainingTime(), Easing.InOutQuart);
|
||||
pinkCircle.Delay(rotation_delay).RotateTo(-180, remainingTime() - rotation_delay, Easing.InOutQuart);
|
||||
pinkCircle.ResizeTo(circle_size, remainingTime(), Easing.InOutQuart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Ring : Container<Circle>
|
||||
{
|
||||
public readonly Circle Foreground;
|
||||
|
||||
public Ring(Color4 ringColour, float foregroundSize)
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Children = new[]
|
||||
{
|
||||
new Circle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.98f),
|
||||
Colour = ringColour,
|
||||
},
|
||||
Foreground = new Circle
|
||||
{
|
||||
Size = new Vector2(foregroundSize),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,224 +1,224 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.ES30;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Batches;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shaders;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class LogoVisualisation : Drawable, IHasAccentColour
|
||||
{
|
||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
/// <summary>
|
||||
/// The number of bars to jump each update iteration.
|
||||
/// </summary>
|
||||
private const int index_change = 5;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum length of each bar in the visualiser. Will be reduced when kiai is not activated.
|
||||
/// </summary>
|
||||
private const float bar_length = 600;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bars in one rotation of the visualiser.
|
||||
/// </summary>
|
||||
private const int bars_per_visualiser = 200;
|
||||
|
||||
/// <summary>
|
||||
/// How many times we should stretch around the circumference (overlapping overselves).
|
||||
/// </summary>
|
||||
private const float visualiser_rounds = 5;
|
||||
|
||||
/// <summary>
|
||||
/// How much should each bar go down each milisecond (based on a full bar).
|
||||
/// </summary>
|
||||
private const float decay_per_milisecond = 0.0024f;
|
||||
|
||||
/// <summary>
|
||||
/// Number of milliseconds between each amplitude update.
|
||||
/// </summary>
|
||||
private const float time_between_updates = 50;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum amplitude to show a bar.
|
||||
/// </summary>
|
||||
private const float amplitude_dead_zone = 1f / bar_length;
|
||||
|
||||
private int indexOffset;
|
||||
|
||||
public Color4 AccentColour { get; set; }
|
||||
|
||||
private readonly float[] frequencyAmplitudes = new float[256];
|
||||
|
||||
public override bool HandleKeyboardInput => false;
|
||||
public override bool HandleMouseInput => false;
|
||||
|
||||
private Shader shader;
|
||||
private readonly Texture texture;
|
||||
|
||||
public LogoVisualisation()
|
||||
{
|
||||
texture = Texture.WhitePixel;
|
||||
AccentColour = new Color4(1, 1, 1, 0.2f);
|
||||
Blending = BlendingMode.Additive;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ShaderManager shaders, OsuGameBase game)
|
||||
{
|
||||
beatmap.BindTo(game.Beatmap);
|
||||
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);
|
||||
}
|
||||
|
||||
private void updateAmplitudes()
|
||||
{
|
||||
var track = beatmap.Value.TrackLoaded ? beatmap.Value.Track : null;
|
||||
var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null;
|
||||
|
||||
float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes ?? new float[256];
|
||||
|
||||
for (int i = 0; i < bars_per_visualiser; i++)
|
||||
{
|
||||
if (track?.IsRunning ?? false)
|
||||
{
|
||||
float targetAmplitude = temporalAmplitudes[(i + indexOffset) % bars_per_visualiser] * (effect?.KiaiMode == true ? 1 : 0.5f);
|
||||
if (targetAmplitude > frequencyAmplitudes[i])
|
||||
frequencyAmplitudes[i] = targetAmplitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = (i + index_change) % bars_per_visualiser;
|
||||
if (frequencyAmplitudes[index] > frequencyAmplitudes[i])
|
||||
frequencyAmplitudes[i] = frequencyAmplitudes[index];
|
||||
}
|
||||
}
|
||||
|
||||
indexOffset = (indexOffset + index_change) % bars_per_visualiser;
|
||||
Scheduler.AddDelayed(updateAmplitudes, time_between_updates);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateAmplitudes();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
float decayFactor = (float)Time.Elapsed * decay_per_milisecond;
|
||||
for (int i = 0; i < bars_per_visualiser; i++)
|
||||
{
|
||||
//3% of extra bar length to make it a little faster when bar is almost at it's minimum
|
||||
frequencyAmplitudes[i] -= decayFactor * (frequencyAmplitudes[i] + 0.03f);
|
||||
if (frequencyAmplitudes[i] < 0)
|
||||
frequencyAmplitudes[i] = 0;
|
||||
}
|
||||
|
||||
Invalidate(Invalidation.DrawNode, shallPropagate: false);
|
||||
}
|
||||
|
||||
protected override DrawNode CreateDrawNode() => new VisualisationDrawNode();
|
||||
|
||||
private readonly VisualiserSharedData sharedData = new VisualiserSharedData();
|
||||
|
||||
protected override void ApplyDrawNode(DrawNode node)
|
||||
{
|
||||
base.ApplyDrawNode(node);
|
||||
|
||||
var visNode = (VisualisationDrawNode)node;
|
||||
|
||||
visNode.Shader = shader;
|
||||
visNode.Texture = texture;
|
||||
visNode.Size = DrawSize.X;
|
||||
visNode.Shared = sharedData;
|
||||
visNode.Colour = AccentColour;
|
||||
visNode.AudioData = frequencyAmplitudes;
|
||||
}
|
||||
|
||||
private class VisualiserSharedData
|
||||
{
|
||||
public readonly LinearBatch<TexturedVertex2D> VertexBatch = new LinearBatch<TexturedVertex2D>(100 * 4, 10, PrimitiveType.Quads);
|
||||
}
|
||||
|
||||
private class VisualisationDrawNode : DrawNode
|
||||
{
|
||||
public Shader Shader;
|
||||
public Texture Texture;
|
||||
public VisualiserSharedData Shared;
|
||||
//Asuming the logo is a circle, we don't need a second dimension.
|
||||
public float Size;
|
||||
|
||||
public Color4 Colour;
|
||||
public float[] AudioData;
|
||||
|
||||
public override void Draw(Action<TexturedVertex2D> vertexAction)
|
||||
{
|
||||
base.Draw(vertexAction);
|
||||
|
||||
Shader.Bind();
|
||||
Texture.TextureGL.Bind();
|
||||
|
||||
Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy;
|
||||
|
||||
ColourInfo colourInfo = DrawInfo.Colour;
|
||||
colourInfo.ApplyChild(Colour);
|
||||
|
||||
if (AudioData != null)
|
||||
{
|
||||
for (int j = 0; j < visualiser_rounds; j++)
|
||||
{
|
||||
for (int i = 0; i < bars_per_visualiser; i++)
|
||||
{
|
||||
if (AudioData[i] < amplitude_dead_zone)
|
||||
continue;
|
||||
|
||||
float rotation = MathHelper.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds);
|
||||
float rotationCos = (float)Math.Cos(rotation);
|
||||
float rotationSin = (float)Math.Sin(rotation);
|
||||
//taking the cos and sin to the 0..1 range
|
||||
var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * Size;
|
||||
|
||||
var barSize = new Vector2(Size * (float)Math.Sqrt(2 * (1 - Math.Cos(MathHelper.DegreesToRadians(360f / bars_per_visualiser)))) / 2f, bar_length * AudioData[i]);
|
||||
//The distance between the position and the sides of the bar.
|
||||
var bottomOffset = new Vector2(-rotationSin * barSize.X / 2, rotationCos * barSize.X / 2);
|
||||
//The distance between the bottom side of the bar and the top side.
|
||||
var amplitudeOffset = new Vector2(rotationCos * barSize.Y, rotationSin * barSize.Y);
|
||||
|
||||
var rectangle = new Quad(
|
||||
Vector2Extensions.Transform(barPosition - bottomOffset, DrawInfo.Matrix),
|
||||
Vector2Extensions.Transform(barPosition - bottomOffset + amplitudeOffset, DrawInfo.Matrix),
|
||||
Vector2Extensions.Transform(barPosition + bottomOffset, DrawInfo.Matrix),
|
||||
Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix)
|
||||
);
|
||||
|
||||
Texture.DrawQuad(
|
||||
rectangle,
|
||||
colourInfo,
|
||||
null,
|
||||
Shared.VertexBatch.AddAction,
|
||||
//barSize by itself will make it smooth more in the X axis than in the Y axis, this reverts that.
|
||||
Vector2.Divide(inflation, barSize.Yx));
|
||||
}
|
||||
}
|
||||
}
|
||||
Shader.Unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.ES30;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Batches;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shaders;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class LogoVisualisation : Drawable, IHasAccentColour
|
||||
{
|
||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
/// <summary>
|
||||
/// The number of bars to jump each update iteration.
|
||||
/// </summary>
|
||||
private const int index_change = 5;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum length of each bar in the visualiser. Will be reduced when kiai is not activated.
|
||||
/// </summary>
|
||||
private const float bar_length = 600;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bars in one rotation of the visualiser.
|
||||
/// </summary>
|
||||
private const int bars_per_visualiser = 200;
|
||||
|
||||
/// <summary>
|
||||
/// How many times we should stretch around the circumference (overlapping overselves).
|
||||
/// </summary>
|
||||
private const float visualiser_rounds = 5;
|
||||
|
||||
/// <summary>
|
||||
/// How much should each bar go down each milisecond (based on a full bar).
|
||||
/// </summary>
|
||||
private const float decay_per_milisecond = 0.0024f;
|
||||
|
||||
/// <summary>
|
||||
/// Number of milliseconds between each amplitude update.
|
||||
/// </summary>
|
||||
private const float time_between_updates = 50;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum amplitude to show a bar.
|
||||
/// </summary>
|
||||
private const float amplitude_dead_zone = 1f / bar_length;
|
||||
|
||||
private int indexOffset;
|
||||
|
||||
public Color4 AccentColour { get; set; }
|
||||
|
||||
private readonly float[] frequencyAmplitudes = new float[256];
|
||||
|
||||
public override bool HandleKeyboardInput => false;
|
||||
public override bool HandleMouseInput => false;
|
||||
|
||||
private Shader shader;
|
||||
private readonly Texture texture;
|
||||
|
||||
public LogoVisualisation()
|
||||
{
|
||||
texture = Texture.WhitePixel;
|
||||
AccentColour = new Color4(1, 1, 1, 0.2f);
|
||||
Blending = BlendingMode.Additive;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ShaderManager shaders, OsuGameBase game)
|
||||
{
|
||||
beatmap.BindTo(game.Beatmap);
|
||||
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);
|
||||
}
|
||||
|
||||
private void updateAmplitudes()
|
||||
{
|
||||
var track = beatmap.Value.TrackLoaded ? beatmap.Value.Track : null;
|
||||
var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null;
|
||||
|
||||
float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes ?? new float[256];
|
||||
|
||||
for (int i = 0; i < bars_per_visualiser; i++)
|
||||
{
|
||||
if (track?.IsRunning ?? false)
|
||||
{
|
||||
float targetAmplitude = temporalAmplitudes[(i + indexOffset) % bars_per_visualiser] * (effect?.KiaiMode == true ? 1 : 0.5f);
|
||||
if (targetAmplitude > frequencyAmplitudes[i])
|
||||
frequencyAmplitudes[i] = targetAmplitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = (i + index_change) % bars_per_visualiser;
|
||||
if (frequencyAmplitudes[index] > frequencyAmplitudes[i])
|
||||
frequencyAmplitudes[i] = frequencyAmplitudes[index];
|
||||
}
|
||||
}
|
||||
|
||||
indexOffset = (indexOffset + index_change) % bars_per_visualiser;
|
||||
Scheduler.AddDelayed(updateAmplitudes, time_between_updates);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateAmplitudes();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
float decayFactor = (float)Time.Elapsed * decay_per_milisecond;
|
||||
for (int i = 0; i < bars_per_visualiser; i++)
|
||||
{
|
||||
//3% of extra bar length to make it a little faster when bar is almost at it's minimum
|
||||
frequencyAmplitudes[i] -= decayFactor * (frequencyAmplitudes[i] + 0.03f);
|
||||
if (frequencyAmplitudes[i] < 0)
|
||||
frequencyAmplitudes[i] = 0;
|
||||
}
|
||||
|
||||
Invalidate(Invalidation.DrawNode, shallPropagate: false);
|
||||
}
|
||||
|
||||
protected override DrawNode CreateDrawNode() => new VisualisationDrawNode();
|
||||
|
||||
private readonly VisualiserSharedData sharedData = new VisualiserSharedData();
|
||||
|
||||
protected override void ApplyDrawNode(DrawNode node)
|
||||
{
|
||||
base.ApplyDrawNode(node);
|
||||
|
||||
var visNode = (VisualisationDrawNode)node;
|
||||
|
||||
visNode.Shader = shader;
|
||||
visNode.Texture = texture;
|
||||
visNode.Size = DrawSize.X;
|
||||
visNode.Shared = sharedData;
|
||||
visNode.Colour = AccentColour;
|
||||
visNode.AudioData = frequencyAmplitudes;
|
||||
}
|
||||
|
||||
private class VisualiserSharedData
|
||||
{
|
||||
public readonly LinearBatch<TexturedVertex2D> VertexBatch = new LinearBatch<TexturedVertex2D>(100 * 4, 10, PrimitiveType.Quads);
|
||||
}
|
||||
|
||||
private class VisualisationDrawNode : DrawNode
|
||||
{
|
||||
public Shader Shader;
|
||||
public Texture Texture;
|
||||
public VisualiserSharedData Shared;
|
||||
//Asuming the logo is a circle, we don't need a second dimension.
|
||||
public float Size;
|
||||
|
||||
public Color4 Colour;
|
||||
public float[] AudioData;
|
||||
|
||||
public override void Draw(Action<TexturedVertex2D> vertexAction)
|
||||
{
|
||||
base.Draw(vertexAction);
|
||||
|
||||
Shader.Bind();
|
||||
Texture.TextureGL.Bind();
|
||||
|
||||
Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy;
|
||||
|
||||
ColourInfo colourInfo = DrawInfo.Colour;
|
||||
colourInfo.ApplyChild(Colour);
|
||||
|
||||
if (AudioData != null)
|
||||
{
|
||||
for (int j = 0; j < visualiser_rounds; j++)
|
||||
{
|
||||
for (int i = 0; i < bars_per_visualiser; i++)
|
||||
{
|
||||
if (AudioData[i] < amplitude_dead_zone)
|
||||
continue;
|
||||
|
||||
float rotation = MathHelper.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds);
|
||||
float rotationCos = (float)Math.Cos(rotation);
|
||||
float rotationSin = (float)Math.Sin(rotation);
|
||||
//taking the cos and sin to the 0..1 range
|
||||
var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * Size;
|
||||
|
||||
var barSize = new Vector2(Size * (float)Math.Sqrt(2 * (1 - Math.Cos(MathHelper.DegreesToRadians(360f / bars_per_visualiser)))) / 2f, bar_length * AudioData[i]);
|
||||
//The distance between the position and the sides of the bar.
|
||||
var bottomOffset = new Vector2(-rotationSin * barSize.X / 2, rotationCos * barSize.X / 2);
|
||||
//The distance between the bottom side of the bar and the top side.
|
||||
var amplitudeOffset = new Vector2(rotationCos * barSize.Y, rotationSin * barSize.Y);
|
||||
|
||||
var rectangle = new Quad(
|
||||
Vector2Extensions.Transform(barPosition - bottomOffset, DrawInfo.Matrix),
|
||||
Vector2Extensions.Transform(barPosition - bottomOffset + amplitudeOffset, DrawInfo.Matrix),
|
||||
Vector2Extensions.Transform(barPosition + bottomOffset, DrawInfo.Matrix),
|
||||
Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix)
|
||||
);
|
||||
|
||||
Texture.DrawQuad(
|
||||
rectangle,
|
||||
colourInfo,
|
||||
null,
|
||||
Shared.VertexBatch.AddAction,
|
||||
//barSize by itself will make it smooth more in the X axis than in the Y axis, this reverts that.
|
||||
Vector2.Divide(inflation, barSize.Yx));
|
||||
}
|
||||
}
|
||||
}
|
||||
Shader.Unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,188 +1,188 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
using osu.Game.Screens.Charts;
|
||||
using osu.Game.Screens.Direct;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Multiplayer;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Tournament;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class MainMenu : OsuScreen
|
||||
{
|
||||
private readonly ButtonSystem buttons;
|
||||
|
||||
public override bool ShowOverlaysOnEnter => buttons.State != MenuState.Initial;
|
||||
|
||||
private readonly BackgroundScreenDefault background;
|
||||
private Screen songSelect;
|
||||
|
||||
private readonly MenuSideFlashes sideFlashes;
|
||||
|
||||
protected override BackgroundScreen CreateBackground() => background;
|
||||
|
||||
public MainMenu()
|
||||
{
|
||||
background = new BackgroundScreenDefault();
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ParallaxContainer
|
||||
{
|
||||
ParallaxAmount = 0.01f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
buttons = new ButtonSystem
|
||||
{
|
||||
OnChart = delegate { Push(new ChartListing()); },
|
||||
OnDirect = delegate { Push(new OnlineListing()); },
|
||||
OnEdit = delegate { Push(new Editor()); },
|
||||
OnSolo = delegate { Push(consumeSongSelect()); },
|
||||
OnMulti = delegate { Push(new Lobby()); },
|
||||
OnExit = Exit,
|
||||
}
|
||||
}
|
||||
},
|
||||
sideFlashes = new MenuSideFlashes(),
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuGame game = null)
|
||||
{
|
||||
LoadComponentAsync(background);
|
||||
|
||||
if (game != null)
|
||||
{
|
||||
buttons.OnSettings = game.ToggleSettings;
|
||||
buttons.OnDirect = game.ToggleDirect;
|
||||
}
|
||||
|
||||
preloadSongSelect();
|
||||
}
|
||||
|
||||
private void preloadSongSelect()
|
||||
{
|
||||
if (songSelect == null)
|
||||
LoadComponentAsync(songSelect = new PlaySongSelect());
|
||||
}
|
||||
|
||||
private Screen consumeSongSelect()
|
||||
{
|
||||
var s = songSelect;
|
||||
songSelect = null;
|
||||
return s;
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
buttons.FadeInFromZero(500);
|
||||
|
||||
var track = Beatmap.Value.Track;
|
||||
var metadata = Beatmap.Value.Metadata;
|
||||
|
||||
if (last is Intro && track != null)
|
||||
{
|
||||
if (!track.IsRunning)
|
||||
{
|
||||
track.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * track.Length);
|
||||
track.Start();
|
||||
}
|
||||
}
|
||||
|
||||
Beatmap.ValueChanged += beatmap_ValueChanged;
|
||||
}
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
{
|
||||
base.LogoArriving(logo, resuming);
|
||||
|
||||
buttons.SetOsuLogo(logo);
|
||||
|
||||
logo.FadeColour(Color4.White, 100, Easing.OutQuint);
|
||||
logo.FadeIn(100, Easing.OutQuint);
|
||||
|
||||
if (resuming)
|
||||
{
|
||||
buttons.State = MenuState.TopLevel;
|
||||
|
||||
const float length = 300;
|
||||
|
||||
Content.FadeIn(length, Easing.OutQuint);
|
||||
Content.MoveTo(new Vector2(0, 0), length, Easing.OutQuint);
|
||||
|
||||
sideFlashes.Delay(length).FadeIn(64, Easing.InQuint);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LogoSuspending(OsuLogo logo)
|
||||
{
|
||||
logo.FadeOut(300, Easing.InSine)
|
||||
.ScaleTo(0.2f, 300, Easing.InSine)
|
||||
.OnComplete(l => buttons.SetOsuLogo(null));
|
||||
}
|
||||
|
||||
private void beatmap_ValueChanged(WorkingBeatmap newValue)
|
||||
{
|
||||
if (!IsCurrentScreen)
|
||||
return;
|
||||
|
||||
background.Next();
|
||||
}
|
||||
|
||||
protected override void OnSuspending(Screen next)
|
||||
{
|
||||
base.OnSuspending(next);
|
||||
|
||||
const float length = 400;
|
||||
|
||||
buttons.State = MenuState.EnteringMode;
|
||||
|
||||
Content.FadeOut(length, Easing.InSine);
|
||||
Content.MoveTo(new Vector2(-800, 0), length, Easing.InSine);
|
||||
|
||||
sideFlashes.FadeOut(64, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void OnResuming(Screen last)
|
||||
{
|
||||
base.OnResuming(last);
|
||||
|
||||
background.Next();
|
||||
|
||||
//we may have consumed our preloaded instance, so let's make another.
|
||||
preloadSongSelect();
|
||||
}
|
||||
|
||||
protected override bool OnExiting(Screen next)
|
||||
{
|
||||
buttons.State = MenuState.Exit;
|
||||
Content.FadeOut(3000);
|
||||
return base.OnExiting(next);
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (!args.Repeat && state.Keyboard.ControlPressed && state.Keyboard.ShiftPressed && args.Key == Key.D)
|
||||
{
|
||||
Push(new Drawings());
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyDown(state, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
using osu.Game.Screens.Charts;
|
||||
using osu.Game.Screens.Direct;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Multiplayer;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Tournament;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class MainMenu : OsuScreen
|
||||
{
|
||||
private readonly ButtonSystem buttons;
|
||||
|
||||
public override bool ShowOverlaysOnEnter => buttons.State != MenuState.Initial;
|
||||
|
||||
private readonly BackgroundScreenDefault background;
|
||||
private Screen songSelect;
|
||||
|
||||
private readonly MenuSideFlashes sideFlashes;
|
||||
|
||||
protected override BackgroundScreen CreateBackground() => background;
|
||||
|
||||
public MainMenu()
|
||||
{
|
||||
background = new BackgroundScreenDefault();
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ParallaxContainer
|
||||
{
|
||||
ParallaxAmount = 0.01f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
buttons = new ButtonSystem
|
||||
{
|
||||
OnChart = delegate { Push(new ChartListing()); },
|
||||
OnDirect = delegate { Push(new OnlineListing()); },
|
||||
OnEdit = delegate { Push(new Editor()); },
|
||||
OnSolo = delegate { Push(consumeSongSelect()); },
|
||||
OnMulti = delegate { Push(new Lobby()); },
|
||||
OnExit = Exit,
|
||||
}
|
||||
}
|
||||
},
|
||||
sideFlashes = new MenuSideFlashes(),
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuGame game = null)
|
||||
{
|
||||
LoadComponentAsync(background);
|
||||
|
||||
if (game != null)
|
||||
{
|
||||
buttons.OnSettings = game.ToggleSettings;
|
||||
buttons.OnDirect = game.ToggleDirect;
|
||||
}
|
||||
|
||||
preloadSongSelect();
|
||||
}
|
||||
|
||||
private void preloadSongSelect()
|
||||
{
|
||||
if (songSelect == null)
|
||||
LoadComponentAsync(songSelect = new PlaySongSelect());
|
||||
}
|
||||
|
||||
private Screen consumeSongSelect()
|
||||
{
|
||||
var s = songSelect;
|
||||
songSelect = null;
|
||||
return s;
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
buttons.FadeInFromZero(500);
|
||||
|
||||
var track = Beatmap.Value.Track;
|
||||
var metadata = Beatmap.Value.Metadata;
|
||||
|
||||
if (last is Intro && track != null)
|
||||
{
|
||||
if (!track.IsRunning)
|
||||
{
|
||||
track.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * track.Length);
|
||||
track.Start();
|
||||
}
|
||||
}
|
||||
|
||||
Beatmap.ValueChanged += beatmap_ValueChanged;
|
||||
}
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
{
|
||||
base.LogoArriving(logo, resuming);
|
||||
|
||||
buttons.SetOsuLogo(logo);
|
||||
|
||||
logo.FadeColour(Color4.White, 100, Easing.OutQuint);
|
||||
logo.FadeIn(100, Easing.OutQuint);
|
||||
|
||||
if (resuming)
|
||||
{
|
||||
buttons.State = MenuState.TopLevel;
|
||||
|
||||
const float length = 300;
|
||||
|
||||
Content.FadeIn(length, Easing.OutQuint);
|
||||
Content.MoveTo(new Vector2(0, 0), length, Easing.OutQuint);
|
||||
|
||||
sideFlashes.Delay(length).FadeIn(64, Easing.InQuint);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LogoSuspending(OsuLogo logo)
|
||||
{
|
||||
logo.FadeOut(300, Easing.InSine)
|
||||
.ScaleTo(0.2f, 300, Easing.InSine)
|
||||
.OnComplete(l => buttons.SetOsuLogo(null));
|
||||
}
|
||||
|
||||
private void beatmap_ValueChanged(WorkingBeatmap newValue)
|
||||
{
|
||||
if (!IsCurrentScreen)
|
||||
return;
|
||||
|
||||
background.Next();
|
||||
}
|
||||
|
||||
protected override void OnSuspending(Screen next)
|
||||
{
|
||||
base.OnSuspending(next);
|
||||
|
||||
const float length = 400;
|
||||
|
||||
buttons.State = MenuState.EnteringMode;
|
||||
|
||||
Content.FadeOut(length, Easing.InSine);
|
||||
Content.MoveTo(new Vector2(-800, 0), length, Easing.InSine);
|
||||
|
||||
sideFlashes.FadeOut(64, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void OnResuming(Screen last)
|
||||
{
|
||||
base.OnResuming(last);
|
||||
|
||||
background.Next();
|
||||
|
||||
//we may have consumed our preloaded instance, so let's make another.
|
||||
preloadSongSelect();
|
||||
}
|
||||
|
||||
protected override bool OnExiting(Screen next)
|
||||
{
|
||||
buttons.State = MenuState.Exit;
|
||||
Content.FadeOut(3000);
|
||||
return base.OnExiting(next);
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (!args.Repeat && state.Keyboard.ControlPressed && state.Keyboard.ShiftPressed && args.Key == Key.D)
|
||||
{
|
||||
Push(new Drawings());
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyDown(state, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,99 +1,99 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class MenuSideFlashes : BeatSyncedContainer
|
||||
{
|
||||
public override bool HandleKeyboardInput => false;
|
||||
public override bool HandleMouseInput => false;
|
||||
|
||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
private readonly Box leftBox;
|
||||
private readonly Box rightBox;
|
||||
|
||||
private const float amplitude_dead_zone = 0.25f;
|
||||
private const float alpha_multiplier = (1 - amplitude_dead_zone) / 0.55f;
|
||||
private const float kiai_multiplier = (1 - amplitude_dead_zone * 0.95f) / 0.8f;
|
||||
|
||||
private const int box_max_alpha = 200;
|
||||
private const double box_fade_in_time = 65;
|
||||
private const int box_width = 200;
|
||||
|
||||
public MenuSideFlashes()
|
||||
{
|
||||
EarlyActivationMilliseconds = box_fade_in_time;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
leftBox = new Box
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = box_width,
|
||||
Alpha = 0,
|
||||
Blending = BlendingMode.Additive,
|
||||
},
|
||||
rightBox = new Box
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = box_width,
|
||||
Alpha = 0,
|
||||
Blending = BlendingMode.Additive,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase game, OsuColour colours)
|
||||
{
|
||||
beatmap.BindTo(game.Beatmap);
|
||||
|
||||
// linear colour looks better in this case, so let's use it for now.
|
||||
Color4 gradientDark = colours.Blue.Opacity(0).ToLinear();
|
||||
Color4 gradientLight = colours.Blue.Opacity(0.3f).ToLinear();
|
||||
|
||||
leftBox.Colour = ColourInfo.GradientHorizontal(gradientLight, gradientDark);
|
||||
rightBox.Colour = ColourInfo.GradientHorizontal(gradientDark, gradientLight);
|
||||
}
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
if (beatIndex < 0)
|
||||
return;
|
||||
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 0 : beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
flash(leftBox, timingPoint.BeatLength, effectPoint.KiaiMode, amplitudes);
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 1 : beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
flash(rightBox, timingPoint.BeatLength, effectPoint.KiaiMode, amplitudes);
|
||||
}
|
||||
|
||||
private void flash(Drawable d, double beatLength, bool kiai, TrackAmplitudes amplitudes)
|
||||
{
|
||||
d.FadeTo(Math.Max(0, ((d.Equals(leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time)
|
||||
.Then()
|
||||
.FadeOut(beatLength, Easing.In);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class MenuSideFlashes : BeatSyncedContainer
|
||||
{
|
||||
public override bool HandleKeyboardInput => false;
|
||||
public override bool HandleMouseInput => false;
|
||||
|
||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
private readonly Box leftBox;
|
||||
private readonly Box rightBox;
|
||||
|
||||
private const float amplitude_dead_zone = 0.25f;
|
||||
private const float alpha_multiplier = (1 - amplitude_dead_zone) / 0.55f;
|
||||
private const float kiai_multiplier = (1 - amplitude_dead_zone * 0.95f) / 0.8f;
|
||||
|
||||
private const int box_max_alpha = 200;
|
||||
private const double box_fade_in_time = 65;
|
||||
private const int box_width = 200;
|
||||
|
||||
public MenuSideFlashes()
|
||||
{
|
||||
EarlyActivationMilliseconds = box_fade_in_time;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
leftBox = new Box
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = box_width,
|
||||
Alpha = 0,
|
||||
Blending = BlendingMode.Additive,
|
||||
},
|
||||
rightBox = new Box
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = box_width,
|
||||
Alpha = 0,
|
||||
Blending = BlendingMode.Additive,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase game, OsuColour colours)
|
||||
{
|
||||
beatmap.BindTo(game.Beatmap);
|
||||
|
||||
// linear colour looks better in this case, so let's use it for now.
|
||||
Color4 gradientDark = colours.Blue.Opacity(0).ToLinear();
|
||||
Color4 gradientLight = colours.Blue.Opacity(0.3f).ToLinear();
|
||||
|
||||
leftBox.Colour = ColourInfo.GradientHorizontal(gradientLight, gradientDark);
|
||||
rightBox.Colour = ColourInfo.GradientHorizontal(gradientDark, gradientLight);
|
||||
}
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
if (beatIndex < 0)
|
||||
return;
|
||||
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 0 : beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
flash(leftBox, timingPoint.BeatLength, effectPoint.KiaiMode, amplitudes);
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 1 : beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
flash(rightBox, timingPoint.BeatLength, effectPoint.KiaiMode, amplitudes);
|
||||
}
|
||||
|
||||
private void flash(Drawable d, double beatLength, bool kiai, TrackAmplitudes amplitudes)
|
||||
{
|
||||
d.FadeTo(Math.Max(0, ((d.Equals(leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time)
|
||||
.Then()
|
||||
.FadeOut(beatLength, Easing.In);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,383 +1,383 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
/// <summary>
|
||||
/// osu! logo and its attachments (pulsing, visualiser etc.)
|
||||
/// </summary>
|
||||
public class OsuLogo : BeatSyncedContainer
|
||||
{
|
||||
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;
|
||||
private readonly Container logoBeatContainer;
|
||||
private readonly Container logoAmplitudeContainer;
|
||||
private readonly Container logoHoverContainer;
|
||||
private readonly LogoVisualisation visualizer;
|
||||
|
||||
private readonly IntroSequence intro;
|
||||
|
||||
private SampleChannel sampleClick;
|
||||
private SampleChannel sampleBeat;
|
||||
|
||||
private readonly Container colourAndTriangles;
|
||||
|
||||
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;
|
||||
|
||||
public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X * 0.74f;
|
||||
|
||||
private readonly Sprite ripple;
|
||||
|
||||
private readonly Container rippleContainer;
|
||||
|
||||
public bool Triangles
|
||||
{
|
||||
set { colourAndTriangles.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); }
|
||||
}
|
||||
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => logoContainer.ReceiveMouseInputAt(screenSpacePos);
|
||||
|
||||
public bool Ripple
|
||||
{
|
||||
get { return rippleContainer.Alpha > 0; }
|
||||
set { rippleContainer.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); }
|
||||
}
|
||||
|
||||
private readonly Box flashLayer;
|
||||
|
||||
private readonly Container impactContainer;
|
||||
|
||||
private const float default_size = 480;
|
||||
|
||||
private const double early_activation = 60;
|
||||
|
||||
public OsuLogo()
|
||||
{
|
||||
// Required to make Schedule calls run in OsuScreen even when we are not visible.
|
||||
AlwaysPresent = true;
|
||||
|
||||
EarlyActivationMilliseconds = early_activation;
|
||||
|
||||
Size = new Vector2(default_size);
|
||||
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
intro = new IntroSequence
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
logoHoverContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoBounceContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
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,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
logoAmplitudeContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoBeatContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
visualizer = new LogoVisualisation
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Alpha = 0.5f,
|
||||
Size = new Vector2(0.96f)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.88f),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
colourAndTriangles = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuPink,
|
||||
},
|
||||
triangles = new Triangles
|
||||
{
|
||||
TriangleScale = 4,
|
||||
ColourLight = OsuColour.FromHex(@"ff7db7"),
|
||||
ColourDark = OsuColour.FromHex(@"de5b95"),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
}
|
||||
},
|
||||
flashLayer = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
logo = new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
}
|
||||
},
|
||||
impactContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
BorderColour = Color4.White,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BorderThickness = 10,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
void runnableAction()
|
||||
{
|
||||
if (waitForPrevious)
|
||||
this.DelayUntilTransformsFinished().Schedule(action);
|
||||
else
|
||||
{
|
||||
ClearTransforms();
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLoaded)
|
||||
runnableAction();
|
||||
else
|
||||
Schedule(runnableAction);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures, AudioManager audio)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
private int lastBeatIndex;
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||
|
||||
lastBeatIndex = beatIndex;
|
||||
|
||||
var beatLength = timingPoint.BeatLength;
|
||||
|
||||
float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum);
|
||||
|
||||
if (beatIndex < 0) return;
|
||||
|
||||
if (IsHovered)
|
||||
this.Delay(early_activation).Schedule(() => sampleBeat.Play());
|
||||
|
||||
logoBeatContainer
|
||||
.ScaleTo(1 - 0.02f * amplitudeAdjust, early_activation, Easing.Out)
|
||||
.Then()
|
||||
.ScaleTo(1, beatLength * 2, Easing.OutQuint);
|
||||
|
||||
ripple.ClearTransforms();
|
||||
ripple
|
||||
.ScaleTo(logoAmplitudeContainer.Scale)
|
||||
.ScaleTo(logoAmplitudeContainer.Scale * (1 + 0.04f * amplitudeAdjust), beatLength, Easing.OutQuint)
|
||||
.FadeTo(0.15f * amplitudeAdjust).FadeOut(beatLength, Easing.OutQuint);
|
||||
|
||||
if (effectPoint.KiaiMode && flashLayer.Alpha < 0.4f)
|
||||
{
|
||||
flashLayer.ClearTransforms();
|
||||
flashLayer
|
||||
.FadeTo(0.2f * amplitudeAdjust, early_activation, Easing.Out)
|
||||
.Then()
|
||||
.FadeOut(beatLength);
|
||||
|
||||
visualizer.ClearTransforms();
|
||||
visualizer
|
||||
.FadeTo(0.9f * amplitudeAdjust, early_activation, Easing.Out)
|
||||
.Then()
|
||||
.FadeTo(0.5f, beatLength);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayIntro()
|
||||
{
|
||||
const double length = 3150;
|
||||
const double fade = 200;
|
||||
|
||||
logoHoverContainer.FadeOut().Delay(length).FadeIn(fade);
|
||||
intro.Show();
|
||||
intro.Start(length);
|
||||
intro.Delay(length + fade).FadeOut();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
const float scale_adjust_cutoff = 0.4f;
|
||||
const float velocity_adjust_cutoff = 0.98f;
|
||||
const float paused_velocity = 0.5f;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HandleMouseInput => base.HandleMouseInput && Action != null && Alpha > 0.2f;
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
{
|
||||
logoBounceContainer.ScaleTo(0.9f, 1000, Easing.Out);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||
{
|
||||
logoBounceContainer.ScaleTo(1f, 500, Easing.OutElastic);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
if (Action?.Invoke() ?? true)
|
||||
sampleClick.Play();
|
||||
|
||||
flashLayer.ClearTransforms();
|
||||
flashLayer.Alpha = 0.4f;
|
||||
flashLayer.FadeOut(1500, Easing.OutExpo);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
logoHoverContainer.ScaleTo(1, 500, Easing.OutElastic);
|
||||
}
|
||||
|
||||
public void Impact()
|
||||
{
|
||||
impactContainer.FadeOutFromOne(250, Easing.In);
|
||||
impactContainer.ScaleTo(0.96f);
|
||||
impactContainer.ScaleTo(1.12f, 250);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
/// <summary>
|
||||
/// osu! logo and its attachments (pulsing, visualiser etc.)
|
||||
/// </summary>
|
||||
public class OsuLogo : BeatSyncedContainer
|
||||
{
|
||||
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;
|
||||
private readonly Container logoBeatContainer;
|
||||
private readonly Container logoAmplitudeContainer;
|
||||
private readonly Container logoHoverContainer;
|
||||
private readonly LogoVisualisation visualizer;
|
||||
|
||||
private readonly IntroSequence intro;
|
||||
|
||||
private SampleChannel sampleClick;
|
||||
private SampleChannel sampleBeat;
|
||||
|
||||
private readonly Container colourAndTriangles;
|
||||
|
||||
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;
|
||||
|
||||
public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X * 0.74f;
|
||||
|
||||
private readonly Sprite ripple;
|
||||
|
||||
private readonly Container rippleContainer;
|
||||
|
||||
public bool Triangles
|
||||
{
|
||||
set { colourAndTriangles.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); }
|
||||
}
|
||||
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => logoContainer.ReceiveMouseInputAt(screenSpacePos);
|
||||
|
||||
public bool Ripple
|
||||
{
|
||||
get { return rippleContainer.Alpha > 0; }
|
||||
set { rippleContainer.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); }
|
||||
}
|
||||
|
||||
private readonly Box flashLayer;
|
||||
|
||||
private readonly Container impactContainer;
|
||||
|
||||
private const float default_size = 480;
|
||||
|
||||
private const double early_activation = 60;
|
||||
|
||||
public OsuLogo()
|
||||
{
|
||||
// Required to make Schedule calls run in OsuScreen even when we are not visible.
|
||||
AlwaysPresent = true;
|
||||
|
||||
EarlyActivationMilliseconds = early_activation;
|
||||
|
||||
Size = new Vector2(default_size);
|
||||
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
intro = new IntroSequence
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
logoHoverContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoBounceContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
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,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
logoAmplitudeContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoBeatContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
visualizer = new LogoVisualisation
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Alpha = 0.5f,
|
||||
Size = new Vector2(0.96f)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.88f),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
colourAndTriangles = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuPink,
|
||||
},
|
||||
triangles = new Triangles
|
||||
{
|
||||
TriangleScale = 4,
|
||||
ColourLight = OsuColour.FromHex(@"ff7db7"),
|
||||
ColourDark = OsuColour.FromHex(@"de5b95"),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
}
|
||||
},
|
||||
flashLayer = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
logo = new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
}
|
||||
},
|
||||
impactContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
BorderColour = Color4.White,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BorderThickness = 10,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
void runnableAction()
|
||||
{
|
||||
if (waitForPrevious)
|
||||
this.DelayUntilTransformsFinished().Schedule(action);
|
||||
else
|
||||
{
|
||||
ClearTransforms();
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLoaded)
|
||||
runnableAction();
|
||||
else
|
||||
Schedule(runnableAction);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures, AudioManager audio)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
private int lastBeatIndex;
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||
|
||||
lastBeatIndex = beatIndex;
|
||||
|
||||
var beatLength = timingPoint.BeatLength;
|
||||
|
||||
float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum);
|
||||
|
||||
if (beatIndex < 0) return;
|
||||
|
||||
if (IsHovered)
|
||||
this.Delay(early_activation).Schedule(() => sampleBeat.Play());
|
||||
|
||||
logoBeatContainer
|
||||
.ScaleTo(1 - 0.02f * amplitudeAdjust, early_activation, Easing.Out)
|
||||
.Then()
|
||||
.ScaleTo(1, beatLength * 2, Easing.OutQuint);
|
||||
|
||||
ripple.ClearTransforms();
|
||||
ripple
|
||||
.ScaleTo(logoAmplitudeContainer.Scale)
|
||||
.ScaleTo(logoAmplitudeContainer.Scale * (1 + 0.04f * amplitudeAdjust), beatLength, Easing.OutQuint)
|
||||
.FadeTo(0.15f * amplitudeAdjust).FadeOut(beatLength, Easing.OutQuint);
|
||||
|
||||
if (effectPoint.KiaiMode && flashLayer.Alpha < 0.4f)
|
||||
{
|
||||
flashLayer.ClearTransforms();
|
||||
flashLayer
|
||||
.FadeTo(0.2f * amplitudeAdjust, early_activation, Easing.Out)
|
||||
.Then()
|
||||
.FadeOut(beatLength);
|
||||
|
||||
visualizer.ClearTransforms();
|
||||
visualizer
|
||||
.FadeTo(0.9f * amplitudeAdjust, early_activation, Easing.Out)
|
||||
.Then()
|
||||
.FadeTo(0.5f, beatLength);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayIntro()
|
||||
{
|
||||
const double length = 3150;
|
||||
const double fade = 200;
|
||||
|
||||
logoHoverContainer.FadeOut().Delay(length).FadeIn(fade);
|
||||
intro.Show();
|
||||
intro.Start(length);
|
||||
intro.Delay(length + fade).FadeOut();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
const float scale_adjust_cutoff = 0.4f;
|
||||
const float velocity_adjust_cutoff = 0.98f;
|
||||
const float paused_velocity = 0.5f;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HandleMouseInput => base.HandleMouseInput && Action != null && Alpha > 0.2f;
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
{
|
||||
logoBounceContainer.ScaleTo(0.9f, 1000, Easing.Out);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||
{
|
||||
logoBounceContainer.ScaleTo(1f, 500, Easing.OutElastic);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
if (Action?.Invoke() ?? true)
|
||||
sampleClick.Play();
|
||||
|
||||
flashLayer.ClearTransforms();
|
||||
flashLayer.Alpha = 0.4f;
|
||||
flashLayer.FadeOut(1500, Easing.OutExpo);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
logoHoverContainer.ScaleTo(1, 500, Easing.OutElastic);
|
||||
}
|
||||
|
||||
public void Impact()
|
||||
{
|
||||
impactContainer.FadeOutFromOne(250, Easing.In);
|
||||
impactContainer.ScaleTo(0.96f);
|
||||
impactContainer.ScaleTo(1.12f, 250);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user