mirror of
https://github.com/ppy/osu.git
synced 2025-03-17 22:17:25 +08:00
Merge pull request #299 from SirCmpwn/song-select-filtering
Song select filtering
This commit is contained in:
commit
e0868d2edf
@ -1 +1 @@
|
||||
Subproject commit 2e74df0a1bca294cad2094c86bf25d1833df7a14
|
||||
Subproject commit 16a01c7381e3ee8ef6b4fe863ba9232deba04c29
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -252,7 +252,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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -235,6 +235,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" />
|
||||
@ -272,4 +274,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
|
Loading…
x
Reference in New Issue
Block a user