diff --git a/osu.Desktop.VisualTests/Program.cs b/osu.Desktop.VisualTests/Program.cs index c4f5075ef9..a6205fe6ba 100644 --- a/osu.Desktop.VisualTests/Program.cs +++ b/osu.Desktop.VisualTests/Program.cs @@ -18,7 +18,7 @@ namespace osu.Desktop.VisualTests [STAThread] public static void Main(string[] args) { - using (BasicGameHost host = Host.GetSuitableHost(@"osu-visual-tests")) + using (BasicGameHost host = Host.GetSuitableHost(@"osu")) { Ruleset.Register(new OsuRuleset()); Ruleset.Register(new TaikoRuleset()); diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 59ef75a909..d6112d7024 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -42,14 +42,13 @@ namespace osu.Desktop.VisualTests.Tests { var h = new HitCircle { - StartTime = Clock.CurrentTime + 1000 + i * 80, + StartTime = Clock.CurrentTime + 600 + i * 80, Position = new Vector2((i - count / 2) * 14), }; DrawableHitCircle d = new DrawableHitCircle(h) { Anchor = Anchor.Centre, - Origin = Anchor.Centre, Depth = i, State = ArmedState.Hit, Judgement = new OsuJudgementInfo { Result = HitResult.Hit } diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index adfa2556a0..0e45d58774 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -41,7 +41,11 @@ namespace osu.Desktop.VisualTests.Tests protected override void Dispose(bool isDisposing) { if (oldDb != null) + { Dependencies.Cache(oldDb, true); + db = null; + } + base.Dispose(isDisposing); } diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 9e3ad1bbc8..b55d341100 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -29,19 +29,17 @@ namespace osu.Desktop.VisualTests.Tests [BackgroundDependencyLoader] private void load(BeatmapDatabase db) { - beatmap = db.GetWorkingBeatmap(db.Query().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault()); + var beatmapInfo = db.Query().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault(); + if (beatmapInfo != null) + beatmap = db.GetWorkingBeatmap(beatmapInfo); } public override void Reset() { base.Reset(); - //ensure we are at offset 0 - Clock = new FramedClock(); - - if (beatmap == null) + if (beatmap?.Track == null) { - var objects = new List(); int time = 1500; diff --git a/osu.Game.Modes.Osu/OsuScoreProcessor.cs b/osu.Game.Modes.Osu/OsuScoreProcessor.cs index 6cb14831f6..6059949fad 100644 --- a/osu.Game.Modes.Osu/OsuScoreProcessor.cs +++ b/osu.Game.Modes.Osu/OsuScoreProcessor.cs @@ -11,6 +11,7 @@ namespace osu.Game.Modes.Osu public OsuScoreProcessor(int hitObjectCount) : base(hitObjectCount) { + Health.Value = 1; } protected override void UpdateCalculations(JudgementInfo judgement) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs index e90829873f..f8cec43f14 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs @@ -18,7 +18,8 @@ namespace osu.Game.Beatmaps.Drawables [BackgroundDependencyLoader] private void load(OsuGameBase game) { - Texture = working.Background; + if (working.Background != null) + Texture = working.Background; } } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 9184607398..a898465610 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -30,6 +30,8 @@ namespace osu.Game.Beatmaps { if (background != null) return background; + if (BeatmapInfo.Metadata?.BackgroundFile == null) return null; + try { using (var reader = GetReader()) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 2f9a026b8f..d246b421a2 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -27,13 +27,13 @@ namespace osu.Game.Graphics.UserInterface private const float shear = 0.1f; - private static readonly Vector2 size_extended = new Vector2(140, 50); - private static readonly Vector2 size_retracted = new Vector2(100, 50); + public static readonly Vector2 SIZE_EXTENDED = new Vector2(140, 50); + public static readonly Vector2 SIZE_RETRACTED = new Vector2(100, 50); private AudioSample sampleClick; public BackButton() { - Size = size_retracted; + Size = SIZE_RETRACTED; } public override bool Contains(Vector2 screenSpacePos) => leftBox.Contains(screenSpacePos) || rightBox.Contains(screenSpacePos); @@ -42,7 +42,7 @@ namespace osu.Game.Graphics.UserInterface { icon.ClearTransformations(); - ResizeTo(size_extended, transform_time, EasingTypes.OutElastic); + ResizeTo(SIZE_EXTENDED, transform_time, EasingTypes.OutElastic); int duration = 0; //(int)(Game.Audio.BeatLength / 2); if (duration == 0) duration = pulse_length; @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.UserInterface { icon.ClearTransformations(); - ResizeTo(size_retracted, transform_time, EasingTypes.OutElastic); + ResizeTo(SIZE_RETRACTED, transform_time, EasingTypes.OutElastic); int duration = 0; //(int)(Game.Audio.BeatLength); if (duration == 0) duration = pulse_length * 2; diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index 6a21da9bce..e55001fd99 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -1,7 +1,6 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -9,10 +8,6 @@ using osu.Framework.Graphics.Transformations; using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using osu.Framework.Allocation; namespace osu.Game.Graphics.UserInterface { @@ -64,7 +59,6 @@ namespace osu.Game.Graphics.UserInterface } } - protected T prevCount; protected T count; /// @@ -78,7 +72,6 @@ namespace osu.Game.Graphics.UserInterface } set { - prevCount = count; count = value; if (IsLoaded) { diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 7ce71acf3e..f2dc7268ac 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -43,8 +43,8 @@ namespace osu.Game.Modes.Objects.Drawables state = value; UpdateState(state); - - Expire(); + if (IsLoaded) + Expire(); if (State == ArmedState.Hit) PlaySample(); @@ -56,8 +56,8 @@ namespace osu.Game.Modes.Objects.Drawables [BackgroundDependencyLoader] private void load(AudioManager audio) { - string hitType = (HitObject.Sample.Type == SampleType.None ? SampleType.Normal : HitObject.Sample.Type).ToString().ToLower(); - string sampleSet = HitObject.Sample.Set.ToString().ToLower(); + string hitType = ((HitObject.Sample?.Type ?? SampleType.None) == SampleType.None ? SampleType.Normal : HitObject.Sample.Type).ToString().ToLower(); + string sampleSet = (HitObject.Sample?.Set ?? SampleSet.Normal).ToString().ToLower(); sample = audio.Sample.Get($@"Gameplay/{sampleSet}-hit{hitType}"); } diff --git a/osu.Game/Modes/ScoreProcesssor.cs b/osu.Game/Modes/ScoreProcesssor.cs index 3c8d2f4d25..fb58aabe97 100644 --- a/osu.Game/Modes/ScoreProcesssor.cs +++ b/osu.Game/Modes/ScoreProcesssor.cs @@ -30,6 +30,22 @@ namespace osu.Game.Modes public readonly BindableInt Combo = new BindableInt(); + /// + /// Are we allowed to fail? + /// + protected bool CanFail => true; + + protected bool HasFailed { get; private set; } + + /// + /// Called when we reach a failing health of zero. + /// + public event Action Failed; + + /// + /// Keeps track of the highest combo ever achieved in this play. + /// This is handled automatically by ScoreProcessor. + /// public readonly BindableInt HighestCombo = new BindableInt(); public readonly List Judgements; @@ -51,6 +67,11 @@ namespace osu.Game.Modes UpdateCalculations(judgement); judgement.ComboAtHit = (ulong)Combo.Value; + if (Health.Value == Health.MinValue && !HasFailed) + { + HasFailed = true; + Failed?.Invoke(); + } } /// diff --git a/osu.Game/Modes/UI/HealthDisplay.cs b/osu.Game/Modes/UI/HealthDisplay.cs index 0645d54b50..f4f1cc37f9 100644 --- a/osu.Game/Modes/UI/HealthDisplay.cs +++ b/osu.Game/Modes/UI/HealthDisplay.cs @@ -14,6 +14,8 @@ namespace osu.Game.Modes.UI private Box background; private Box fill; + public BindableDouble Current = new BindableDouble() { MinValue = 0, MaxValue = 1 }; + public HealthDisplay() { Children = new Drawable[] @@ -30,13 +32,12 @@ namespace osu.Game.Modes.UI Scale = new Vector2(0, 1), }, }; + + Current.ValueChanged += current_ValueChanged; } - public double Current; - - public void Set(double value) + private void current_ValueChanged(object sender, EventArgs e) { - Current = value; fill.ScaleTo(new Vector2((float)Current, 1), 200, EasingTypes.OutQuint); } } diff --git a/osu.Game/Modes/UI/ScoreOverlay.cs b/osu.Game/Modes/UI/ScoreOverlay.cs index fbdd75b97d..144370c826 100644 --- a/osu.Game/Modes/UI/ScoreOverlay.cs +++ b/osu.Game/Modes/UI/ScoreOverlay.cs @@ -63,7 +63,7 @@ namespace osu.Game.Modes.UI processor.TotalScore.ValueChanged += delegate { ScoreCounter?.Set((ulong)processor.TotalScore.Value); }; processor.Accuracy.ValueChanged += delegate { AccuracyCounter?.Set((float)processor.Accuracy.Value); }; processor.Combo.ValueChanged += delegate { ComboCounter?.Set((ulong)processor.Combo.Value); }; - processor.Health.ValueChanged += delegate { HealthDisplay?.Set(processor.Health.Value); }; + HealthDisplay?.Current.Weld(processor.Health); } } } diff --git a/osu.Game/Overlays/Options/CheckBoxOption.cs b/osu.Game/Overlays/Options/CheckBoxOption.cs index 310d33580d..cc1af1e3c9 100644 --- a/osu.Game/Overlays/Options/CheckBoxOption.cs +++ b/osu.Game/Overlays/Options/CheckBoxOption.cs @@ -168,14 +168,17 @@ namespace osu.Game.Overlays.Options private void load(OsuColour colours) { Colour = idleColour = colours.Pink; + glowingColour = colours.PinkLighter; EdgeEffect = new EdgeEffect { - Colour = glowingColour = colours.PinkDarker, + Colour = colours.PinkDarker, Type = EdgeEffectType.Glow, Radius = 10, Roundness = 8, }; + + FadeGlowTo(0); } public bool Glowing diff --git a/osu.Game/Screens/OsuGameMode.cs b/osu.Game/Screens/OsuGameMode.cs index b5e45f2097..b938a450f8 100644 --- a/osu.Game/Screens/OsuGameMode.cs +++ b/osu.Game/Screens/OsuGameMode.cs @@ -130,7 +130,7 @@ namespace osu.Game.Screens { if (nextOsu != null) //We need to use MakeCurrent in case we are jumping up multiple game modes. - nextOsu.Background.MakeCurrent(); + nextOsu.Background?.MakeCurrent(); else Background.Exit(); } diff --git a/osu.Game/Screens/Play/FailDialog.cs b/osu.Game/Screens/Play/FailDialog.cs new file mode 100644 index 0000000000..c8718c1618 --- /dev/null +++ b/osu.Game/Screens/Play/FailDialog.cs @@ -0,0 +1,45 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.GameModes; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transformations; +using osu.Game.Modes; +using osu.Game.Screens.Backgrounds; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Screens.Play +{ + class FailDialog : OsuGameMode + { + protected override BackgroundMode CreateBackground() => new BackgroundModeBeatmap(Beatmap); + + private static readonly Vector2 BACKGROUND_BLUR = new Vector2(20); + + public FailDialog() + { + Add(new SpriteText + { + Text = "You failed!", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + TextSize = 50 + }); + } + + protected override void OnEntering(GameMode last) + { + base.OnEntering(last); + Background.Schedule(() => (Background as BackgroundModeBeatmap)?.BlurTo(BACKGROUND_BLUR, 1000)); + } + + protected override bool OnExiting(GameMode next) + { + Background.Schedule(() => Background.FadeColour(Color4.White, 500)); + return base.OnExiting(next); + } + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fe9345eca8..d6594dd2be 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -24,6 +24,7 @@ using osu.Game.Screens.Ranking; using osu.Game.Configuration; using osu.Framework.Configuration; using System; +using OpenTK.Graphics; namespace osu.Game.Screens.Play { @@ -31,7 +32,7 @@ namespace osu.Game.Screens.Play { public bool Autoplay; - protected override BackgroundMode CreateBackground() => null; + protected override BackgroundMode CreateBackground() => new BackgroundModeBeatmap(Beatmap); internal override bool ShowOverlays => false; @@ -96,8 +97,12 @@ namespace osu.Game.Screens.Play hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); + //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) hitRenderer.OnJudgement += scoreProcessor.AddJudgement; - hitRenderer.OnAllJudged += hitRenderer_OnAllJudged; + hitRenderer.OnAllJudged += onPass; + + //bind ScoreProcessor to ourselves (for a fail situation) + scoreProcessor.Failed += onFail; if (Autoplay) hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); @@ -132,7 +137,7 @@ namespace osu.Game.Screens.Play }); } - private void hitRenderer_OnAllJudged() + private void onPass() { Delay(1000); Schedule(delegate @@ -145,6 +150,19 @@ namespace osu.Game.Screens.Play }); } + private void onFail() + { + Content.FadeColour(Color4.Red, 500); + sourceClock.Stop(); + + Delay(500); + Schedule(delegate + { + ValidForResume = false; + Push(new FailDialog()); + }); + } + protected override void OnEntering(GameMode last) { base.OnEntering(last); @@ -167,50 +185,5 @@ namespace osu.Game.Screens.Play { Background?.FadeTo((100f - dimLevel) / 100, 800); } - - class PlayerInputManager : UserInputManager - { - public PlayerInputManager(BasicGameHost host) - : base(host) - { - } - - bool leftViaKeyboard; - bool rightViaKeyboard; - Bindable mouseDisabled; - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - mouseDisabled = config.GetBindable(OsuConfig.MouseDisableButtons) - ?? new Bindable(false); - } - - protected override void TransformState(InputState state) - { - base.TransformState(state); - - if (state.Keyboard != null) - { - leftViaKeyboard = state.Keyboard.Keys.Contains(Key.Z); - rightViaKeyboard = state.Keyboard.Keys.Contains(Key.X); - } - - MouseState mouse = (MouseState)state.Mouse; - if (state.Mouse != null) - { - if (mouseDisabled.Value) - { - mouse.ButtonStates.Find(s => s.Button == MouseButton.Left).State = false; - mouse.ButtonStates.Find(s => s.Button == MouseButton.Right).State = false; - } - - if (leftViaKeyboard) - mouse.ButtonStates.Find(s => s.Button == MouseButton.Left).State = true; - if (rightViaKeyboard) - mouse.ButtonStates.Find(s => s.Button == MouseButton.Right).State = true; - } - } - } } } \ No newline at end of file diff --git a/osu.Game/Screens/Play/PlayerInputManager.cs b/osu.Game/Screens/Play/PlayerInputManager.cs new file mode 100644 index 0000000000..b0da57ce0a --- /dev/null +++ b/osu.Game/Screens/Play/PlayerInputManager.cs @@ -0,0 +1,56 @@ +using OpenTK.Input; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Input; +using osu.Framework.Platform; +using osu.Game.Configuration; +using System; +using System.Linq; + +namespace osu.Game.Screens.Play +{ + class PlayerInputManager : UserInputManager + { + public PlayerInputManager(BasicGameHost host) + : base(host) + { + } + + bool leftViaKeyboard; + bool rightViaKeyboard; + Bindable mouseDisabled; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + mouseDisabled = config.GetBindable(OsuConfig.MouseDisableButtons) + ?? new Bindable(false); + } + + protected override void TransformState(InputState state) + { + base.TransformState(state); + + if (state.Keyboard != null) + { + leftViaKeyboard = state.Keyboard.Keys.Contains(Key.Z); + rightViaKeyboard = state.Keyboard.Keys.Contains(Key.X); + } + + var mouse = (Framework.Input.MouseState)state.Mouse; + if (state.Mouse != null) + { + if (mouseDisabled.Value) + { + mouse.ButtonStates.Find(s => s.Button == MouseButton.Left).State = false; + mouse.ButtonStates.Find(s => s.Button == MouseButton.Right).State = false; + } + + if (leftViaKeyboard) + mouse.ButtonStates.Find(s => s.Button == MouseButton.Left).State = true; + if (rightViaKeyboard) + mouse.ButtonStates.Find(s => s.Button == MouseButton.Right).State = true; + } + } + } +} diff --git a/osu.Game/Screens/Select/CarouselContainer.cs b/osu.Game/Screens/Select/CarouselContainer.cs index e1aceb2964..5337255bbf 100644 --- a/osu.Game/Screens/Select/CarouselContainer.cs +++ b/osu.Game/Screens/Select/CarouselContainer.cs @@ -1,22 +1,23 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using osu.Framework.Caching; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Transformations; -using osu.Game.Database; -using System; -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Lists; -using osu.Game.Beatmaps.Drawables; +using OpenTK; +using osu.Framework.Caching; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Transformations; +using osu.Game.Database; +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Lists; +using osu.Game.Beatmaps.Drawables; using osu.Framework.Timing; using osu.Framework.Input; using OpenTK.Input; using System.Collections; +using osu.Framework.MathUtils; namespace osu.Game.Screens.Select { @@ -297,6 +298,17 @@ namespace osu.Game.Screens.Select } return base.OnKeyDown(state, args); + } + + public void SelectRandom() + { + if (groups.Count < 1) + return; + BeatmapGroup group = groups[RNG.Next(groups.Count)]; + BeatmapPanel panel = group?.BeatmapPanels.First(); + if (panel == null) + return; + SelectGroup(group, panel); } public IEnumerator GetEnumerator() diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs new file mode 100644 index 0000000000..bb280f56c1 --- /dev/null +++ b/osu.Game/Screens/Select/Footer.cs @@ -0,0 +1,115 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transformations; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Menu; + +namespace osu.Game.Screens.Select +{ + public class Footer : Container + { + private Box modeLight; + + private const float play_song_select_button_width = 100; + private const float play_song_select_button_height = 50; + + public const int TRANSITION_LENGTH = 300; + + private const float padding = 80; + + public Action OnBack; + public Action OnStart; + + private FlowContainer buttons; + + public void AddButton(string text, Color4 colour, Action action) + { + var button = new FooterButton + { + Text = text, + Height = play_song_select_button_height, + Width = play_song_select_button_width, + SelectedColour = colour, + DeselectedColour = colour.Opacity(0.5f), + }; + + button.Hovered = () => updateModeLight(button); + button.HoverLost = () => updateModeLight(); + button.Action = action; + buttons.Add(button); + } + + private void updateModeLight(FooterButton button = null) + { + modeLight.FadeColour(button?.SelectedColour ?? Color4.Transparent, TRANSITION_LENGTH, EasingTypes.OutQuint); + } + + public Footer() + { + const float bottomToolHeight = 50; + + RelativeSizeAxes = Axes.X; + Height = bottomToolHeight; + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Size = Vector2.One, + Colour = Color4.Black.Opacity(0.5f), + }, + modeLight = new Box + { + RelativeSizeAxes = Axes.X, + Height = 3, + Position = new Vector2(0, -3), + }, + new OsuLogo() + { + Anchor = Anchor.BottomRight, + Scale = new Vector2(0.4f), + Position = new Vector2(-70, -25), + Action = () => OnStart?.Invoke() + }, + new BackButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Action = () => OnBack?.Invoke(), + }, + new FlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Position = new Vector2(BackButton.SIZE_EXTENDED.X + padding, 0), + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FlowDirection.HorizontalOnly, + Spacing = new Vector2(padding, 0), + Children = new Drawable[] + { + + buttons = new FlowContainer + { + Direction = FlowDirection.HorizontalOnly, + Spacing = new Vector2(0.2f, 0), + AutoSizeAxes = Axes.Both, + } + } + } + }; + + updateModeLight(); + } + } +} diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs new file mode 100644 index 0000000000..9d49e88716 --- /dev/null +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -0,0 +1,117 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using System; +using osu.Framework.Graphics.Transformations; + +namespace osu.Game.Screens.Select +{ + public class FooterButton : ClickableContainer + { + private static readonly Vector2 shearing = new Vector2(0.15f, 0); + + public string Text + { + get { return spriteText?.Text; } + set + { + if (spriteText != null) + spriteText.Text = value; + } + } + + private Color4 deselectedColour; + public Color4 DeselectedColour + { + get { return deselectedColour; } + set + { + deselectedColour = value; + if(light.Colour != SelectedColour) + light.Colour = value; + } + } + + private Color4 selectedColour; + public Color4 SelectedColour + { + get { return selectedColour; } + set + { + selectedColour = value; + box.Colour = selectedColour; + } + } + + private SpriteText spriteText; + private Box box; + private Box light; + + public FooterButton() + { + Children = new Drawable[] + { + box = new Box + { + RelativeSizeAxes = Axes.Both, + Shear = shearing, + EdgeSmoothness = new Vector2(2, 0), + Colour = Color4.White, + Alpha = 0, + }, + light = new Box + { + Shear = shearing, + Height = 4, + EdgeSmoothness = new Vector2(2, 0), + RelativeSizeAxes = Axes.X, + }, + spriteText = new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + + public Action Hovered; + public Action HoverLost; + + protected override bool OnHover(InputState state) + { + Hovered?.Invoke(); + light.ScaleTo(new Vector2(1, 2), Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); + light.FadeColour(SelectedColour, Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); + return true; + } + + protected override void OnHoverLost(InputState state) + { + HoverLost?.Invoke(); + light.ScaleTo(new Vector2(1, 1), Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); + light.FadeColour(DeselectedColour, Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); + box.FadeOut(Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + box.FadeTo(0.3f, Footer.TRANSITION_LENGTH * 2, EasingTypes.OutQuint); + return base.OnMouseDown(state, args); + } + + protected override bool OnClick(InputState state) + { + box.ClearTransformations(); + box.Alpha = 1; + box.FadeOut(Footer.TRANSITION_LENGTH * 3, EasingTypes.OutQuint); + return base.OnClick(state); + } + + } +} diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 5a54ac07b6..6c7936e95e 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -14,12 +14,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Modes; using osu.Game.Screens.Backgrounds; -using osu.Game.Graphics.UserInterface; using OpenTK; using OpenTK.Graphics; using osu.Game.Screens.Play; @@ -28,6 +26,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Graphics.Transformations; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; +using osu.Game.Graphics; using osu.Framework.Input; using OpenTK.Input; using osu.Game.Graphics; @@ -57,6 +56,8 @@ namespace osu.Game.Screens.Select private List beatmapGroups; + private Footer footer; + class WedgeBackground : Container { public WedgeBackground() @@ -154,41 +155,17 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, Margin = new MarginPadding { Top = 20, Right = 20, }, }, - new Container + footer = new Footer() { - RelativeSizeAxes = Axes.X, - Height = bottomToolHeight, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Size = Vector2.One, - Colour = Color4.Black.Opacity(0.5f), - }, - new BackButton - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - //RelativeSizeAxes = Axes.Y, - Action = () => Exit() - }, - new Button - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.Y, - Width = 100, - Text = "Play", - Colour = colours.Pink, - Action = start - }, - } + OnBack = Exit, + OnStart = start, } }; - + + footer.AddButton(@"mods", colours.Yellow, null); + footer.AddButton(@"random", colours.Green, carousel.SelectRandom); + footer.AddButton(@"options", colours.Blue, null); + if (osuGame != null) { playMode = osuGame.PlayMode; @@ -344,14 +321,10 @@ namespace osu.Game.Screens.Select //todo: change background in selectionChanged instead; support per-difficulty backgrounds. changeBackground(beatmap); - selectBeatmap(beatmap.BeatmapInfo); } - private void selectBeatmap(BeatmapInfo beatmap) - { - carousel.SelectBeatmap(beatmap); - } + private void selectBeatmap(BeatmapInfo beatmap) => carousel.SelectBeatmap(beatmap); /// /// selection has been changed as the result of interaction with the carousel. diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ed8df8b9f6..93091ff677 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -116,6 +116,8 @@ + + @@ -234,6 +236,8 @@ + + @@ -262,4 +266,4 @@ --> - \ No newline at end of file +