Add initial game-wide beatmap flow.

This commit is contained in:
Dean Herbert
2016-10-28 19:55:48 +09:00
parent 0f5614ffa2
commit 74f1a9622f
10 changed files with 197 additions and 51 deletions

View File

@ -2,6 +2,7 @@
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework; using osu.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -27,6 +28,8 @@ namespace osu.Game.Beatmaps.Drawable
private BeatmapGroupState state; private BeatmapGroupState state;
public IEnumerable<BeatmapPanel> BeatmapPanels;
public BeatmapGroupState State public BeatmapGroupState State
{ {
get { return state; } get { return state; }
@ -62,6 +65,16 @@ namespace osu.Game.Beatmaps.Drawable
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
BeatmapPanels = beatmapSet.Beatmaps.Select(b =>
new BeatmapPanel(this.beatmapSet, b)
{
GainedSelection = panelGainedSelection,
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
RelativeSizeAxes = Axes.X,
});
Children = new[] Children = new[]
{ {
new FlowContainer new FlowContainer
@ -87,15 +100,7 @@ namespace osu.Game.Beatmaps.Drawable
Spacing = new Vector2(0, 5), Spacing = new Vector2(0, 5),
Direction = FlowDirection.VerticalOnly, Direction = FlowDirection.VerticalOnly,
Alpha = 0, Alpha = 0,
Children = this.beatmapSet.Beatmaps.Select(b => Children = BeatmapPanels
new BeatmapPanel(this.beatmapSet, b)
{
GainedSelection = panelGainedSelection,
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
RelativeSizeAxes = Axes.X,
}
)
} }
} }
} }

View File

