mirror of
https://github.com/ppy/osu.git
synced 2025-01-14 02:22:56 +08:00
Merge remote-tracking branch 'upstream/master' into login-updates
This commit is contained in:
commit
a6fd7f46c3
@ -1 +1 @@
|
||||
Subproject commit b10125a7334c07221503163a289522bddf6b793d
|
||||
Subproject commit 16a01c7381e3ee8ef6b4fe863ba9232deba04c29
|
@ -13,6 +13,7 @@ using OpenTK.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Transformations;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
|
27
osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs
Normal file
27
osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs
Normal file
@ -0,0 +1,27 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.GameModes.Testing;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseTwoLayerButton : TestCase
|
||||
{
|
||||
public override string Name => @"TwoLayerButton";
|
||||
public override string Description => @"Back and skip and what not";
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
Add(new BackButton());
|
||||
Add(new SkipButton());
|
||||
}
|
||||
}
|
||||
}
|
@ -183,6 +183,7 @@
|
||||
<Compile Include="Tests\TestCaseScoreCounter.cs" />
|
||||
<Compile Include="Tests\TestCaseTextAwesome.cs" />
|
||||
<Compile Include="Tests\TestCasePlaySongSelect.cs" />
|
||||
<Compile Include="Tests\TestCaseTwoLayerButton.cs" />
|
||||
<Compile Include="VisualTestGame.cs" />
|
||||
<Compile Include="Platform\TestStorage.cs" />
|
||||
<Compile Include="Tests\TestCaseOptions.cs" />
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using osu.Desktop.Beatmaps.IO;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Desktop;
|
||||
@ -26,16 +27,22 @@ namespace osu.Desktop
|
||||
{
|
||||
LegacyFilesystemReader.Register();
|
||||
|
||||
// Back up the cwd before DesktopGameHost changes it
|
||||
var cwd = Environment.CurrentDirectory;
|
||||
|
||||
using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true))
|
||||
{
|
||||
if (!host.IsPrimaryInstance)
|
||||
{
|
||||
var importer = new BeatmapImporter(host);
|
||||
|
||||
// Restore the cwd so relative paths given at the command line work correctly
|
||||
Directory.SetCurrentDirectory(cwd);
|
||||
foreach (var file in args)
|
||||
if (!importer.Import(file).Wait(1000))
|
||||
{
|
||||
Console.WriteLine(@"Importing {0}", file);
|
||||
if (!importer.Import(Path.GetFullPath(file)).Wait(3000))
|
||||
throw new TimeoutException(@"IPC took too long to send");
|
||||
Console.WriteLine(@"Sent import requests to running instance");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -7,6 +7,7 @@ using osu.Game.Modes.UI;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Modes.Osu.UI
|
||||
{
|
||||
|
@ -31,31 +31,32 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
|
||||
public List<BeatmapPanel> BeatmapPanels;
|
||||
|
||||
public BeatmapSetInfo BeatmapSet;
|
||||
|
||||
public BeatmapGroupState State
|
||||
{
|
||||
get { return state; }
|
||||
set
|
||||
{
|
||||
state = value;
|
||||
switch (state)
|
||||
switch (value)
|
||||
{
|
||||
case BeatmapGroupState.Expanded:
|
||||
foreach (BeatmapPanel panel in BeatmapPanels)
|
||||
panel.FadeIn(250);
|
||||
|
||||
Header.State = PanelSelectedState.Selected;
|
||||
if (SelectedPanel != null)
|
||||
SelectedPanel.State = PanelSelectedState.Selected;
|
||||
foreach (BeatmapPanel panel in BeatmapPanels)
|
||||
panel.State = panel == SelectedPanel ? PanelSelectedState.Selected : PanelSelectedState.NotSelected;
|
||||
break;
|
||||
case BeatmapGroupState.Collapsed:
|
||||
Header.State = PanelSelectedState.NotSelected;
|
||||
if (SelectedPanel != null)
|
||||
SelectedPanel.State = PanelSelectedState.NotSelected;
|
||||
|
||||
foreach (BeatmapPanel panel in BeatmapPanels)
|
||||
panel.FadeOut(300, EasingTypes.OutQuint);
|
||||
panel.State = PanelSelectedState.Hidden;
|
||||
break;
|
||||
case BeatmapGroupState.Hidden:
|
||||
Header.State = PanelSelectedState.Hidden;
|
||||
foreach (BeatmapPanel panel in BeatmapPanels)
|
||||
panel.State = PanelSelectedState.Hidden;
|
||||
break;
|
||||
}
|
||||
state = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,6 +76,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
RelativeSizeAxes = Axes.X,
|
||||
}).ToList();
|
||||
|
||||
BeatmapSet = set;
|
||||
Header.AddDifficultyIcons(BeatmapPanels);
|
||||
}
|
||||
|
||||
@ -111,5 +113,6 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
Collapsed,
|
||||
Expanded,
|
||||
Hidden,
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,11 @@
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
@ -17,7 +14,6 @@ using osu.Game.Graphics.UserInterface;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Modes;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
@ -33,6 +29,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
protected override void Selected()
|
||||
{
|
||||
base.Selected();
|
||||
|
||||
GainedSelection?.Invoke(this);
|
||||
|
||||
background.ColourInfo = ColourInfo.GradientVertical(
|
||||
|
@ -68,12 +68,6 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
FadeInFromZero(250);
|
||||
}
|
||||
|
||||
protected override void Selected()
|
||||
{
|
||||
base.Selected();
|
||||
|
@ -55,6 +55,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PanelSelectedState.Hidden:
|
||||
case PanelSelectedState.NotSelected:
|
||||
Deselected();
|
||||
break;
|
||||
@ -62,6 +63,11 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
Selected();
|
||||
break;
|
||||
}
|
||||
|
||||
if (state == PanelSelectedState.Hidden)
|
||||
FadeOut(300, EasingTypes.OutQuint);
|
||||
else
|
||||
FadeIn(250);
|
||||
}
|
||||
|
||||
private PanelSelectedState state = PanelSelectedState.NotSelected;
|
||||
@ -112,6 +118,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
|
||||
enum PanelSelectedState
|
||||
{
|
||||
Hidden,
|
||||
NotSelected,
|
||||
Selected
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
@ -10,6 +11,8 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics.Transformations;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Configuration;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Graphics.Cursor
|
||||
{
|
||||
@ -38,6 +41,8 @@ namespace osu.Game.Graphics.Cursor
|
||||
|
||||
class OsuCursor : Container
|
||||
{
|
||||
private BindableDouble cursorScale;
|
||||
private Sprite sprite;
|
||||
public OsuCursor()
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
@ -45,15 +50,24 @@ namespace osu.Game.Graphics.Cursor
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
private void load(TextureStore textures, OsuConfigManager config)
|
||||
{
|
||||
cursorScale = (BindableDouble)config.GetBindable<double>(OsuConfig.CursorSize);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Sprite
|
||||
sprite = new Sprite
|
||||
{
|
||||
Scale = new Vector2((float)cursorScale),
|
||||
Texture = textures.Get(@"Cursor/cursor")
|
||||
}
|
||||
};
|
||||
cursorScale.ValueChanged += scaleChanged;
|
||||
}
|
||||
|
||||
private void scaleChanged(object sender, EventArgs e)
|
||||
{
|
||||
sprite.Scale = new Vector2((float)cursorScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,163 +3,26 @@
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Transformations;
|
||||
using osu.Framework.Input;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
// Basic back button as it was on stable (kinda). No skinning possible for now
|
||||
public class BackButton : ClickableContainer
|
||||
public class BackButton : TwoLayerButton
|
||||
{
|
||||
private TextAwesome icon;
|
||||
|
||||
private Box leftBox;
|
||||
private Box rightBox;
|
||||
|
||||
private const double transform_time = 600;
|
||||
private const int pulse_length = 250;
|
||||
|
||||
private const float shear = 0.15f;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public override bool Contains(Vector2 screenSpacePos) => leftBox.Contains(screenSpacePos) || rightBox.Contains(screenSpacePos);
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
icon.ClearTransformations();
|
||||
|
||||
ResizeTo(SIZE_EXTENDED, transform_time, EasingTypes.OutElastic);
|
||||
|
||||
int duration = 0; //(int)(Game.Audio.BeatLength / 2);
|
||||
if (duration == 0) duration = pulse_length;
|
||||
|
||||
double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration;
|
||||
double startTime = Time.Current + offset;
|
||||
|
||||
// basic pulse
|
||||
icon.Transforms.Add(new TransformScale
|
||||
{
|
||||
StartValue = new Vector2(1.1f),
|
||||
EndValue = Vector2.One,
|
||||
StartTime = startTime,
|
||||
EndTime = startTime + duration,
|
||||
Easing = EasingTypes.Out,
|
||||
LoopCount = -1,
|
||||
LoopDelay = duration
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
icon.ClearTransformations();
|
||||
|
||||
ResizeTo(SIZE_RETRACTED, transform_time, EasingTypes.OutElastic);
|
||||
|
||||
int duration = 0; //(int)(Game.Audio.BeatLength);
|
||||
if (duration == 0) duration = pulse_length * 2;
|
||||
|
||||
double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration;
|
||||
double startTime = Time.Current + offset;
|
||||
|
||||
// slow pulse
|
||||
icon.Transforms.Add(new TransformScale
|
||||
{
|
||||
StartValue = new Vector2(1.1f),
|
||||
EndValue = Vector2.One,
|
||||
StartTime = startTime,
|
||||
EndTime = startTime + duration,
|
||||
Easing = EasingTypes.Out,
|
||||
LoopCount = -1,
|
||||
LoopDelay = duration
|
||||
});
|
||||
Text = @"Back";
|
||||
Icon = FontAwesome.fa_osu_left_o;
|
||||
Anchor = Anchor.BottomLeft;
|
||||
Origin = Anchor.BottomLeft;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, OsuColour colours)
|
||||
{
|
||||
sampleClick = audio.Sample.Get(@"Menu/menuback");
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.4f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
leftBox = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colours.PinkDark,
|
||||
Shear = new Vector2(shear, 0),
|
||||
},
|
||||
icon = new TextAwesome
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
TextSize = 25,
|
||||
Icon = FontAwesome.fa_osu_left_o
|
||||
},
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.6f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
rightBox = new Box
|
||||
{
|
||||
Colour = colours.Pink,
|
||||
Origin = Anchor.TopLeft,
|
||||
Anchor = Anchor.TopLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Shear = new Vector2(shear, 0),
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Text = @"Back",
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
var flash = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Shear = new Vector2(shear, 0),
|
||||
Colour = Color4.White.Opacity(0.5f),
|
||||
};
|
||||
Add(flash);
|
||||
|
||||
flash.FadeOutFromOne(200);
|
||||
flash.Expire();
|
||||
|
||||
sampleClick.Play();
|
||||
|
||||
return base.OnClick(state);
|
||||
ActivationSound = audio.Sample.Get(@"Menu/menuback");
|
||||
Colour = colours.Pink;
|
||||
HoverColour = colours.PinkDark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
237
osu.Game/Graphics/UserInterface/TwoLayerButton.cs
Normal file
237
osu.Game/Graphics/UserInterface/TwoLayerButton.cs
Normal file
@ -0,0 +1,237 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Transformations;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
public class TwoLayerButton : ClickableContainer
|
||||
{
|
||||
private TextAwesome icon;
|
||||
|
||||
public Box IconLayer;
|
||||
public Box TextLayer;
|
||||
|
||||
private const int transform_time = 600;
|
||||
private const int pulse_length = 250;
|
||||
|
||||
private const float shear = 0.1f;
|
||||
|
||||
public static readonly Vector2 SIZE_EXTENDED = new Vector2(140, 50);
|
||||
public static readonly Vector2 SIZE_RETRACTED = new Vector2(100, 50);
|
||||
public AudioSample ActivationSound;
|
||||
private SpriteText text;
|
||||
|
||||
public Color4 HoverColour;
|
||||
private Container c1;
|
||||
private Container c2;
|
||||
|
||||
public Color4 Colour
|
||||
{
|
||||
set
|
||||
{
|
||||
TextLayer.Colour = value;
|
||||
IconLayer.Colour = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Anchor Origin
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.Origin;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
base.Origin = value;
|
||||
c1.Origin = c1.Anchor = (value & Anchor.x2) > 0 ? Anchor.TopLeft : Anchor.TopRight;
|
||||
c2.Origin = c2.Anchor = (value & Anchor.x2) > 0 ? Anchor.TopRight : Anchor.TopLeft;
|
||||
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Right = (value & Anchor.x2) > 0 ? -SIZE_RETRACTED.X * shear * 0.5f : 0
|
||||
};
|
||||
|
||||
c1.Depth = (value & Anchor.x2) > 0 ? 0 : 1;
|
||||
c2.Depth = (value & Anchor.x2) > 0 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public TwoLayerButton()
|
||||
{
|
||||
Size = SIZE_RETRACTED;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
c2 = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.4f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container {
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Shear = new Vector2(shear, 0),
|
||||
Masking = true,
|
||||
EdgeEffect = new EdgeEffect {
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.Black.Opacity(0.2f),
|
||||
Offset = new Vector2(2, 0),
|
||||
Radius = 2,
|
||||
},
|
||||
Children = new [] {
|
||||
IconLayer = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
},
|
||||
}
|
||||
},
|
||||
icon = new TextAwesome
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
TextSize = 25,
|
||||
},
|
||||
}
|
||||
},
|
||||
c1 = new Container
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.6f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container {
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Shear = new Vector2(shear, 0),
|
||||
Masking = true,
|
||||
EdgeEffect = new EdgeEffect {
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.Black.Opacity(0.2f),
|
||||
Offset = new Vector2(2, 0),
|
||||
Radius = 2,
|
||||
},
|
||||
Children = new [] {
|
||||
TextLayer = new Box
|
||||
{
|
||||
Origin = Anchor.TopLeft,
|
||||
Anchor = Anchor.TopLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
},
|
||||
}
|
||||
},
|
||||
text = new SpriteText
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public FontAwesome Icon
|
||||
{
|
||||
set
|
||||
{
|
||||
icon.Icon = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
set
|
||||
{
|
||||
text.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Contains(Vector2 screenSpacePos) => IconLayer.Contains(screenSpacePos) || TextLayer.Contains(screenSpacePos);
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
icon.ClearTransformations();
|
||||
|
||||
ResizeTo(SIZE_EXTENDED, transform_time, EasingTypes.OutElastic);
|
||||
|
||||
int duration = 0; //(int)(Game.Audio.BeatLength / 2);
|
||||
if (duration == 0) duration = pulse_length;
|
||||
|
||||
IconLayer.FadeColour(HoverColour, transform_time, EasingTypes.OutElastic);
|
||||
|
||||
double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration;
|
||||
double startTime = Time.Current + offset;
|
||||
|
||||
// basic pulse
|
||||
icon.Transforms.Add(new TransformScale
|
||||
{
|
||||
StartValue = new Vector2(1.1f),
|
||||
EndValue = Vector2.One,
|
||||
StartTime = startTime,
|
||||
EndTime = startTime + duration,
|
||||
Easing = EasingTypes.Out,
|
||||
LoopCount = -1,
|
||||
LoopDelay = duration
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
icon.ClearTransformations();
|
||||
|
||||
ResizeTo(SIZE_RETRACTED, transform_time, EasingTypes.OutElastic);
|
||||
|
||||
IconLayer.FadeColour(TextLayer.Colour, transform_time, EasingTypes.OutElastic);
|
||||
|
||||
int duration = 0; //(int)(Game.Audio.BeatLength);
|
||||
if (duration == 0) duration = pulse_length * 2;
|
||||
|
||||
double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration;
|
||||
double startTime = Time.Current + offset;
|
||||
|
||||
// slow pulse
|
||||
icon.Transforms.Add(new TransformScale
|
||||
{
|
||||
StartValue = new Vector2(1.1f),
|
||||
EndValue = Vector2.One,
|
||||
StartTime = startTime,
|
||||
EndTime = startTime + duration,
|
||||
Easing = EasingTypes.Out,
|
||||
LoopCount = -1,
|
||||
LoopDelay = duration
|
||||
});
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
var flash = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Shear = new Vector2(shear, 0),
|
||||
Colour = Color4.White.Opacity(0.5f),
|
||||
};
|
||||
Add(flash);
|
||||
|
||||
flash.Alpha = 1;
|
||||
flash.FadeOut(500, EasingTypes.OutQuint);
|
||||
flash.Expire();
|
||||
|
||||
ActivationSound.Play();
|
||||
|
||||
return base.OnClick(state);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Modes.Objects;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Modes.UI
|
||||
{
|
||||
|
@ -1,212 +1,212 @@
|
||||
using System;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using System;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Transformations;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace osu.Game.Overlays.Pause
|
||||
{
|
||||
public class PauseOverlay : OverlayContainer
|
||||
{
|
||||
private const int transition_duration = 200;
|
||||
private const int button_height = 70;
|
||||
private const float background_alpha = 0.75f;
|
||||
|
||||
public Action OnResume;
|
||||
public Action OnRetry;
|
||||
public Action OnQuit;
|
||||
|
||||
public int Retries
|
||||
{
|
||||
set
|
||||
{
|
||||
namespace osu.Game.Overlays.Pause
|
||||
{
|
||||
public class PauseOverlay : OverlayContainer
|
||||
{
|
||||
private const int transition_duration = 200;
|
||||
private const int button_height = 70;
|
||||
private const float background_alpha = 0.75f;
|
||||
|
||||
public Action OnResume;
|
||||
public Action OnRetry;
|
||||
public Action OnQuit;
|
||||
|
||||
public int Retries
|
||||
{
|
||||
set
|
||||
{
|
||||
if (retryCounterContainer != null)
|
||||
{
|
||||
// "You've retried 1,065 times in this session"
|
||||
// "You've retried 1 time in this session"
|
||||
// "You've retried 1 time in this session"
|
||||
|
||||
retryCounterContainer.Children = new Drawable[]
|
||||
{
|
||||
new SpriteText
|
||||
{
|
||||
Text = "You've retried ",
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f),
|
||||
TextSize = 18
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = String.Format("{0:n0}", value),
|
||||
Font = @"Exo2.0-Bold",
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f),
|
||||
TextSize = 18
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = $" time{((value == 1) ? "" : "s")} in this session",
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f),
|
||||
TextSize = 18
|
||||
{
|
||||
new SpriteText
|
||||
{
|
||||
Text = "You've retried ",
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f),
|
||||
TextSize = 18
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = String.Format("{0:n0}", value),
|
||||
Font = @"Exo2.0-Bold",
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f),
|
||||
TextSize = 18
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = $" time{((value == 1) ? "" : "s")} in this session",
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f),
|
||||
TextSize = 18
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private FlowContainer retryCounterContainer;
|
||||
|
||||
public override bool Contains(Vector2 screenSpacePos) => true;
|
||||
public override bool HandleInput => State == Visibility.Visible;
|
||||
|
||||
protected override void PopIn() => FadeIn(transition_duration, EasingTypes.In);
|
||||
protected override void PopOut() => FadeOut(transition_duration, EasingTypes.In);
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Key == Key.Escape)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private FlowContainer retryCounterContainer;
|
||||
|
||||
public override bool Contains(Vector2 screenSpacePos) => true;
|
||||
public override bool HandleInput => State == Visibility.Visible;
|
||||
|
||||
protected override void PopIn() => FadeIn(transition_duration, EasingTypes.In);
|
||||
protected override void PopOut() => FadeOut(transition_duration, EasingTypes.In);
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Key == Key.Escape)
|
||||
{
|
||||
if (State == Visibility.Hidden) return false;
|
||||
resume();
|
||||
return true;
|
||||
}
|
||||
return base.OnKeyDown(state, args);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
return true;
|
||||
}
|
||||
return base.OnKeyDown(state, args);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
Alpha = background_alpha,
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Spacing = new Vector2(0f, 50f),
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Spacing = new Vector2(0f, 20f),
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SpriteText
|
||||
{
|
||||
Text = @"paused",
|
||||
Font = @"Exo2.0-Medium",
|
||||
Spacing = new Vector2(5, 0),
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
TextSize = 30,
|
||||
Colour = colours.Yellow,
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f)
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = @"you're not going to do what i think you're going to do, are ya?",
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f)
|
||||
}
|
||||
}
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Masking = true,
|
||||
EdgeEffect = new EdgeEffect
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.Black.Opacity(0.6f),
|
||||
Radius = 50
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ResumeButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Height = button_height,
|
||||
Action = resume
|
||||
},
|
||||
new RetryButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Height = button_height,
|
||||
Action = delegate
|
||||
{
|
||||
OnRetry?.Invoke();
|
||||
Hide();
|
||||
}
|
||||
},
|
||||
new QuitButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Height = button_height,
|
||||
Action = delegate
|
||||
{
|
||||
OnQuit?.Invoke();
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
retryCounterContainer = new FlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre
|
||||
}
|
||||
}
|
||||
},
|
||||
new PauseProgressBar
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Width = 1f
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
Alpha = background_alpha,
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Spacing = new Vector2(0f, 50f),
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Spacing = new Vector2(0f, 20f),
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SpriteText
|
||||
{
|
||||
Text = @"paused",
|
||||
Font = @"Exo2.0-Medium",
|
||||
Spacing = new Vector2(5, 0),
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
TextSize = 30,
|
||||
Colour = colours.Yellow,
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f)
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = @"you're not going to do what i think you're going to do, are ya?",
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Shadow = true,
|
||||
ShadowColour = new Color4(0, 0, 0, 0.25f)
|
||||
}
|
||||
}
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Masking = true,
|
||||
EdgeEffect = new EdgeEffect
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.Black.Opacity(0.6f),
|
||||
Radius = 50
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ResumeButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Height = button_height,
|
||||
Action = resume
|
||||
},
|
||||
new RetryButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Height = button_height,
|
||||
Action = delegate
|
||||
{
|
||||
OnRetry?.Invoke();
|
||||
Hide();
|
||||
}
|
||||
},
|
||||
new QuitButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Height = button_height,
|
||||
Action = delegate
|
||||
{
|
||||
OnQuit?.Invoke();
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
retryCounterContainer = new FlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre
|
||||
}
|
||||
}
|
||||
},
|
||||
new PauseProgressBar
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Width = 1f
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
Retries = 0;
|
||||
}
|
||||
|
||||
private void resume()
|
||||
}
|
||||
|
||||
private void resume()
|
||||
{
|
||||
OnResume?.Invoke();
|
||||
Hide();
|
||||
}
|
||||
OnResume?.Invoke();
|
||||
Hide();
|
||||
}
|
||||
|
||||
public PauseOverlay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,17 +22,19 @@ namespace osu.Game.Screens.Backgrounds
|
||||
{
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (beatmap == value)
|
||||
if (beatmap == value && beatmap != null)
|
||||
return;
|
||||
|
||||
beatmap = value;
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
Background newBackground = new BeatmapBackground(beatmap);
|
||||
Background newBackground;
|
||||
if (beatmap == null)
|
||||
newBackground = new Background(@"Backgrounds/bg1");
|
||||
else
|
||||
newBackground = new BeatmapBackground(beatmap);
|
||||
|
||||
newBackground.Preload(Game, delegate
|
||||
{
|
||||
@ -84,7 +86,6 @@ namespace osu.Game.Screens.Backgrounds
|
||||
{
|
||||
Sprite.Texture = beatmap.Background;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
Action = onOsuLogo,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre
|
||||
Anchor = Anchor.Centre,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,16 +1,15 @@
|
||||
//Copyright (c) 2007-2016 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 osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public abstract class KeyCounter : Container
|
||||
{
|
@ -2,11 +2,11 @@
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class KeyCounterCollection : FlowContainer<KeyCounter>
|
||||
{
|
@ -1,11 +1,11 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class KeyCounterKeyboard : KeyCounter
|
||||
{
|
@ -1,12 +1,12 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class KeyCounterMouse : KeyCounter
|
||||
{
|
@ -1,22 +1,16 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Modes;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
using OpenTK.Input;
|
||||
using MouseState = osu.Framework.Input.MouseState;
|
||||
using OpenTK;
|
||||
using osu.Framework.GameModes;
|
||||
using osu.Game.Modes.UI;
|
||||
@ -25,6 +19,8 @@ using osu.Game.Configuration;
|
||||
using osu.Game.Overlays.Pause;
|
||||
using osu.Framework.Configuration;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
@ -65,6 +61,7 @@ namespace osu.Game.Screens.Play
|
||||
private ScoreProcessor scoreProcessor;
|
||||
private HitRenderer hitRenderer;
|
||||
private Bindable<int> dimLevel;
|
||||
private SkipButton skipButton;
|
||||
|
||||
private ScoreOverlay scoreOverlay;
|
||||
private PauseOverlay pauseOverlay;
|
||||
@ -149,6 +146,7 @@ namespace osu.Game.Screens.Play
|
||||
Children = new Drawable[]
|
||||
{
|
||||
hitRenderer,
|
||||
skipButton = new SkipButton { Alpha = 0 },
|
||||
}
|
||||
},
|
||||
scoreOverlay,
|
||||
@ -156,6 +154,33 @@ namespace osu.Game.Screens.Play
|
||||
};
|
||||
}
|
||||
|
||||
private void initializeSkipButton()
|
||||
{
|
||||
const double skip_required_cutoff = 3000;
|
||||
const double fade_time = 300;
|
||||
|
||||
double firstHitObject = Beatmap.Beatmap.HitObjects.First().StartTime;
|
||||
|
||||
if (firstHitObject < skip_required_cutoff)
|
||||
{
|
||||
skipButton.Alpha = 0;
|
||||
skipButton.Expire();
|
||||
return;
|
||||
}
|
||||
|
||||
skipButton.FadeInFromZero(fade_time);
|
||||
|
||||
skipButton.Action = () =>
|
||||
{
|
||||
sourceClock.Seek(firstHitObject - skip_required_cutoff - fade_time);
|
||||
skipButton.Action = null;
|
||||
};
|
||||
|
||||
skipButton.Delay(firstHitObject - skip_required_cutoff - fade_time);
|
||||
skipButton.FadeOut(fade_time);
|
||||
skipButton.Expire();
|
||||
}
|
||||
|
||||
public void Pause(bool force = false)
|
||||
{
|
||||
if (canPause || force)
|
||||
@ -220,6 +245,7 @@ namespace osu.Game.Screens.Play
|
||||
Schedule(() =>
|
||||
{
|
||||
sourceClock.Start();
|
||||
initializeSkipButton();
|
||||
});
|
||||
}
|
||||
|
||||
@ -252,7 +278,7 @@ namespace osu.Game.Screens.Play
|
||||
protected override void OnEntering(GameMode last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
|
||||
|
||||
(Background as BackgroundModeBeatmap)?.BlurTo(Vector2.Zero, 1000);
|
||||
Background?.FadeTo((100f- dimLevel)/100, 1000);
|
||||
|
||||
|
32
osu.Game/Screens/Play/SkipButton.cs
Normal file
32
osu.Game/Screens/Play/SkipButton.cs
Normal file
@ -0,0 +1,32 @@
|
||||
//Copyright (c) 2007-2016 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.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class SkipButton : TwoLayerButton
|
||||
{
|
||||
private readonly double skipDestination;
|
||||
|
||||
public SkipButton()
|
||||
{
|
||||
Text = @"Skip";
|
||||
Icon = FontAwesome.fa_osu_right_o;
|
||||
Anchor = Anchor.BottomRight;
|
||||
Origin = Anchor.BottomRight;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, OsuColour colours)
|
||||
{
|
||||
ActivationSound = audio.Sample.Get(@"Menu/menuhit");
|
||||
Colour = colours.Yellow;
|
||||
HoverColour = colours.YellowDark;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +1,27 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//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 osu.Framework.MathUtils;
|
||||
using System.Collections;
|
||||
using osu.Framework.MathUtils;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
class CarouselContainer : ScrollContainer
|
||||
class CarouselContainer : ScrollContainer, IEnumerable<BeatmapGroup>
|
||||
{
|
||||
private Container<Panel> scrollableContent;
|
||||
private List<BeatmapGroup> groups = new List<BeatmapGroup>();
|
||||
@ -28,29 +29,29 @@ namespace osu.Game.Screens.Select
|
||||
public BeatmapGroup SelectedGroup { get; private set; }
|
||||
public BeatmapPanel SelectedPanel { get; private set; }
|
||||
|
||||
private List<float> yPositions = new List<float>();
|
||||
private CarouselLifetimeList<Panel> Lifetime;
|
||||
|
||||
public CarouselContainer()
|
||||
{
|
||||
DistanceDecayJump = 0.01;
|
||||
|
||||
Add(scrollableContent = new Container<Panel>(Lifetime = new CarouselLifetimeList<Panel>(DepthComparer))
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
});
|
||||
}
|
||||
|
||||
internal class CarouselLifetimeList<T> : LifetimeList<Panel>
|
||||
{
|
||||
public CarouselLifetimeList(IComparer<Panel> comparer)
|
||||
: base(comparer)
|
||||
{
|
||||
}
|
||||
|
||||
public int StartIndex;
|
||||
private List<float> yPositions = new List<float>();
|
||||
private CarouselLifetimeList<Panel> Lifetime;
|
||||
|
||||
public CarouselContainer()
|
||||
{
|
||||
DistanceDecayJump = 0.01;
|
||||
|
||||
Add(scrollableContent = new Container<Panel>(Lifetime = new CarouselLifetimeList<Panel>(DepthComparer))
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
});
|
||||
}
|
||||
|
||||
internal class CarouselLifetimeList<T> : LifetimeList<Panel>
|
||||
{
|
||||
public CarouselLifetimeList(IComparer<Panel> comparer)
|
||||
: base(comparer)
|
||||
{
|
||||
}
|
||||
|
||||
public int StartIndex;
|
||||
public int EndIndex;
|
||||
|
||||
|
||||
public override bool Update(FrameTimeInfo time)
|
||||
{
|
||||
bool anyAliveChanged = false;
|
||||
@ -76,9 +77,9 @@ namespace osu.Game.Screens.Select
|
||||
}
|
||||
|
||||
return anyAliveChanged;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void AddGroup(BeatmapGroup group)
|
||||
{
|
||||
group.State = BeatmapGroupState.Collapsed;
|
||||
@ -96,10 +97,10 @@ namespace osu.Game.Screens.Select
|
||||
computeYPositions();
|
||||
}
|
||||
|
||||
private void movePanel(Panel panel, bool advance, ref float currentY)
|
||||
private void movePanel(Panel panel, bool advance, bool animated, ref float currentY)
|
||||
{
|
||||
yPositions.Add(currentY);
|
||||
panel.MoveToY(currentY, 750, EasingTypes.OutExpo);
|
||||
panel.MoveToY(currentY, animated && (panel.IsOnScreen || panel.State != PanelSelectedState.Hidden) ? 750 : 0, EasingTypes.OutExpo);
|
||||
|
||||
if (advance)
|
||||
currentY += panel.DrawHeight + 5;
|
||||
@ -109,7 +110,7 @@ namespace osu.Game.Screens.Select
|
||||
/// Computes the target Y positions for every panel in the carousel.
|
||||
/// </summary>
|
||||
/// <returns>The Y position of the currently selected panel.</returns>
|
||||
private float computeYPositions()
|
||||
private float computeYPositions(bool animated = true)
|
||||
{
|
||||
yPositions.Clear();
|
||||
|
||||
@ -118,7 +119,7 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
foreach (BeatmapGroup group in groups)
|
||||
{
|
||||
movePanel(group.Header, true, ref currentY);
|
||||
movePanel(group.Header, group.State != BeatmapGroupState.Hidden, animated, ref currentY);
|
||||
|
||||
if (group.State == BeatmapGroupState.Expanded)
|
||||
{
|
||||
@ -136,7 +137,7 @@ namespace osu.Game.Screens.Select
|
||||
if (panel.Alpha == 0)
|
||||
panel.MoveToY(headerY);
|
||||
|
||||
movePanel(panel, true, ref currentY);
|
||||
movePanel(panel, true, animated, ref currentY);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -146,7 +147,7 @@ namespace osu.Game.Screens.Select
|
||||
foreach (BeatmapPanel panel in group.BeatmapPanels)
|
||||
{
|
||||
panel.MoveToX(0, 500, EasingTypes.OutExpo);
|
||||
movePanel(panel, false, ref currentY);
|
||||
movePanel(panel, false, animated, ref currentY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,30 +158,30 @@ namespace osu.Game.Screens.Select
|
||||
return selectedY;
|
||||
}
|
||||
|
||||
public void SelectBeatmap(BeatmapInfo beatmap)
|
||||
public void SelectBeatmap(BeatmapInfo beatmap, bool animated = true)
|
||||
{
|
||||
foreach (BeatmapGroup group in groups)
|
||||
{
|
||||
var panel = group.BeatmapPanels.FirstOrDefault(p => p.Beatmap.Equals(beatmap));
|
||||
if (panel != null)
|
||||
{
|
||||
SelectGroup(group, panel);
|
||||
SelectGroup(group, panel, animated);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectGroup(BeatmapGroup group, BeatmapPanel panel)
|
||||
public void SelectGroup(BeatmapGroup group, BeatmapPanel panel, bool animated = true)
|
||||
{
|
||||
if (SelectedGroup != null && SelectedGroup != group)
|
||||
if (SelectedGroup != null && SelectedGroup != group && SelectedGroup.State != BeatmapGroupState.Hidden)
|
||||
SelectedGroup.State = BeatmapGroupState.Collapsed;
|
||||
|
||||
SelectedGroup = group;
|
||||
panel.State = PanelSelectedState.Selected;
|
||||
SelectedPanel = panel;
|
||||
|
||||
float selectedY = computeYPositions();
|
||||
ScrollTo(selectedY);
|
||||
float selectedY = computeYPositions(animated);
|
||||
ScrollTo(selectedY, animated);
|
||||
}
|
||||
|
||||
private static float offsetX(float dist, float halfHeight)
|
||||
@ -201,7 +202,9 @@ namespace osu.Game.Screens.Select
|
||||
/// <param name="halfHeight">Half the draw height of the carousel container.</param>
|
||||
private void updatePanel(Panel p, float halfHeight)
|
||||
{
|
||||
float panelDrawY = p.Position.Y - Current + p.DrawHeight / 2;
|
||||
var height = p.IsVisible ? p.DrawHeight : 0;
|
||||
|
||||
float panelDrawY = p.Position.Y - Current + height / 2;
|
||||
float dist = Math.Abs(1f - panelDrawY / halfHeight);
|
||||
|
||||
// Setting the origin position serves as an additive position on top of potential
|
||||
@ -223,11 +226,11 @@ namespace osu.Game.Screens.Select
|
||||
float drawHeight = DrawHeight;
|
||||
float halfHeight = drawHeight / 2;
|
||||
|
||||
foreach (Panel p in Lifetime.AliveItems)
|
||||
{
|
||||
float panelPosY = p.Position.Y;
|
||||
p.IsOnScreen = panelPosY >= Current - p.DrawHeight && panelPosY <= Current + drawHeight;
|
||||
updatePanel(p, halfHeight);
|
||||
foreach (Panel p in Lifetime.AliveItems)
|
||||
{
|
||||
float panelPosY = p.Position.Y;
|
||||
p.IsOnScreen = panelPosY >= Current - p.DrawHeight && panelPosY <= Current + drawHeight;
|
||||
updatePanel(p, halfHeight);
|
||||
}
|
||||
|
||||
// Determine range of indices for items that are now definitely on screen to be added
|
||||
@ -243,7 +246,8 @@ namespace osu.Game.Screens.Select
|
||||
for (int i = firstIndex; i < lastIndex; ++i)
|
||||
{
|
||||
Panel p = Lifetime[i];
|
||||
p.IsOnScreen = true;
|
||||
if (p.State != PanelSelectedState.Hidden)
|
||||
p.IsOnScreen = true; //we don't want to update the on-screen state of hidden pannels as they have incorrect (stacked) y values.
|
||||
updatePanel(p, halfHeight);
|
||||
}
|
||||
}
|
||||
@ -271,34 +275,50 @@ namespace osu.Game.Screens.Select
|
||||
break;
|
||||
}
|
||||
|
||||
if (direction != 0)
|
||||
if (direction == 0)
|
||||
return base.OnKeyDown(state, args);
|
||||
|
||||
if (!skipDifficulties)
|
||||
{
|
||||
int index = SelectedGroup.BeatmapPanels.IndexOf(SelectedPanel) + direction;
|
||||
int i = SelectedGroup.BeatmapPanels.IndexOf(SelectedPanel) + direction;
|
||||
|
||||
if (!skipDifficulties && index >= 0 && index < SelectedGroup.BeatmapPanels.Count)
|
||||
//changing difficulty panel, not set.
|
||||
SelectGroup(SelectedGroup, SelectedGroup.BeatmapPanels[index]);
|
||||
else
|
||||
if (i >= 0 && i < SelectedGroup.BeatmapPanels.Count)
|
||||
{
|
||||
index = (groups.IndexOf(SelectedGroup) + direction + groups.Count) % groups.Count;
|
||||
SelectBeatmap(groups[index].BeatmapPanels.First().Beatmap);
|
||||
//changing difficulty panel, not set.
|
||||
SelectGroup(SelectedGroup, SelectedGroup.BeatmapPanels[i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
int startIndex = groups.IndexOf(SelectedGroup);
|
||||
int index = startIndex;
|
||||
|
||||
do
|
||||
{
|
||||
index = (index + direction + groups.Count) % groups.Count;
|
||||
if (groups[index].State != BeatmapGroupState.Hidden)
|
||||
{
|
||||
SelectBeatmap(groups[index].BeatmapPanels.First().Beatmap);
|
||||
return true;
|
||||
}
|
||||
} while (index != startIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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<BeatmapGroup> GetEnumerator() => groups.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
279
osu.Game/Screens/Select/FilterControl.cs
Normal file
279
osu.Game/Screens/Select/FilterControl.cs
Normal file
@ -0,0 +1,279 @@
|
||||
using System;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
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.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
public class FilterControl : Container
|
||||
{
|
||||
public Action FilterChanged;
|
||||
|
||||
public string Search => searchTextBox.Text;
|
||||
public SortMode Sort { get; private set; } = SortMode.Title;
|
||||
public Action Exit;
|
||||
|
||||
private SearchTextBox searchTextBox;
|
||||
|
||||
public FilterControl()
|
||||
{
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = Color4.Black,
|
||||
Alpha = 0.6f,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
Padding = new MarginPadding(20),
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Width = 0.4f, // TODO: InnerWidth property or something
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
searchTextBox = new SearchTextBox { RelativeSizeAxes = Axes.X },
|
||||
new GroupSortTabs()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
searchTextBox.OnChange += (TextBox sender, bool newText) =>
|
||||
{
|
||||
if (newText)
|
||||
FilterChanged?.Invoke();
|
||||
};
|
||||
searchTextBox.Exit = () => Exit?.Invoke();
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
searchTextBox.GrabFocus = false;
|
||||
searchTextBox.TriggerFocusLost();
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
searchTextBox.GrabFocus = true;
|
||||
}
|
||||
|
||||
private class TabItem : ClickableContainer
|
||||
{
|
||||
public string Text
|
||||
{
|
||||
get { return text.Text; }
|
||||
set { text.Text = value; }
|
||||
}
|
||||
|
||||
private void FadeActive()
|
||||
{
|
||||
box.FadeIn(300);
|
||||
text.FadeColour(Color4.White, 300);
|
||||
}
|
||||
|
||||
private void FadeInactive()
|
||||
{
|
||||
box.FadeOut(300);
|
||||
text.FadeColour(fadeColour, 300);
|
||||
}
|
||||
|
||||
private bool active;
|
||||
public bool Active
|
||||
{
|
||||
get { return active; }
|
||||
set
|
||||
{
|
||||
active = value;
|
||||
if (active)
|
||||
FadeActive();
|
||||
else
|
||||
FadeInactive();
|
||||
}
|
||||
}
|
||||
|
||||
private SpriteText text;
|
||||
private Box box;
|
||||
private Color4 fadeColour;
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
if (!active)
|
||||
FadeActive();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
if (!active)
|
||||
FadeInactive();
|
||||
}
|
||||
|
||||
public TabItem()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
text = new SpriteText
|
||||
{
|
||||
Margin = new MarginPadding(5),
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
},
|
||||
box = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
Alpha = 0,
|
||||
Colour = Color4.White,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
text.Colour = colours.Blue;
|
||||
fadeColour = colours.Blue;
|
||||
}
|
||||
}
|
||||
|
||||
private class GroupSortTabs : Container
|
||||
{
|
||||
private TextAwesome groupsEllipsis, sortEllipsis;
|
||||
private SpriteText sortLabel;
|
||||
|
||||
public GroupSortTabs()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
Colour = OsuColour.Gray(80),
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FlowDirection.HorizontalOnly,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TabItem
|
||||
{
|
||||
Text = "All",
|
||||
Active = true,
|
||||
},
|
||||
new TabItem
|
||||
{
|
||||
Text = "Recently Played",
|
||||
Active = false,
|
||||
},
|
||||
new TabItem
|
||||
{
|
||||
Text = "Collections",
|
||||
Active = false,
|
||||
},
|
||||
groupsEllipsis = new TextAwesome
|
||||
{
|
||||
Icon = FontAwesome.fa_ellipsis_h,
|
||||
TextSize = 14,
|
||||
Margin = new MarginPadding { Top = 5, Bottom = 5 },
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
}
|
||||
}
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FlowDirection.HorizontalOnly,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
sortLabel = new SpriteText
|
||||
{
|
||||
Font = @"Exo2.0-Bold",
|
||||
Text = "Sort results by",
|
||||
TextSize = 14,
|
||||
Margin = new MarginPadding { Top = 5, Bottom = 5 },
|
||||
},
|
||||
new TabItem
|
||||
{
|
||||
Text = "Artist",
|
||||
Active = true,
|
||||
},
|
||||
sortEllipsis = new TextAwesome
|
||||
{
|
||||
Icon = FontAwesome.fa_ellipsis_h,
|
||||
TextSize = 14,
|
||||
Margin = new MarginPadding { Top = 5, Bottom = 5 },
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
groupsEllipsis.Colour = colours.Blue;
|
||||
sortLabel.Colour = colours.GreenLight;
|
||||
sortEllipsis.Colour = colours.GreenLight;
|
||||
}
|
||||
}
|
||||
|
||||
public enum SortMode
|
||||
{
|
||||
Arist,
|
||||
BPM,
|
||||
Creator,
|
||||
DateAdded,
|
||||
Difficulty,
|
||||
Length,
|
||||
RankAchieved,
|
||||
Title
|
||||
}
|
||||
|
||||
public enum GroupMode
|
||||
{
|
||||
NoGrouping,
|
||||
Arist,
|
||||
BPM,
|
||||
Creator,
|
||||
DateAdded,
|
||||
Difficulty,
|
||||
Length,
|
||||
RankAchieved,
|
||||
Title,
|
||||
Collections,
|
||||
Favorites,
|
||||
MyMaps,
|
||||
RankedStatus,
|
||||
RecentlyPlayed
|
||||
}
|
||||
}
|
||||
}
|
@ -29,6 +29,9 @@ using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Graphics;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Threading;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
@ -50,6 +53,8 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
private AudioSample sampleChangeDifficulty;
|
||||
private AudioSample sampleChangeBeatmap;
|
||||
|
||||
private List<BeatmapGroup> beatmapGroups;
|
||||
|
||||
private Footer footer;
|
||||
|
||||
@ -82,10 +87,11 @@ namespace osu.Game.Screens.Select
|
||||
}
|
||||
|
||||
Player player;
|
||||
FilterControl filter;
|
||||
|
||||
private void start()
|
||||
{
|
||||
if (player != null)
|
||||
if (player != null || Beatmap == null)
|
||||
return;
|
||||
|
||||
//in the future we may want to move this logic to a PlayerLoader gamemode or similar, so we can rely on the SongSelect transition
|
||||
@ -111,7 +117,8 @@ namespace osu.Game.Screens.Select
|
||||
OsuGame osuGame, OsuColour colours)
|
||||
{
|
||||
const float carouselWidth = 640;
|
||||
|
||||
const float bottomToolHeight = 50;
|
||||
beatmapGroups = new List<BeatmapGroup>();
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ParallaxContainer
|
||||
@ -134,6 +141,13 @@ namespace osu.Game.Screens.Select
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
},
|
||||
filter = new FilterControl
|
||||
{
|
||||
Position = wedged_container_start_position,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
FilterChanged = filterChanged,
|
||||
Exit = Exit,
|
||||
},
|
||||
beatmapInfoWedge = new BeatmapInfoWedge
|
||||
{
|
||||
Alpha = 0,
|
||||
@ -174,9 +188,43 @@ namespace osu.Game.Screens.Select
|
||||
Task.Factory.StartNew(() => addBeatmapSets(game, initialAddSetsTask.Token), initialAddSetsTask.Token);
|
||||
}
|
||||
|
||||
private ScheduledDelegate filterTask;
|
||||
|
||||
private void filterChanged()
|
||||
{
|
||||
filterTask?.Cancel();
|
||||
filterTask = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
filterTask = null;
|
||||
var search = filter.Search;
|
||||
BeatmapGroup newSelection = null;
|
||||
foreach (var beatmapGroup in carousel)
|
||||
{
|
||||
var set = beatmapGroup.BeatmapSet;
|
||||
bool match = string.IsNullOrEmpty(search)
|
||||
|| (set.Metadata.Artist ?? "").IndexOf(search, StringComparison.InvariantCultureIgnoreCase) != -1
|
||||
|| (set.Metadata.ArtistUnicode ?? "").IndexOf(search, StringComparison.InvariantCultureIgnoreCase) != -1
|
||||
|| (set.Metadata.Title ?? "").IndexOf(search, StringComparison.InvariantCultureIgnoreCase) != -1
|
||||
|| (set.Metadata.TitleUnicode ?? "").IndexOf(search, StringComparison.InvariantCultureIgnoreCase) != -1;
|
||||
if (match)
|
||||
{
|
||||
beatmapGroup.State = BeatmapGroupState.Collapsed;
|
||||
if (newSelection == null || beatmapGroup.BeatmapSet.OnlineBeatmapSetID == Beatmap.BeatmapSetInfo.OnlineBeatmapSetID)
|
||||
newSelection = beatmapGroup;
|
||||
}
|
||||
else
|
||||
{
|
||||
beatmapGroup.State = BeatmapGroupState.Hidden;
|
||||
}
|
||||
}
|
||||
if (newSelection != null)
|
||||
carousel.SelectBeatmap(newSelection.BeatmapSet.Beatmaps[0], false);
|
||||
}, 250);
|
||||
}
|
||||
|
||||
private void onDatabaseOnBeatmapSetAdded(BeatmapSetInfo s)
|
||||
{
|
||||
Schedule(() => addBeatmapSet(s, Game));
|
||||
Schedule(() => addBeatmapSet(s, Game, true));
|
||||
}
|
||||
|
||||
protected override void OnEntering(GameMode last)
|
||||
@ -190,6 +238,8 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
beatmapInfoWedge.MoveToX(wedged_container_start_position.X - 50);
|
||||
beatmapInfoWedge.MoveToX(wedged_container_start_position.X, 800, EasingTypes.OutQuint);
|
||||
|
||||
filter.Activate();
|
||||
}
|
||||
|
||||
protected override void OnResuming(GameMode last)
|
||||
@ -203,6 +253,8 @@ namespace osu.Game.Screens.Select
|
||||
Content.FadeIn(250);
|
||||
|
||||
Content.ScaleTo(1, 250, EasingTypes.OutSine);
|
||||
|
||||
filter.Activate();
|
||||
}
|
||||
|
||||
protected override void OnSuspending(GameMode next)
|
||||
@ -210,6 +262,8 @@ namespace osu.Game.Screens.Select
|
||||
Content.ScaleTo(1.1f, 250, EasingTypes.InSine);
|
||||
|
||||
Content.FadeOut(250);
|
||||
|
||||
filter.Deactivate();
|
||||
base.OnSuspending(next);
|
||||
}
|
||||
|
||||
@ -219,6 +273,8 @@ namespace osu.Game.Screens.Select
|
||||
beatmapInfoWedge.RotateTo(10, 800, EasingTypes.InQuint);
|
||||
|
||||
Content.FadeOut(100);
|
||||
|
||||
filter.Deactivate();
|
||||
return base.OnExiting(next);
|
||||
}
|
||||
|
||||
@ -239,18 +295,15 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
private void changeBackground(WorkingBeatmap beatmap)
|
||||
{
|
||||
if (beatmap == null)
|
||||
return;
|
||||
|
||||
var backgroundModeBeatmap = Background as BackgroundModeBeatmap;
|
||||
if (backgroundModeBeatmap != null)
|
||||
{
|
||||
backgroundModeBeatmap.Beatmap = beatmap;
|
||||
// TODO: Remove this once we have non-nullable Beatmap
|
||||
(Background as BackgroundModeBeatmap)?.BlurTo(BACKGROUND_BLUR, 1000);
|
||||
backgroundModeBeatmap.BlurTo(BACKGROUND_BLUR, 1000);
|
||||
}
|
||||
|
||||
beatmapInfoWedge.UpdateBeatmap(beatmap);
|
||||
if (beatmap != null)
|
||||
beatmapInfoWedge.UpdateBeatmap(beatmap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -262,11 +315,9 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
//todo: change background in selectionChanged instead; support per-difficulty backgrounds.
|
||||
changeBackground(beatmap);
|
||||
selectBeatmap(beatmap.BeatmapInfo);
|
||||
carousel.SelectBeatmap(beatmap.BeatmapInfo);
|
||||
}
|
||||
|
||||
private void selectBeatmap(BeatmapInfo beatmap) => carousel.SelectBeatmap(beatmap);
|
||||
|
||||
/// <summary>
|
||||
/// selection has been changed as the result of interaction with the carousel.
|
||||
/// </summary>
|
||||
@ -301,7 +352,7 @@ namespace osu.Game.Screens.Select
|
||||
}
|
||||
}
|
||||
|
||||
private void addBeatmapSet(BeatmapSetInfo beatmapSet, BaseGame game)
|
||||
private void addBeatmapSet(BeatmapSetInfo beatmapSet, BaseGame game, bool select = false)
|
||||
{
|
||||
beatmapSet = database.GetWithChildren<BeatmapSetInfo>(beatmapSet.ID);
|
||||
beatmapSet.Beatmaps.ForEach(b =>
|
||||
@ -314,7 +365,7 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
var beatmap = new WorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault(), beatmapSet, database);
|
||||
|
||||
var group = new BeatmapGroup(beatmap)
|
||||
var group = new BeatmapGroup(beatmap, beatmapSet)
|
||||
{
|
||||
SelectionChanged = selectionChanged,
|
||||
StartRequested = b => start()
|
||||
@ -324,9 +375,11 @@ namespace osu.Game.Screens.Select
|
||||
//this likely won't scale so well, but allows us to completely async the loading flow.
|
||||
Task.WhenAll(group.BeatmapPanels.Select(panel => panel.Preload(game))).ContinueWith(task => Schedule(delegate
|
||||
{
|
||||
beatmapGroups.Add(group);
|
||||
|
||||
carousel.AddGroup(group);
|
||||
|
||||
if (Beatmap == null)
|
||||
if (Beatmap == null || select)
|
||||
carousel.SelectBeatmap(beatmapSet.Beatmaps.First());
|
||||
else
|
||||
{
|
||||
|
86
osu.Game/Screens/Select/SearchTextBox.cs
Normal file
86
osu.Game/Screens/Select/SearchTextBox.cs
Normal file
@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
public class SearchTextBox : TextBox
|
||||
{
|
||||
protected override Color4 BackgroundUnfocused => new Color4(10, 10, 10, 255);
|
||||
protected override Color4 BackgroundFocused => new Color4(10, 10, 10, 255);
|
||||
public Action Exit;
|
||||
public bool GrabFocus = false;
|
||||
|
||||
private SpriteText placeholder;
|
||||
|
||||
protected override string InternalText
|
||||
{
|
||||
get { return base.InternalText; }
|
||||
set
|
||||
{
|
||||
base.InternalText = value;
|
||||
if (placeholder != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
placeholder.Text = "type to search";
|
||||
else
|
||||
placeholder.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SearchTextBox()
|
||||
{
|
||||
Height = 35;
|
||||
TextContainer.Padding = new MarginPadding(5);
|
||||
Add(new Drawable[]
|
||||
{
|
||||
placeholder = new SpriteText
|
||||
{
|
||||
Font = @"Exo2.0-MediumItalic",
|
||||
Text = "type to search",
|
||||
Colour = new Color4(180, 180, 180, 255),
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding { Left = 10 },
|
||||
},
|
||||
new TextAwesome
|
||||
{
|
||||
Icon = FontAwesome.fa_search,
|
||||
Origin = Anchor.CentreRight,
|
||||
Anchor = Anchor.CentreRight,
|
||||
Margin = new MarginPadding { Right = 10 },
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (GrabFocus && !HasFocus && IsVisible)
|
||||
TriggerFocus();
|
||||
base.Update();
|
||||
}
|
||||
|
||||
protected override void OnFocusLost(InputState state)
|
||||
{
|
||||
if (state.Keyboard.Keys.Any(key => key == Key.Escape))
|
||||
Exit?.Invoke();
|
||||
base.OnFocusLost(state);
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Key == Key.Left || args.Key == Key.Right || args.Key == Key.Enter)
|
||||
return false;
|
||||
return base.OnKeyDown(state, args);
|
||||
}
|
||||
}
|
||||
}
|
@ -68,6 +68,7 @@
|
||||
<Compile Include="Graphics\Cursor\CursorTrail.cs" />
|
||||
<Compile Include="Graphics\UserInterface\BackButton.cs" />
|
||||
<Compile Include="Graphics\UserInterface\OsuTextBox.cs" />
|
||||
<Compile Include="Graphics\UserInterface\TwoLayerButton.cs" />
|
||||
<Compile Include="Modes\Objects\HitObjectParser.cs" />
|
||||
<Compile Include="Modes\Score.cs" />
|
||||
<Compile Include="Modes\ScoreProcesssor.cs" />
|
||||
@ -121,6 +122,7 @@
|
||||
<Compile Include="Screens\Multiplayer\MatchCreate.cs" />
|
||||
<Compile Include="Screens\Play\FailDialog.cs" />
|
||||
<Compile Include="Screens\Play\PlayerInputManager.cs" />
|
||||
<Compile Include="Screens\Play\SkipButton.cs" />
|
||||
<Compile Include="Screens\Select\CarouselContainer.cs" />
|
||||
<Compile Include="Screens\Select\MatchSongSelect.cs" />
|
||||
<Compile Include="Screens\OsuGameMode.cs" />
|
||||
@ -148,10 +150,10 @@
|
||||
<Compile Include="Graphics\Cursor\OsuCursorContainer.cs" />
|
||||
<Compile Include="Graphics\Processing\RatioAdjust.cs" />
|
||||
<Compile Include="Graphics\TextAwesome.cs" />
|
||||
<Compile Include="Graphics\UserInterface\KeyCounter.cs" />
|
||||
<Compile Include="Graphics\UserInterface\KeyCounterKeyboard.cs" />
|
||||
<Compile Include="Graphics\UserInterface\KeyCounterCollection.cs" />
|
||||
<Compile Include="Graphics\UserInterface\KeyCounterMouse.cs" />
|
||||
<Compile Include="Screens\Play\KeyCounter.cs" />
|
||||
<Compile Include="Screens\Play\KeyCounterKeyboard.cs" />
|
||||
<Compile Include="Screens\Play\KeyCounterCollection.cs" />
|
||||
<Compile Include="Screens\Play\KeyCounterMouse.cs" />
|
||||
<Compile Include="Graphics\UserInterface\PercentageCounter.cs" />
|
||||
<Compile Include="Graphics\UserInterface\ScoreCounter.cs" />
|
||||
<Compile Include="Graphics\UserInterface\StarCounter.cs" />
|
||||
@ -237,6 +239,8 @@
|
||||
<Compile Include="Configuration\ScreenshotFormat.cs" />
|
||||
<Compile Include="Configuration\ConfineMouseMode.cs" />
|
||||
<Compile Include="Graphics\OsuColour.cs" />
|
||||
<Compile Include="Screens\Select\FilterControl.cs" />
|
||||
<Compile Include="Screens\Select\SearchTextBox.cs" />
|
||||
<Compile Include="Screens\Select\FooterButton.cs" />
|
||||
<Compile Include="Screens\Select\Footer.cs" />
|
||||
<Compile Include="Overlays\Pause\PauseButton.cs" />
|
||||
@ -274,4 +278,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
|
Loading…
Reference in New Issue
Block a user