@ -17,16 +17,15 @@ namespace osu.Game.Beatmaps
{ {
get get
{ {
if (track == null) if (track != null) return track;
try
{ {
try var trackData = Reader.ReadFile(Beatmap.Metadata.AudioFile);
{ if (trackData != null)
var trackData = Reader.ReadFile(Beatmap.Metadata.AudioFile); track = new AudioTrackBass(trackData);
if (trackData != null)
track = new AudioTrackBass(trackData);
}
catch { }
} }
catch { }
return track; return track;
} }

View File

@ -136,7 +136,7 @@ namespace osu.Game.Database
return Query<BeatmapSetInfo>().Where(s => s.BeatmapSetID == id).FirstOrDefault(); return Query<BeatmapSetInfo>().Where(s => s.BeatmapSetID == id).FirstOrDefault();
} }
public WorkingBeatmap GetBeatmapData(BeatmapInfo beatmapInfo) public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo)
{ {
var beatmapSet = Query<BeatmapSetInfo>().Where(s => s.BeatmapSetID == beatmapInfo.BeatmapSetID).FirstOrDefault(); var beatmapSet = Query<BeatmapSetInfo>().Where(s => s.BeatmapSetID == beatmapInfo.BeatmapSetID).FirstOrDefault();
if (beatmapSet == null) if (beatmapSet == null)
@ -150,7 +150,7 @@ namespace osu.Game.Database
public Beatmap GetBeatmap(BeatmapInfo beatmapInfo) public Beatmap GetBeatmap(BeatmapInfo beatmapInfo)
{ {
using (WorkingBeatmap data = GetBeatmapData(beatmapInfo)) using (WorkingBeatmap data = GetWorkingBeatmap(beatmapInfo))
return data.Beatmap; return data.Beatmap;
} }

View File

@ -7,7 +7,7 @@ using SQLiteNetExtensions.Attributes;
namespace osu.Game.Database namespace osu.Game.Database
{ {
public class BeatmapInfo public class BeatmapInfo : IEquatable<BeatmapInfo>
{ {
[PrimaryKey] [PrimaryKey]
public int BeatmapID { get; set; } public int BeatmapID { get; set; }
@ -64,5 +64,10 @@ namespace osu.Game.Database
// Metadata // Metadata
public string Version { get; set; } public string Version { get; set; }
public bool Equals(BeatmapInfo other)
{
return BeatmapID == other?.BeatmapID;
}
} }
} }

View File

@ -10,6 +10,8 @@ using osu.Framework.Graphics.Transformations;
using osu.Game.GameModes.Backgrounds; using osu.Game.GameModes.Backgrounds;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework; using osu.Framework;
using osu.Framework.Configuration;
using osu.Game.Beatmaps;
namespace osu.Game.GameModes.Menu namespace osu.Game.GameModes.Menu
{ {

View File

@ -3,17 +3,20 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Configuration;
using osu.Framework.GameModes; using osu.Framework.GameModes;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Background; using osu.Game.Graphics.Background;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
namespace osu.Game.GameModes namespace osu.Game.GameModes
{ {
public class OsuGameMode : GameMode public abstract class OsuGameMode : GameMode
{ {
internal BackgroundMode Background { get; private set; } internal BackgroundMode Background { get; private set; }
@ -23,6 +26,64 @@ namespace osu.Game.GameModes
/// </summary> /// </summary>
protected virtual BackgroundMode CreateBackground() => null; protected virtual BackgroundMode CreateBackground() => null;
private bool boundToBeatmap;
private Bindable<WorkingBeatmap> beatmap;
public WorkingBeatmap Beatmap
{
get
{
bindBeatmap();
return beatmap.Value;
}
set
{
bindBeatmap();
beatmap.Value = value;
}
}
private void bindBeatmap()
{
if (beatmap == null)
beatmap = new Bindable<WorkingBeatmap>();
if (!boundToBeatmap)
{
beatmap.ValueChanged += beatmap_ValueChanged;
boundToBeatmap = true;
}
}
protected override void Dispose(bool isDisposing)
{
if (boundToBeatmap)
beatmap.ValueChanged -= beatmap_ValueChanged;
base.Dispose(isDisposing);
}
private void beatmap_ValueChanged(object sender, EventArgs e)
{
OnBeatmapChanged(beatmap.Value);
}
public override bool Push(GameMode mode)
{
OsuGameMode nextOsu = mode as OsuGameMode;
if (nextOsu != null)
{
nextOsu.beatmap = beatmap;
}
return base.Push(mode);
}
protected virtual void OnBeatmapChanged(WorkingBeatmap beatmap)
{
}
protected override void OnEntering(GameMode last) protected override void OnEntering(GameMode last)
{ {
OsuGameMode lastOsu = last as OsuGameMode; OsuGameMode lastOsu = last as OsuGameMode;

View File

@ -16,8 +16,11 @@ using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Audio.Track;
using osu.Game.Beatmaps.Drawable; using osu.Game.Beatmaps.Drawable;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Game.Beatmaps;
using osu.Framework.GameModes;
namespace osu.Game.GameModes.Play namespace osu.Game.GameModes.Play
{ {
@ -26,10 +29,12 @@ namespace osu.Game.GameModes.Play
private Bindable<PlayMode> playMode; private Bindable<PlayMode> playMode;
private BeatmapDatabase database; private BeatmapDatabase database;
private BeatmapGroup selectedBeatmapGroup; private BeatmapGroup selectedBeatmapGroup;
private BeatmapInfo selectedBeatmapInfo;
// TODO: use currently selected track as bg // TODO: use currently selected track as bg
protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4"); protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4");
private ScrollContainer scrollContainer; private ScrollContainer scrollContainer;
private FlowContainer setList; private FlowContainer beatmapSetFlow;
private TrackManager trackManager;
/// <param name="database">Optionally provide a database to use instead of the OsuGame one.</param> /// <param name="database">Optionally provide a database to use instead of the OsuGame one.</param>
public PlaySongSelect(BeatmapDatabase database = null) public PlaySongSelect(BeatmapDatabase database = null)
@ -73,7 +78,7 @@ namespace osu.Game.GameModes.Play
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
Children = new Drawable[] Children = new Drawable[]
{ {
setList = new FlowContainer beatmapSetFlow = new FlowContainer
{ {
Padding = new MarginPadding { Left = 25, Top = 25, Bottom = 25 + bottomToolHeight }, Padding = new MarginPadding { Left = 25, Top = 25, Bottom = 25 + bottomToolHeight },
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
@ -123,7 +128,7 @@ namespace osu.Game.GameModes.Play
if (osuGame != null) if (osuGame != null)
{ {
playMode = osuGame.PlayMode; playMode = osuGame.PlayMode;
playMode.ValueChanged += PlayMode_ValueChanged; playMode.ValueChanged += playMode_ValueChanged;
// Temporary: // Temporary:
scrollContainer.Padding = new MarginPadding { Top = osuGame.Toolbar.Height }; scrollContainer.Padding = new MarginPadding { Top = osuGame.Toolbar.Height };
} }
@ -133,22 +138,68 @@ namespace osu.Game.GameModes.Play
database.BeatmapSetAdded += s => Schedule(() => addBeatmapSet(s)); database.BeatmapSetAdded += s => Schedule(() => addBeatmapSet(s));
trackManager = game.Audio.Track;
Task.Factory.StartNew(addBeatmapSets); Task.Factory.StartNew(addBeatmapSets);
} }
protected override void OnEntering(GameMode last)
{
base.OnEntering(last);
ensurePlayingSelected();
}
protected override void OnResuming(GameMode last)
{
ensurePlayingSelected();
base.OnResuming(last);
}
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);
if (playMode != null) if (playMode != null)
playMode.ValueChanged -= PlayMode_ValueChanged; playMode.ValueChanged -= playMode_ValueChanged;
} }
private void PlayMode_ValueChanged(object sender, EventArgs e) private void playMode_ValueChanged(object sender, EventArgs e)
{ {
} }
private void selectBeatmap(BeatmapGroup group, BeatmapInfo beatmap) protected override void OnBeatmapChanged(WorkingBeatmap beatmap)
{ {
base.OnBeatmapChanged(beatmap);
selectBeatmap(beatmap.Beatmap.BeatmapInfo);
}
private void selectBeatmap(BeatmapInfo beatmap)
{
if (beatmap.Equals(selectedBeatmapInfo))
return;
beatmapSetFlow.Children.Cast<BeatmapGroup>().First(b =>
{
var panel = b.BeatmapPanels.FirstOrDefault(p => p.Beatmap.Equals(beatmap));
panel?.TriggerClick();
return panel != null;
});
}
/// <summary>
/// selection has been changed as the result of interaction with the carousel.
/// </summary>
private void selectionChanged(BeatmapGroup group, BeatmapInfo beatmap)
{
selectedBeatmapInfo = beatmap;
if (!beatmap.Equals(Beatmap?.Beatmap?.BeatmapInfo))
{
Beatmap = database.GetWorkingBeatmap(beatmap);
}
ensurePlayingSelected();
if (selectedBeatmapGroup == group) if (selectedBeatmapGroup == group)
return; return;
@ -158,6 +209,17 @@ namespace osu.Game.GameModes.Play
selectedBeatmapGroup = group; selectedBeatmapGroup = group;
} }
private void ensurePlayingSelected()
{
var track = Beatmap?.Track;
if (track != null)
{
trackManager.SetExclusive(track);
track.Start();
}
}
private void addBeatmapSet(BeatmapSetInfo beatmapSet) private void addBeatmapSet(BeatmapSetInfo beatmapSet)
{ {
beatmapSet = database.GetWithChildren<BeatmapSetInfo>(beatmapSet.BeatmapSetID); beatmapSet = database.GetWithChildren<BeatmapSetInfo>(beatmapSet.BeatmapSetID);
@ -165,9 +227,9 @@ namespace osu.Game.GameModes.Play
beatmapSet.Beatmaps = beatmapSet.Beatmaps.OrderBy(b => b.BaseDifficulty.OverallDifficulty).ToList(); beatmapSet.Beatmaps = beatmapSet.Beatmaps.OrderBy(b => b.BaseDifficulty.OverallDifficulty).ToList();
Schedule(() => Schedule(() =>
{ {
var group = new BeatmapGroup(beatmapSet) { SelectionChanged = selectBeatmap }; var group = new BeatmapGroup(beatmapSet) { SelectionChanged = selectionChanged };
setList.Add(group); beatmapSetFlow.Add(group);
if (setList.Children.Count() == 1) if (beatmapSetFlow.Children.Count() == 1)
group.State = BeatmapGroupState.Expanded; group.State = BeatmapGroupState.Expanded;
}); });
} }

View File

@ -22,7 +22,6 @@ namespace osu.Game.GameModes.Play
protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4"); protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4");
public BeatmapInfo BeatmapInfo; public BeatmapInfo BeatmapInfo;
public WorkingBeatmap Beatmap;
public PlayMode PreferredPlayMode; public PlayMode PreferredPlayMode;
@ -31,16 +30,13 @@ namespace osu.Game.GameModes.Play
private InterpolatingFramedClock playerClock; private InterpolatingFramedClock playerClock;
private IAdjustableClock sourceClock; private IAdjustableClock sourceClock;
protected override void Dispose(bool isDisposing)
{
Beatmap?.Dispose();
base.Dispose(isDisposing);
}
protected override bool OnExiting(GameMode next) protected override bool OnExiting(GameMode next)
{ {
//eagerly dispose as the finalizer runs too late right now. if (next == null)
Beatmap?.Dispose(); {
//eagerly dispose as the finalizer runs too late right now.
Beatmap?.Dispose();
}
return base.OnExiting(next); return base.OnExiting(next);
} }
@ -52,7 +48,7 @@ namespace osu.Game.GameModes.Play
try try
{ {
if (Beatmap == null) if (Beatmap == null)
Beatmap = ((OsuGame)game).Beatmaps.GetBeatmapData(BeatmapInfo); Beatmap = ((OsuGame)game).Beatmaps.GetWorkingBeatmap(BeatmapInfo);
} }
catch catch
{ {
@ -69,27 +65,28 @@ namespace osu.Game.GameModes.Play
sourceClock = track; sourceClock = track;
} }
sourceClock = (IAdjustableClock)Beatmap.Track ?? new StopwatchClock(); sourceClock = (IAdjustableClock)track ?? new StopwatchClock();
playerClock = new InterpolatingFramedClock(sourceClock); playerClock = new InterpolatingFramedClock(sourceClock);
Schedule(() => Schedule(() =>
{ {
sourceClock.Reset();
sourceClock.Start(); sourceClock.Start();
}); });
HitRenderer hitRenderer; HitRenderer hitRenderer;
ScoreOverlay scoreOverlay; ScoreOverlay scoreOverlay;
if (Beatmap.Beatmap.BeatmapInfo?.Mode > PlayMode.Osu) var beatmap = Beatmap.Beatmap;
if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu)
{ {
//we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor.
Exit(); Exit();
return; return;
} }
PlayMode usablePlayMode = Beatmap.Beatmap.BeatmapInfo?.Mode > PlayMode.Osu ? Beatmap.Beatmap.BeatmapInfo.Mode : PreferredPlayMode; PlayMode usablePlayMode = beatmap.BeatmapInfo?.Mode > PlayMode.Osu ? beatmap.BeatmapInfo.Mode : PreferredPlayMode;
switch (usablePlayMode) switch (usablePlayMode)
{ {
@ -98,7 +95,7 @@ namespace osu.Game.GameModes.Play
hitRenderer = new OsuHitRenderer hitRenderer = new OsuHitRenderer
{ {
Objects = Beatmap.Beatmap.HitObjects, Objects = beatmap.HitObjects,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre Origin = Anchor.Centre
}; };
@ -108,7 +105,7 @@ namespace osu.Game.GameModes.Play
hitRenderer = new TaikoHitRenderer hitRenderer = new TaikoHitRenderer
{ {
Objects = Beatmap.Beatmap.HitObjects, Objects = beatmap.HitObjects,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre Origin = Anchor.Centre
}; };
@ -118,7 +115,7 @@ namespace osu.Game.GameModes.Play
hitRenderer = new CatchHitRenderer hitRenderer = new CatchHitRenderer
{ {
Objects = Beatmap.Beatmap.HitObjects, Objects = beatmap.HitObjects,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre Origin = Anchor.Centre
}; };
@ -128,7 +125,7 @@ namespace osu.Game.GameModes.Play
hitRenderer = new ManiaHitRenderer hitRenderer = new ManiaHitRenderer
{ {
Objects = Beatmap.Beatmap.HitObjects, Objects = beatmap.HitObjects,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre Origin = Anchor.Centre
}; };

View File

@ -70,7 +70,10 @@ namespace osu.Game
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
ActivateRequested = delegate { volume.Show(); } ActivateRequested = delegate { volume.Show(); }
}, },
intro = new Intro(), intro = new Intro
{
Beatmap = Beatmap
},
Toolbar = new Toolbar Toolbar = new Toolbar
{ {
OnHome = delegate { MainMenu?.MakeCurrent(); }, OnHome = delegate { MainMenu?.MakeCurrent(); },

View File

@ -1,10 +1,13 @@
using osu.Framework; using System;
using osu.Framework;
using osu.Framework.Configuration;
using osu.Framework.GameModes; using osu.Framework.GameModes;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.IO.Stores; using osu.Framework.IO.Stores;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.IO; using osu.Game.Beatmaps.IO;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Database; using osu.Game.Database;
@ -32,6 +35,8 @@ namespace osu.Game
public CursorContainer Cursor; public CursorContainer Cursor;
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
public OsuGameBase() public OsuGameBase()
{ {
AddInternal(ratioContainer = new RatioAdjust()); AddInternal(ratioContainer = new RatioAdjust());
@ -41,6 +46,13 @@ namespace osu.Game
Options = new Options(), Options = new Options(),
Cursor = new OsuCursorContainer() Cursor = new OsuCursorContainer()
}; };
Beatmap.ValueChanged += Beatmap_ValueChanged;
}
private void Beatmap_ValueChanged(object sender, EventArgs e)
{
throw new NotImplementedException();
} }
public override void Load(BaseGame game) public override void Load(BaseGame game)