mirror of
https://github.com/ppy/osu.git
synced 2025-01-06 20:33:08 +08:00
Merge branch 'master' of git://github.com/ppy/osu into direct-previews
This commit is contained in:
commit
259d49e6b9
@ -1 +1 @@
|
|||||||
Subproject commit 5f3a7fe4d0537820a33b817a41623b4b22a3ec59
|
Subproject commit cdb031c3a8ef693cd71458c5e19c68127ab72938
|
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
|
|
||||||
public class CatchModHidden : ModHidden
|
public class CatchModHidden : ModHidden
|
||||||
{
|
{
|
||||||
public override string Description => @"Play with no approach circles and fading notes for a slight score advantage.";
|
public override string Description => @"Play with fading notes for a slight score advantage.";
|
||||||
public override double ScoreMultiplier => 1.06;
|
public override double ScoreMultiplier => 1.06;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
public void TestImportWhenClosed()
|
public void TestImportWhenClosed()
|
||||||
{
|
{
|
||||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||||
using (HeadlessGameHost host = new HeadlessGameHost())
|
using (HeadlessGameHost host = new HeadlessGameHost("TestImportWhenClosed"))
|
||||||
{
|
{
|
||||||
var osu = loadOsu(host);
|
var osu = loadOsu(host);
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
Assert.IsFalse(File.Exists(temp));
|
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,15 +61,14 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
Assert.IsFalse(File.Exists(temp));
|
waitForOrAssert(() => !File.Exists(temp), "Temporary still exists after IPC import", 5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestImportWhenFileOpen()
|
public void TestImportWhenFileOpen()
|
||||||
{
|
{
|
||||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
using (HeadlessGameHost host = new HeadlessGameHost("TestImportWhenFileOpen"))
|
||||||
using (HeadlessGameHost host = new HeadlessGameHost())
|
|
||||||
{
|
{
|
||||||
var osu = loadOsu(host);
|
var osu = loadOsu(host);
|
||||||
|
|
||||||
@ -101,8 +100,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
var osu = new OsuGameBase();
|
var osu = new OsuGameBase();
|
||||||
Task.Run(() => host.Run(osu));
|
Task.Run(() => host.Run(osu));
|
||||||
|
|
||||||
while (!osu.IsLoaded)
|
waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time");
|
||||||
Thread.Sleep(1);
|
|
||||||
|
|
||||||
return osu;
|
return osu;
|
||||||
}
|
}
|
||||||
@ -113,30 +111,17 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
var store = osu.Dependencies.Get<BeatmapManager>();
|
var store = osu.Dependencies.Get<BeatmapManager>();
|
||||||
|
|
||||||
Action waitAction = () =>
|
waitForOrAssert(() => (resultSets = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526)).Any(),
|
||||||
{
|
@"BeatmapSet did not import to the database in allocated time.", timeout);
|
||||||
while (!(resultSets = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526)).Any())
|
|
||||||
Thread.Sleep(50);
|
|
||||||
};
|
|
||||||
|
|
||||||
Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout),
|
|
||||||
@"BeatmapSet did not import to the database in allocated time.");
|
|
||||||
|
|
||||||
//ensure we were stored to beatmap database backing...
|
//ensure we were stored to beatmap database backing...
|
||||||
|
|
||||||
Assert.IsTrue(resultSets.Count() == 1, $@"Incorrect result count found ({resultSets.Count()} but should be 1).");
|
Assert.IsTrue(resultSets.Count() == 1, $@"Incorrect result count found ({resultSets.Count()} but should be 1).");
|
||||||
|
|
||||||
IEnumerable<BeatmapInfo> resultBeatmaps = null;
|
IEnumerable<BeatmapInfo> resultBeatmaps = null;
|
||||||
|
|
||||||
//if we don't re-check here, the set will be inserted but the beatmaps won't be present yet.
|
//if we don't re-check here, the set will be inserted but the beatmaps won't be present yet.
|
||||||
waitAction = () =>
|
waitForOrAssert(() => (resultBeatmaps = store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() == 12,
|
||||||
{
|
@"Beatmaps did not import to the database in allocated time", timeout);
|
||||||
while ((resultBeatmaps = store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() != 12)
|
|
||||||
Thread.Sleep(50);
|
|
||||||
};
|
|
||||||
|
|
||||||
Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout),
|
|
||||||
@"Beatmaps did not import to the database in allocated time");
|
|
||||||
|
|
||||||
var set = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526).First();
|
var set = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526).First();
|
||||||
|
|
||||||
@ -160,5 +145,11 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap;
|
beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap;
|
||||||
Assert.IsTrue(beatmap?.HitObjects.Count > 0);
|
Assert.IsTrue(beatmap?.HitObjects.Count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void waitForOrAssert(Func<bool> result, string failureMessage, int timeout = 60000)
|
||||||
|
{
|
||||||
|
Action waitAction = () => { while (!result()) Thread.Sleep(20); };
|
||||||
|
Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout), failureMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,15 +78,29 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
// Editor
|
// Editor
|
||||||
// This bookmarks stuff is necessary because DB doesn't know how to store int[]
|
// This bookmarks stuff is necessary because DB doesn't know how to store int[]
|
||||||
public string StoredBookmarks { get; set; }
|
[JsonIgnore]
|
||||||
|
public string StoredBookmarks
|
||||||
|
{
|
||||||
|
get { return string.Join(",", Bookmarks); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
Bookmarks = new int[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bookmarks = value.Split(',').Select(v =>
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
bool result = int.TryParse(v, out val);
|
||||||
|
return new { result, val };
|
||||||
|
}).Where(p => p.result).Select(p => p.val).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Ignore]
|
[Ignore]
|
||||||
[JsonIgnore]
|
public int[] Bookmarks { get; set; } = new int[0];
|
||||||
public int[] Bookmarks
|
|
||||||
{
|
|
||||||
get { return StoredBookmarks.Split(',').Select(int.Parse).ToArray(); }
|
|
||||||
set { StoredBookmarks = string.Join(",", value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public double DistanceSpacing { get; set; }
|
public double DistanceSpacing { get; set; }
|
||||||
public int BeatDivisor { get; set; }
|
public int BeatDivisor { get; set; }
|
||||||
|
@ -54,6 +54,7 @@ namespace osu.Game.Configuration
|
|||||||
// Graphics
|
// Graphics
|
||||||
Set(OsuSetting.ShowFpsDisplay, false);
|
Set(OsuSetting.ShowFpsDisplay, false);
|
||||||
|
|
||||||
|
Set(OsuSetting.ShowStoryboard, true);
|
||||||
Set(OsuSetting.CursorRotation, true);
|
Set(OsuSetting.CursorRotation, true);
|
||||||
|
|
||||||
Set(OsuSetting.MenuParallax, true);
|
Set(OsuSetting.MenuParallax, true);
|
||||||
@ -89,6 +90,7 @@ namespace osu.Game.Configuration
|
|||||||
GameplayCursorSize,
|
GameplayCursorSize,
|
||||||
AutoCursorSize,
|
AutoCursorSize,
|
||||||
DimLevel,
|
DimLevel,
|
||||||
|
ShowStoryboard,
|
||||||
KeyOverlay,
|
KeyOverlay,
|
||||||
FloatingComments,
|
FloatingComments,
|
||||||
PlaybackSpeed,
|
PlaybackSpeed,
|
||||||
|
@ -101,17 +101,15 @@ namespace osu.Game.Online.API
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case APIState.Offline:
|
case APIState.Offline:
|
||||||
|
case APIState.Connecting:
|
||||||
//work to restore a connection...
|
//work to restore a connection...
|
||||||
if (!HasLogin)
|
if (!HasLogin)
|
||||||
{
|
{
|
||||||
//OsuGame.Scheduler.Add(() => { OsuGame.ShowLogin(); });
|
|
||||||
|
|
||||||
State = APIState.Offline;
|
State = APIState.Offline;
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(50);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State < APIState.Connecting)
|
|
||||||
State = APIState.Connecting;
|
State = APIState.Connecting;
|
||||||
|
|
||||||
if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, Password))
|
if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, Password))
|
||||||
@ -125,7 +123,8 @@ namespace osu.Game.Online.API
|
|||||||
|
|
||||||
|
|
||||||
var userReq = new GetUserRequest();
|
var userReq = new GetUserRequest();
|
||||||
userReq.Success += u => {
|
userReq.Success += u =>
|
||||||
|
{
|
||||||
LocalUser.Value = u;
|
LocalUser.Value = u;
|
||||||
//we're connected!
|
//we're connected!
|
||||||
State = APIState.Online;
|
State = APIState.Online;
|
||||||
@ -133,16 +132,14 @@ namespace osu.Game.Online.API
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!handleRequest(userReq))
|
if (!handleRequest(userReq))
|
||||||
{
|
|
||||||
State = APIState.Failing;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//hard bail if we can't get a valid access token.
|
//hard bail if we can't get a valid access token.
|
||||||
if (authentication.RequestAccessToken() == null)
|
if (authentication.RequestAccessToken() == null)
|
||||||
{
|
{
|
||||||
|
Logout(false);
|
||||||
State = APIState.Offline;
|
State = APIState.Offline;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -162,20 +159,12 @@ namespace osu.Game.Online.API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearCredentials()
|
|
||||||
{
|
|
||||||
Username = null;
|
|
||||||
Password = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Login(string username, string password)
|
public void Login(string username, string password)
|
||||||
{
|
{
|
||||||
Debug.Assert(State == APIState.Offline);
|
Debug.Assert(State == APIState.Offline);
|
||||||
|
|
||||||
Username = username;
|
Username = username;
|
||||||
Password = password;
|
Password = password;
|
||||||
|
|
||||||
State = APIState.Connecting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -204,7 +193,7 @@ namespace osu.Game.Online.API
|
|||||||
switch (statusCode)
|
switch (statusCode)
|
||||||
{
|
{
|
||||||
case HttpStatusCode.Unauthorized:
|
case HttpStatusCode.Unauthorized:
|
||||||
State = APIState.Offline;
|
Logout(false);
|
||||||
return true;
|
return true;
|
||||||
case HttpStatusCode.RequestTimeout:
|
case HttpStatusCode.RequestTimeout:
|
||||||
failureCount++;
|
failureCount++;
|
||||||
@ -215,6 +204,7 @@ namespace osu.Game.Online.API
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
State = APIState.Failing;
|
State = APIState.Failing;
|
||||||
|
flushQueue();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,26 +225,15 @@ namespace osu.Game.Online.API
|
|||||||
public APIState State
|
public APIState State
|
||||||
{
|
{
|
||||||
get { return state; }
|
get { return state; }
|
||||||
set
|
private set
|
||||||
{
|
{
|
||||||
APIState oldState = state;
|
APIState oldState = state;
|
||||||
APIState newState = value;
|
APIState newState = value;
|
||||||
|
|
||||||
state = value;
|
state = value;
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case APIState.Failing:
|
|
||||||
case APIState.Offline:
|
|
||||||
flushQueue();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldState != newState)
|
if (oldState != newState)
|
||||||
{
|
{
|
||||||
//OsuGame.Scheduler.Add(delegate
|
|
||||||
{
|
|
||||||
//NotificationOverlay.ShowMessage($@"We just went {newState}!", newState == APIState.Online ? Color4.YellowGreen : Color4.OrangeRed, 5000);
|
|
||||||
log.Add($@"We just went {newState}!");
|
log.Add($@"We just went {newState}!");
|
||||||
Scheduler.Add(delegate
|
Scheduler.Add(delegate
|
||||||
{
|
{
|
||||||
@ -264,7 +243,6 @@ namespace osu.Game.Online.API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsLoggedIn => LocalUser.Value.Id > 1;
|
public bool IsLoggedIn => LocalUser.Value.Id > 1;
|
||||||
|
|
||||||
@ -292,11 +270,12 @@ namespace osu.Game.Online.API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Logout()
|
public void Logout(bool clearUsername = true)
|
||||||
{
|
{
|
||||||
clearCredentials();
|
flushQueue();
|
||||||
|
if (clearUsername) Username = null;
|
||||||
|
Password = null;
|
||||||
authentication.Clear();
|
authentication.Clear();
|
||||||
State = APIState.Offline;
|
|
||||||
LocalUser.Value = createGuestUser();
|
LocalUser.Value = createGuestUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Online.API.Requests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty(@"statistics")]
|
[JsonProperty(@"statistics")]
|
||||||
private Dictionary<string, dynamic> jsonStats
|
private Dictionary<string, object> jsonStats
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,9 @@ namespace osu.Game.Overlays
|
|||||||
private readonly Header header;
|
private readonly Header header;
|
||||||
private readonly Info info;
|
private readonly Info info;
|
||||||
|
|
||||||
|
// receive input outside our bounds so we can trigger a close event on ourselves.
|
||||||
|
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true;
|
||||||
|
|
||||||
public BeatmapSetOverlay()
|
public BeatmapSetOverlay()
|
||||||
{
|
{
|
||||||
FirstWaveColour = OsuColour.Gray(0.4f);
|
FirstWaveColour = OsuColour.Gray(0.4f);
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
|
|
||||||
public Header()
|
public Header()
|
||||||
{
|
{
|
||||||
Tabs.Current.Value = DirectTab.Search;
|
Tabs.Current.Value = DirectTab.NewestMaps;
|
||||||
Tabs.Current.TriggerChange();
|
Tabs.Current.TriggerChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,7 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return;
|
if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return;
|
||||||
|
|
||||||
getSetsRequest = new GetBeatmapSetsRequest(currentQuery,
|
getSetsRequest = new GetBeatmapSetsRequest(currentQuery.Value ?? string.Empty,
|
||||||
((FilterControl)Filter).Ruleset.Value,
|
((FilterControl)Filter).Ruleset.Value,
|
||||||
Filter.DisplayStyleControl.Dropdown.Current.Value,
|
Filter.DisplayStyleControl.Dropdown.Current.Value,
|
||||||
Filter.Tabs.Current.Value); //todo: sort direction (?)
|
Filter.Tabs.Current.Value); //todo: sort direction (?)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Overlays.Settings.Sections.General;
|
using osu.Game.Overlays.Settings.Sections.General;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
@ -26,6 +27,12 @@ namespace osu.Game.Overlays
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuContextMenuContainer
|
||||||
|
{
|
||||||
|
Width = 360,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
@ -34,9 +41,9 @@ namespace osu.Game.Overlays
|
|||||||
Colour = Color4.Black,
|
Colour = Color4.Black,
|
||||||
Alpha = 0.6f,
|
Alpha = 0.6f,
|
||||||
},
|
},
|
||||||
new OsuContextMenuContainer
|
new Container
|
||||||
{
|
{
|
||||||
Width = 360,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
AutoSizeDuration = transition_time,
|
AutoSizeDuration = transition_time,
|
||||||
@ -59,6 +66,8 @@ namespace osu.Game.Overlays
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
|||||||
{
|
{
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
|
new SettingsCheckbox
|
||||||
|
{
|
||||||
|
LabelText = "Storyboards",
|
||||||
|
Bindable = config.GetBindable<bool>(OsuSetting.ShowStoryboard)
|
||||||
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
LabelText = "Rotate cursor when dragging",
|
LabelText = "Rotate cursor when dragging",
|
||||||
|
@ -34,6 +34,7 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
public const float CONTENT_X_MARGIN = 50;
|
public const float CONTENT_X_MARGIN = 50;
|
||||||
|
|
||||||
|
// receive input outside our bounds so we can trigger a close event on ourselves.
|
||||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true;
|
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true;
|
||||||
|
|
||||||
protected override bool OnClick(InputState state)
|
protected override bool OnClick(InputState state)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// 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 osu.Framework;
|
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -165,10 +164,8 @@ namespace osu.Game.Overlays
|
|||||||
wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y));
|
wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Wave : Container, IStateful<Visibility>
|
private class Wave : VisibilityContainer
|
||||||
{
|
{
|
||||||
public event Action<Visibility> StateChanged;
|
|
||||||
|
|
||||||
public float FinalPosition;
|
public float FinalPosition;
|
||||||
|
|
||||||
public Wave()
|
public Wave()
|
||||||
@ -183,13 +180,7 @@ namespace osu.Game.Overlays
|
|||||||
Radius = 20f,
|
Radius = 20f,
|
||||||
};
|
};
|
||||||
|
|
||||||
Children = new Drawable[]
|
Child = new Box { RelativeSizeAxes = Axes.Both };
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
@ -201,28 +192,8 @@ namespace osu.Game.Overlays
|
|||||||
Height = Parent.Parent.DrawSize.Y * 1.5f;
|
Height = Parent.Parent.DrawSize.Y * 1.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Visibility state;
|
protected override void PopIn() => this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show);
|
||||||
|
protected override void PopOut() => this.MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide);
|
||||||
public Visibility State
|
|
||||||
{
|
|
||||||
get { return state; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
state = value;
|
|
||||||
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case Visibility.Hidden:
|
|
||||||
this.MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide);
|
|
||||||
break;
|
|
||||||
case Visibility.Visible:
|
|
||||||
this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
StateChanged?.Invoke(State);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,6 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
|
|
||||||
public DateTimeOffset Date;
|
public DateTimeOffset Date;
|
||||||
|
|
||||||
public Dictionary<string, dynamic> Statistics = new Dictionary<string, dynamic>();
|
public Dictionary<string, object> Statistics = new Dictionary<string, object>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2007-2017 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.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The part of the timeline that displays bookmarks.
|
||||||
|
/// </summary>
|
||||||
|
internal class BookmarkPart : TimelinePart
|
||||||
|
{
|
||||||
|
protected override void LoadBeatmap(WorkingBeatmap beatmap)
|
||||||
|
{
|
||||||
|
base.LoadBeatmap(beatmap);
|
||||||
|
foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks)
|
||||||
|
Add(new BookmarkVisualisation(bookmark));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BookmarkVisualisation : PointVisualisation
|
||||||
|
{
|
||||||
|
public BookmarkVisualisation(double startTime)
|
||||||
|
: base(startTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours) => Colour = colours.Blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2007-2017 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.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The part of the timeline that displays breaks in the song.
|
||||||
|
/// </summary>
|
||||||
|
internal class BreakPart : TimelinePart
|
||||||
|
{
|
||||||
|
protected override void LoadBeatmap(WorkingBeatmap beatmap)
|
||||||
|
{
|
||||||
|
base.LoadBeatmap(beatmap);
|
||||||
|
foreach (var breakPeriod in beatmap.Beatmap.Breaks)
|
||||||
|
Add(new BreakVisualisation(breakPeriod));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BreakVisualisation : DurationVisualisation
|
||||||
|
{
|
||||||
|
public BreakVisualisation(BreakPeriod breakPeriod)
|
||||||
|
: base(breakPeriod.StartTime, breakPeriod.EndTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours) => Colour = colours.Yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright (c) 2007-2017 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.Extensions.IEnumerableExtensions;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The part of the timeline that displays the control points.
|
||||||
|
/// </summary>
|
||||||
|
internal class ControlPointPart : TimelinePart
|
||||||
|
{
|
||||||
|
protected override void LoadBeatmap(WorkingBeatmap beatmap)
|
||||||
|
{
|
||||||
|
base.LoadBeatmap(beatmap);
|
||||||
|
|
||||||
|
ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo;
|
||||||
|
|
||||||
|
cpi.TimingPoints.ForEach(addTimingPoint);
|
||||||
|
|
||||||
|
// Consider all non-timing points as the same type
|
||||||
|
cpi.SoundPoints.Select(c => (ControlPoint)c)
|
||||||
|
.Concat(cpi.EffectPoints)
|
||||||
|
.Concat(cpi.DifficultyPoints)
|
||||||
|
.Distinct()
|
||||||
|
// Non-timing points should not be added where there are timing points
|
||||||
|
.Where(c => cpi.TimingPointAt(c.Time).Time != c.Time)
|
||||||
|
.ForEach(addNonTimingPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTimingPoint(ControlPoint controlPoint) => Add(new TimingPointVisualisation(controlPoint));
|
||||||
|
private void addNonTimingPoint(ControlPoint controlPoint) => Add(new NonTimingPointVisualisation(controlPoint));
|
||||||
|
|
||||||
|
private class TimingPointVisualisation : ControlPointVisualisation
|
||||||
|
{
|
||||||
|
public TimingPointVisualisation(ControlPoint controlPoint)
|
||||||
|
: base(controlPoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours) => Colour = colours.YellowDark;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NonTimingPointVisualisation : ControlPointVisualisation
|
||||||
|
{
|
||||||
|
public NonTimingPointVisualisation(ControlPoint controlPoint)
|
||||||
|
: base(controlPoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours) => Colour = colours.Green;
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class ControlPointVisualisation : PointVisualisation
|
||||||
|
{
|
||||||
|
protected ControlPointVisualisation(ControlPoint controlPoint)
|
||||||
|
: base(controlPoint.Time)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The part of the timeline that displays the current position of the song.
|
||||||
|
/// </summary>
|
||||||
|
internal class MarkerPart : TimelinePart
|
||||||
|
{
|
||||||
|
private readonly Drawable marker;
|
||||||
|
|
||||||
|
public MarkerPart()
|
||||||
|
{
|
||||||
|
Add(marker = new MarkerVisualisation());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnDragStart(InputState state) => true;
|
||||||
|
protected override bool OnDragEnd(InputState state) => true;
|
||||||
|
protected override bool OnDrag(InputState state)
|
||||||
|
{
|
||||||
|
seekToPosition(state.Mouse.NativeState.Position);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||||
|
{
|
||||||
|
seekToPosition(state.Mouse.NativeState.Position);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Seeks the <see cref="SummaryTimeline"/> to the time closest to a position on the screen relative to the <see cref="SummaryTimeline"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="screenPosition">The position in screen coordinates.</param>
|
||||||
|
private void seekToPosition(Vector2 screenPosition)
|
||||||
|
{
|
||||||
|
if (Beatmap.Value == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth);
|
||||||
|
seekTo(markerPos / DrawWidth * Beatmap.Value.Track.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void seekTo(double time) => Beatmap.Value?.Track.Seek(time);
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
marker.X = (float)(Beatmap.Value?.Track.CurrentTime ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadBeatmap(WorkingBeatmap beatmap)
|
||||||
|
{
|
||||||
|
// block base call so we don't clear our marker (can be reused on beatmap change).
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MarkerVisualisation : CompositeDrawable
|
||||||
|
{
|
||||||
|
public MarkerVisualisation()
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
RelativePositionAxes = Axes.X;
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
AutoSizeAxes = Axes.X;
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Triangle
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
Scale = new Vector2(1, -1),
|
||||||
|
Size = new Vector2(10, 5),
|
||||||
|
},
|
||||||
|
new Triangle
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
Size = new Vector2(10, 5)
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 2,
|
||||||
|
EdgeSmoothness = new Vector2(1, 0)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours) => Colour = colours.Red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a part of the summary timeline..
|
||||||
|
/// </summary>
|
||||||
|
internal abstract class TimelinePart : CompositeDrawable
|
||||||
|
{
|
||||||
|
public Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
private readonly Container timeline;
|
||||||
|
|
||||||
|
protected TimelinePart()
|
||||||
|
{
|
||||||
|
AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both });
|
||||||
|
|
||||||
|
Beatmap.ValueChanged += b =>
|
||||||
|
{
|
||||||
|
updateRelativeChildSize();
|
||||||
|
LoadBeatmap(b);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateRelativeChildSize()
|
||||||
|
{
|
||||||
|
// the track may not be loaded completely (only has a length once it is).
|
||||||
|
if (!Beatmap.Value.Track.IsLoaded)
|
||||||
|
{
|
||||||
|
timeline.RelativeChildSize = Vector2.One;
|
||||||
|
Schedule(updateRelativeChildSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeline.RelativeChildSize = new Vector2((float)Math.Max(1, Beatmap.Value.Track.Length), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Add(Drawable visualisation) => timeline.Add(visualisation);
|
||||||
|
|
||||||
|
protected virtual void LoadBeatmap(WorkingBeatmap beatmap)
|
||||||
|
{
|
||||||
|
timeline.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The timeline that sits at the bottom of the editor.
|
||||||
|
/// </summary>
|
||||||
|
public class SummaryTimeline : CompositeDrawable
|
||||||
|
{
|
||||||
|
private const float corner_radius = 5;
|
||||||
|
private const float contents_padding = 15;
|
||||||
|
|
||||||
|
public Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
private readonly Drawable background;
|
||||||
|
|
||||||
|
private readonly Drawable timelineBar;
|
||||||
|
|
||||||
|
public SummaryTimeline()
|
||||||
|
{
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = corner_radius;
|
||||||
|
|
||||||
|
TimelinePart markerPart, controlPointPart, bookmarkPart, breakPart;
|
||||||
|
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
background = new Box { RelativeSizeAxes = Axes.Both },
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Left = contents_padding, Right = contents_padding },
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
markerPart = new MarkerPart { RelativeSizeAxes = Axes.Both },
|
||||||
|
controlPointPart = new ControlPointPart
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Height = 0.35f
|
||||||
|
},
|
||||||
|
bookmarkPart = new BookmarkPart
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Height = 0.35f
|
||||||
|
},
|
||||||
|
timelineBar = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Circle
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Size = new Vector2(5)
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 1,
|
||||||
|
EdgeSmoothness = new Vector2(0, 1),
|
||||||
|
},
|
||||||
|
new Circle
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Size = new Vector2(5)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
breakPart = new BreakPart
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Height = 0.25f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
markerPart.Beatmap.BindTo(Beatmap);
|
||||||
|
controlPointPart.Beatmap.BindTo(Beatmap);
|
||||||
|
bookmarkPart.Beatmap.BindTo(Beatmap);
|
||||||
|
breakPart.Beatmap.BindTo(Beatmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
background.Colour = colours.Gray1;
|
||||||
|
timelineBar.Colour = colours.Gray5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a spanning point on a timeline part.
|
||||||
|
/// </summary>
|
||||||
|
internal class DurationVisualisation : Container
|
||||||
|
{
|
||||||
|
protected DurationVisualisation(double startTime, double endTime)
|
||||||
|
{
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = 5;
|
||||||
|
|
||||||
|
RelativePositionAxes = Axes.X;
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
X = (float)startTime;
|
||||||
|
Width = (float)(endTime - startTime);
|
||||||
|
|
||||||
|
AddInternal(new Box { RelativeSizeAxes = Axes.Both });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a singular point on a timeline part.
|
||||||
|
/// </summary>
|
||||||
|
internal class PointVisualisation : Box
|
||||||
|
{
|
||||||
|
protected PointVisualisation(double startTime)
|
||||||
|
{
|
||||||
|
Origin = Anchor.TopCentre;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
Width = 1;
|
||||||
|
EdgeSmoothness = new Vector2(1, 0);
|
||||||
|
|
||||||
|
RelativePositionAxes = Axes.X;
|
||||||
|
X = (float)startTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,29 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// 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.Collections.Generic;
|
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Screens.Backgrounds;
|
using osu.Game.Screens.Backgrounds;
|
||||||
using osu.Game.Screens.Select;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Screens.Edit.Menus;
|
using osu.Game.Screens.Edit.Menus;
|
||||||
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit
|
namespace osu.Game.Screens.Edit
|
||||||
{
|
{
|
||||||
internal class Editor : ScreenWhiteBox
|
internal class Editor : OsuScreen
|
||||||
{
|
{
|
||||||
protected override IEnumerable<Type> PossibleChildren => new[] { typeof(EditSongSelect) };
|
|
||||||
|
|
||||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4");
|
protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4");
|
||||||
|
|
||||||
internal override bool ShowOverlays => false;
|
internal override bool ShowOverlays => false;
|
||||||
|
|
||||||
|
private readonly Box bottomBackground;
|
||||||
|
|
||||||
public Editor()
|
public Editor()
|
||||||
{
|
{
|
||||||
Add(new Container
|
Add(new Container
|
||||||
@ -189,6 +189,49 @@ namespace osu.Game.Screens.Edit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
SummaryTimeline summaryTimeline;
|
||||||
|
Add(new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 60,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
bottomBackground = new Box { RelativeSizeAxes = Axes.Both },
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Top = 5, Bottom = 5, Left = 10, Right = 10 },
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Name = "Bottom bar",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(10, 0),
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
summaryTimeline = new SummaryTimeline
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Width = 0.65f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
summaryTimeline.Beatmap.BindTo(Beatmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
bottomBackground.Colour = colours.Gray2;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnResuming(Screen last)
|
protected override void OnResuming(Screen last)
|
||||||
|
@ -24,6 +24,8 @@ using osu.Game.Screens.Ranking;
|
|||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Storyboards.Drawables;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play
|
namespace osu.Game.Screens.Play
|
||||||
{
|
{
|
||||||
@ -59,6 +61,7 @@ namespace osu.Game.Screens.Play
|
|||||||
#region User Settings
|
#region User Settings
|
||||||
|
|
||||||
private Bindable<double> dimLevel;
|
private Bindable<double> dimLevel;
|
||||||
|
private Bindable<bool> showStoryboard;
|
||||||
private Bindable<bool> mouseWheelDisabled;
|
private Bindable<bool> mouseWheelDisabled;
|
||||||
private Bindable<double> userAudioOffset;
|
private Bindable<double> userAudioOffset;
|
||||||
|
|
||||||
@ -66,6 +69,9 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private Container storyboardContainer;
|
||||||
|
private DrawableStoryboard storyboard;
|
||||||
|
|
||||||
private HUDOverlay hudOverlay;
|
private HUDOverlay hudOverlay;
|
||||||
private FailOverlay failOverlay;
|
private FailOverlay failOverlay;
|
||||||
|
|
||||||
@ -77,6 +83,7 @@ namespace osu.Game.Screens.Play
|
|||||||
this.api = api;
|
this.api = api;
|
||||||
|
|
||||||
dimLevel = config.GetBindable<double>(OsuSetting.DimLevel);
|
dimLevel = config.GetBindable<double>(OsuSetting.DimLevel);
|
||||||
|
showStoryboard = config.GetBindable<bool>(OsuSetting.ShowStoryboard);
|
||||||
|
|
||||||
mouseWheelDisabled = config.GetBindable<bool>(OsuSetting.MouseDisableWheel);
|
mouseWheelDisabled = config.GetBindable<bool>(OsuSetting.MouseDisableWheel);
|
||||||
|
|
||||||
@ -145,6 +152,12 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
|
storyboardContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Clock = offsetClock,
|
||||||
|
Alpha = 0,
|
||||||
|
},
|
||||||
pauseContainer = new PauseContainer
|
pauseContainer = new PauseContainer
|
||||||
{
|
{
|
||||||
AudioClock = decoupledClock,
|
AudioClock = decoupledClock,
|
||||||
@ -196,6 +209,9 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
scoreProcessor = RulesetContainer.CreateScoreProcessor();
|
scoreProcessor = RulesetContainer.CreateScoreProcessor();
|
||||||
|
|
||||||
|
if (showStoryboard)
|
||||||
|
initializeStoryboard(false);
|
||||||
|
|
||||||
hudOverlay.BindProcessor(scoreProcessor);
|
hudOverlay.BindProcessor(scoreProcessor);
|
||||||
hudOverlay.BindRulesetContainer(RulesetContainer);
|
hudOverlay.BindRulesetContainer(RulesetContainer);
|
||||||
|
|
||||||
@ -211,6 +227,16 @@ namespace osu.Game.Screens.Play
|
|||||||
scoreProcessor.Failed += onFail;
|
scoreProcessor.Failed += onFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeStoryboard(bool asyncLoad)
|
||||||
|
{
|
||||||
|
var beatmap = Beatmap.Value.Beatmap;
|
||||||
|
|
||||||
|
storyboard = beatmap.Storyboard.CreateDrawable(Beatmap.Value);
|
||||||
|
storyboard.Masking = true;
|
||||||
|
|
||||||
|
storyboardContainer.Add(asyncLoad ? new AsyncLoadWrapper(storyboard) { RelativeSizeAxes = Axes.Both } : (Drawable)storyboard);
|
||||||
|
}
|
||||||
|
|
||||||
public void Restart()
|
public void Restart()
|
||||||
{
|
{
|
||||||
sampleRestart?.Play();
|
sampleRestart?.Play();
|
||||||
@ -266,12 +292,12 @@ namespace osu.Game.Screens.Play
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
(Background as BackgroundScreenBeatmap)?.BlurTo(Vector2.Zero, 1500, Easing.OutQuint);
|
(Background as BackgroundScreenBeatmap)?.BlurTo(Vector2.Zero, 1500, Easing.OutQuint);
|
||||||
Background?.FadeTo(1 - (float)dimLevel, 1500, Easing.OutQuint);
|
|
||||||
|
dimLevel.ValueChanged += dimLevel_ValueChanged;
|
||||||
|
showStoryboard.ValueChanged += showStoryboard_ValueChanged;
|
||||||
|
updateBackgroundElements();
|
||||||
|
|
||||||
Content.Alpha = 0;
|
Content.Alpha = 0;
|
||||||
|
|
||||||
dimLevel.ValueChanged += newDim => Background?.FadeTo(1 - (float)newDim, 800);
|
|
||||||
|
|
||||||
Content
|
Content
|
||||||
.ScaleTo(0.7f)
|
.ScaleTo(0.7f)
|
||||||
.ScaleTo(1, 750, Easing.OutQuint)
|
.ScaleTo(1, 750, Easing.OutQuint)
|
||||||
@ -310,8 +336,33 @@ namespace osu.Game.Screens.Play
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void dimLevel_ValueChanged(double newValue)
|
||||||
|
=> updateBackgroundElements();
|
||||||
|
|
||||||
|
private void showStoryboard_ValueChanged(bool newValue)
|
||||||
|
=> updateBackgroundElements();
|
||||||
|
|
||||||
|
private void updateBackgroundElements()
|
||||||
|
{
|
||||||
|
var opacity = 1 - (float)dimLevel;
|
||||||
|
|
||||||
|
if (showStoryboard && storyboard == null)
|
||||||
|
initializeStoryboard(true);
|
||||||
|
|
||||||
|
var beatmap = Beatmap.Value;
|
||||||
|
var storyboardVisible = showStoryboard && beatmap.Beatmap.Storyboard.HasDrawable;
|
||||||
|
|
||||||
|
storyboardContainer.FadeColour(new Color4(opacity, opacity, opacity, 1), 800);
|
||||||
|
storyboardContainer.FadeTo(storyboardVisible && opacity > 0 ? 1 : 0);
|
||||||
|
|
||||||
|
Background?.FadeTo(!storyboardVisible || beatmap.Background == null ? opacity : 0, 800, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
private void fadeOut()
|
private void fadeOut()
|
||||||
{
|
{
|
||||||
|
dimLevel.ValueChanged -= dimLevel_ValueChanged;
|
||||||
|
showStoryboard.ValueChanged -= showStoryboard_ValueChanged;
|
||||||
|
|
||||||
const float fade_out_duration = 250;
|
const float fade_out_duration = 250;
|
||||||
|
|
||||||
RulesetContainer?.FadeOut(fade_out_duration);
|
RulesetContainer?.FadeOut(fade_out_duration);
|
||||||
|
@ -186,9 +186,9 @@ namespace osu.Game.Screens.Ranking
|
|||||||
|
|
||||||
private class DrawableScoreStatistic : Container
|
private class DrawableScoreStatistic : Container
|
||||||
{
|
{
|
||||||
private readonly KeyValuePair<string, dynamic> statistic;
|
private readonly KeyValuePair<string, object> statistic;
|
||||||
|
|
||||||
public DrawableScoreStatistic(KeyValuePair<string, dynamic> statistic)
|
public DrawableScoreStatistic(KeyValuePair<string, object> statistic)
|
||||||
{
|
{
|
||||||
this.statistic = statistic;
|
this.statistic = statistic;
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ namespace osu.Game.Storyboards
|
|||||||
public double LoopStartTime;
|
public double LoopStartTime;
|
||||||
public int LoopCount;
|
public int LoopCount;
|
||||||
|
|
||||||
public override double StartTime => LoopStartTime;
|
public override double StartTime => LoopStartTime + CommandsStartTime;
|
||||||
public override double EndTime => LoopStartTime + CommandsDuration * LoopCount;
|
public override double EndTime => StartTime + CommandsDuration * LoopCount;
|
||||||
|
|
||||||
public CommandLoop(double startTime, int loopCount)
|
public CommandLoop(double startTime, int loopCount)
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@ using OpenTK;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.IO;
|
using osu.Game.IO;
|
||||||
|
|
||||||
@ -14,6 +15,16 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
{
|
{
|
||||||
public Storyboard Storyboard { get; private set; }
|
public Storyboard Storyboard { get; private set; }
|
||||||
|
|
||||||
|
private readonly Background background;
|
||||||
|
public Texture BackgroundTexture
|
||||||
|
{
|
||||||
|
get { return background.Texture; }
|
||||||
|
set { background.Texture = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Container<DrawableStoryboardLayer> content;
|
||||||
|
protected override Container<DrawableStoryboardLayer> Content => content;
|
||||||
|
|
||||||
protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480);
|
protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480);
|
||||||
public override bool HandleInput => false;
|
public override bool HandleInput => false;
|
||||||
|
|
||||||
@ -39,6 +50,18 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
Size = new Vector2(640, 480);
|
Size = new Vector2(640, 480);
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
AddInternal(background = new Background
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
});
|
||||||
|
AddInternal(content = new Container<DrawableStoryboardLayer>
|
||||||
|
{
|
||||||
|
Size = new Vector2(640, 480),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -55,5 +78,10 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
foreach (var layer in Children)
|
foreach (var layer in Children)
|
||||||
layer.Enabled = passing ? layer.Layer.EnabledWhenPassing : layer.Layer.EnabledWhenFailing;
|
layer.Enabled = passing ? layer.Layer.EnabledWhenPassing : layer.Layer.EnabledWhenFailing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class Background : Sprite
|
||||||
|
{
|
||||||
|
protected override Vector2 DrawScale => Texture != null ? new Vector2(Parent.DrawHeight / Texture.DisplayHeight) : base.DrawScale;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,6 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
{
|
{
|
||||||
public StoryboardAnimation Animation { get; private set; }
|
public StoryboardAnimation Animation { get; private set; }
|
||||||
|
|
||||||
protected override bool ShouldBeAlive => Animation.HasCommands && base.ShouldBeAlive;
|
|
||||||
public override bool RemoveWhenNotAlive => !Animation.HasCommands || base.RemoveWhenNotAlive;
|
|
||||||
|
|
||||||
public bool FlipH { get; set; }
|
public bool FlipH { get; set; }
|
||||||
public bool FlipV { get; set; }
|
public bool FlipV { get; set; }
|
||||||
|
|
||||||
@ -59,12 +56,9 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
Position = animation.InitialPosition;
|
Position = animation.InitialPosition;
|
||||||
Repeat = animation.LoopType == AnimationLoopType.LoopForever;
|
Repeat = animation.LoopType == AnimationLoopType.LoopForever;
|
||||||
|
|
||||||
if (animation.HasCommands)
|
|
||||||
{
|
|
||||||
LifetimeStart = animation.StartTime;
|
LifetimeStart = animation.StartTime;
|
||||||
LifetimeEnd = animation.EndTime;
|
LifetimeEnd = animation.EndTime;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuGameBase game, TextureStore textureStore)
|
private void load(OsuGameBase game, TextureStore textureStore)
|
||||||
|
@ -28,9 +28,8 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
{
|
{
|
||||||
foreach (var element in Layer.Elements)
|
foreach (var element in Layer.Elements)
|
||||||
{
|
{
|
||||||
var drawable = element.CreateDrawable();
|
if (element.IsDrawable)
|
||||||
if (drawable != null)
|
Add(element.CreateDrawable());
|
||||||
Add(drawable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,6 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
{
|
{
|
||||||
public StoryboardSprite Sprite { get; private set; }
|
public StoryboardSprite Sprite { get; private set; }
|
||||||
|
|
||||||
protected override bool ShouldBeAlive => Sprite.HasCommands && base.ShouldBeAlive;
|
|
||||||
public override bool RemoveWhenNotAlive => !Sprite.HasCommands || base.RemoveWhenNotAlive;
|
|
||||||
|
|
||||||
public bool FlipH { get; set; }
|
public bool FlipH { get; set; }
|
||||||
public bool FlipV { get; set; }
|
public bool FlipV { get; set; }
|
||||||
|
|
||||||
@ -58,12 +55,9 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
Origin = sprite.Origin;
|
Origin = sprite.Origin;
|
||||||
Position = sprite.InitialPosition;
|
Position = sprite.InitialPosition;
|
||||||
|
|
||||||
if (sprite.HasCommands)
|
|
||||||
{
|
|
||||||
LifetimeStart = sprite.StartTime;
|
LifetimeStart = sprite.StartTime;
|
||||||
LifetimeEnd = sprite.EndTime;
|
LifetimeEnd = sprite.EndTime;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuGameBase game, TextureStore textureStore)
|
private void load(OsuGameBase game, TextureStore textureStore)
|
||||||
|
@ -8,6 +8,8 @@ namespace osu.Game.Storyboards
|
|||||||
public interface IStoryboardElement
|
public interface IStoryboardElement
|
||||||
{
|
{
|
||||||
string Path { get; }
|
string Path { get; }
|
||||||
|
bool IsDrawable { get; }
|
||||||
|
|
||||||
Drawable CreateDrawable();
|
Drawable CreateDrawable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// 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 osu.Game.Beatmaps;
|
||||||
using osu.Game.Storyboards.Drawables;
|
using osu.Game.Storyboards.Drawables;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -12,6 +13,8 @@ namespace osu.Game.Storyboards
|
|||||||
private readonly Dictionary<string, StoryboardLayer> layers = new Dictionary<string, StoryboardLayer>();
|
private readonly Dictionary<string, StoryboardLayer> layers = new Dictionary<string, StoryboardLayer>();
|
||||||
public IEnumerable<StoryboardLayer> Layers => layers.Values;
|
public IEnumerable<StoryboardLayer> Layers => layers.Values;
|
||||||
|
|
||||||
|
public bool HasDrawable => Layers.Any(l => l.Elements.Any(e => e.IsDrawable));
|
||||||
|
|
||||||
public Storyboard()
|
public Storyboard()
|
||||||
{
|
{
|
||||||
layers.Add("Background", new StoryboardLayer("Background", 3));
|
layers.Add("Background", new StoryboardLayer("Background", 3));
|
||||||
@ -29,7 +32,32 @@ namespace osu.Game.Storyboards
|
|||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DrawableStoryboard CreateDrawable()
|
/// <summary>
|
||||||
=> new DrawableStoryboard(this);
|
/// Whether the beatmap's background should be hidden while this storyboard is being displayed.
|
||||||
|
/// </summary>
|
||||||
|
public bool ReplacesBackground(BeatmapInfo beatmapInfo)
|
||||||
|
{
|
||||||
|
var backgroundPath = beatmapInfo.BeatmapSet?.Metadata?.BackgroundFile?.ToLowerInvariant();
|
||||||
|
if (backgroundPath == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return GetLayer("Background").Elements.Any(e => e.Path.ToLowerInvariant() == backgroundPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float AspectRatio(BeatmapInfo beatmapInfo)
|
||||||
|
=> beatmapInfo.WidescreenStoryboard ? 16 / 9f : 4 / 3f;
|
||||||
|
|
||||||
|
public DrawableStoryboard CreateDrawable(WorkingBeatmap working = null)
|
||||||
|
{
|
||||||
|
var drawable = new DrawableStoryboard(this);
|
||||||
|
if (working != null)
|
||||||
|
{
|
||||||
|
var beatmapInfo = working.Beatmap.BeatmapInfo;
|
||||||
|
drawable.Width = drawable.Height * AspectRatio(beatmapInfo);
|
||||||
|
if (!ReplacesBackground(beatmapInfo))
|
||||||
|
drawable.BackgroundTexture = working.Background;
|
||||||
|
}
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
// 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 osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace osu.Game.Storyboards
|
namespace osu.Game.Storyboards
|
||||||
{
|
{
|
||||||
public class StoryboardSample : IStoryboardElement
|
public class StoryboardSample : IStoryboardElement
|
||||||
{
|
{
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
public bool IsDrawable => false;
|
||||||
|
|
||||||
public double Time;
|
public double Time;
|
||||||
public float Volume;
|
public float Volume;
|
||||||
|
|
||||||
@ -19,6 +22,8 @@ namespace osu.Game.Storyboards
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Drawable CreateDrawable()
|
public Drawable CreateDrawable()
|
||||||
=> null;
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ namespace osu.Game.Storyboards
|
|||||||
private readonly List<CommandTrigger> triggers = new List<CommandTrigger>();
|
private readonly List<CommandTrigger> triggers = new List<CommandTrigger>();
|
||||||
|
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
public bool IsDrawable => HasCommands;
|
||||||
|
|
||||||
public Anchor Origin;
|
public Anchor Origin;
|
||||||
public Vector2 InitialPosition;
|
public Vector2 InitialPosition;
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics.UserInterface;
|
|||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
using osu.Game.Graphics.Cursor;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
@ -23,34 +24,34 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
public TestCaseContextMenu()
|
public TestCaseContextMenu()
|
||||||
{
|
{
|
||||||
Add(container = new MyContextMenuContainer
|
Add(new OsuContextMenuContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
container = new MyContextMenuContainer
|
||||||
{
|
{
|
||||||
Size = new Vector2(200),
|
Size = new Vector2(200),
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Children = new Drawable[]
|
Child = new Box
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.Green,
|
Colour = Color4.Green,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
new AnotherContextMenuContainer
|
||||||
|
|
||||||
Add(new AnotherContextMenuContainer
|
|
||||||
{
|
{
|
||||||
Size = new Vector2(200),
|
Size = new Vector2(200),
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Children = new Drawable[]
|
Child = new Box
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.Red,
|
Colour = Color4.Red,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
93
osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs
Normal file
93
osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Audio.Track;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
internal class TestCaseEditorSummaryTimeline : OsuTestCase
|
||||||
|
{
|
||||||
|
private const int length = 60000;
|
||||||
|
private readonly Random random;
|
||||||
|
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(SummaryTimeline) };
|
||||||
|
|
||||||
|
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
public TestCaseEditorSummaryTimeline()
|
||||||
|
{
|
||||||
|
random = new Random(1337);
|
||||||
|
|
||||||
|
SummaryTimeline summaryTimeline;
|
||||||
|
Add(summaryTimeline = new SummaryTimeline
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(500, 50)
|
||||||
|
});
|
||||||
|
|
||||||
|
summaryTimeline.Beatmap.BindTo(beatmap);
|
||||||
|
|
||||||
|
AddStep("New beatmap", newBeatmap);
|
||||||
|
|
||||||
|
newBeatmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void newBeatmap()
|
||||||
|
{
|
||||||
|
var b = new Beatmap();
|
||||||
|
|
||||||
|
for (int i = 0; i < random.Next(1, 10); i++)
|
||||||
|
b.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { Time = random.Next(0, length) });
|
||||||
|
|
||||||
|
for (int i = 0; i < random.Next(1, 5); i++)
|
||||||
|
b.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { Time = random.Next(0, length) });
|
||||||
|
|
||||||
|
for (int i = 0; i < random.Next(1, 5); i++)
|
||||||
|
b.ControlPointInfo.EffectPoints.Add(new EffectControlPoint { Time = random.Next(0, length) });
|
||||||
|
|
||||||
|
for (int i = 0; i < random.Next(1, 5); i++)
|
||||||
|
b.ControlPointInfo.SoundPoints.Add(new SoundControlPoint { Time = random.Next(0, length) });
|
||||||
|
|
||||||
|
b.BeatmapInfo.Bookmarks = new int[random.Next(10, 30)];
|
||||||
|
for (int i = 0; i < b.BeatmapInfo.Bookmarks.Length; i++)
|
||||||
|
b.BeatmapInfo.Bookmarks[i] = random.Next(0, length);
|
||||||
|
|
||||||
|
beatmap.Value = new TestWorkingBeatmap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestWorkingBeatmap : WorkingBeatmap
|
||||||
|
{
|
||||||
|
private readonly Beatmap beatmap;
|
||||||
|
|
||||||
|
public TestWorkingBeatmap(Beatmap beatmap)
|
||||||
|
: base(beatmap.BeatmapInfo)
|
||||||
|
{
|
||||||
|
this.beatmap = beatmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Texture GetBackground() => null;
|
||||||
|
|
||||||
|
protected override Beatmap GetBeatmap() => beatmap;
|
||||||
|
|
||||||
|
protected override Track GetTrack() => new TestTrack();
|
||||||
|
|
||||||
|
private class TestTrack : TrackVirtual
|
||||||
|
{
|
||||||
|
public TestTrack()
|
||||||
|
{
|
||||||
|
Length = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -79,11 +79,13 @@ namespace osu.Game.Tests.Visual
|
|||||||
storyboardContainer.Remove(storyboard);
|
storyboardContainer.Remove(storyboard);
|
||||||
|
|
||||||
var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true };
|
var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true };
|
||||||
decoupledClock.ChangeSource(working.Track);
|
|
||||||
storyboardContainer.Clock = decoupledClock;
|
storyboardContainer.Clock = decoupledClock;
|
||||||
|
|
||||||
storyboardContainer.Add(storyboard = working.Beatmap.Storyboard.CreateDrawable());
|
storyboard = working.Beatmap.Storyboard.CreateDrawable(beatmapBacking);
|
||||||
storyboard.Passing = false;
|
storyboard.Passing = false;
|
||||||
|
|
||||||
|
storyboardContainer.Add(storyboard);
|
||||||
|
decoupledClock.ChangeSource(working.Track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,6 @@
|
|||||||
<HintPath>$(SolutionDir)\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
@ -608,6 +607,14 @@
|
|||||||
<Compile Include="Screens\Charts\ChartListing.cs" />
|
<Compile Include="Screens\Charts\ChartListing.cs" />
|
||||||
<Compile Include="Screens\Direct\OnlineListing.cs" />
|
<Compile Include="Screens\Direct\OnlineListing.cs" />
|
||||||
<Compile Include="Screens\Edit\Editor.cs" />
|
<Compile Include="Screens\Edit\Editor.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\BreakPart.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\BookmarkPart.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\ControlPointPart.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\MarkerPart.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\TimelinePart.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\Visualisations\DurationVisualisation.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\Visualisations\PointVisualisation.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Components\Timelines\Summary\SummaryTimeline.cs" />
|
||||||
<Compile Include="Screens\Edit\Menus\EditorMenuBar.cs" />
|
<Compile Include="Screens\Edit\Menus\EditorMenuBar.cs" />
|
||||||
<Compile Include="Screens\Edit\Menus\EditorMenuBarItem.cs" />
|
<Compile Include="Screens\Edit\Menus\EditorMenuBarItem.cs" />
|
||||||
<Compile Include="Screens\Edit\Menus\EditorMenuItem.cs" />
|
<Compile Include="Screens\Edit\Menus\EditorMenuItem.cs" />
|
||||||
@ -737,6 +744,7 @@
|
|||||||
<Compile Include="Tests\Visual\TestCaseDrawableRoom.cs" />
|
<Compile Include="Tests\Visual\TestCaseDrawableRoom.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseDrawings.cs" />
|
<Compile Include="Tests\Visual\TestCaseDrawings.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseEditorMenuBar.cs" />
|
<Compile Include="Tests\Visual\TestCaseEditorMenuBar.cs" />
|
||||||
|
<Compile Include="Tests\Visual\TestCaseEditorSummaryTimeline.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseGamefield.cs" />
|
<Compile Include="Tests\Visual\TestCaseGamefield.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseGraph.cs" />
|
<Compile Include="Tests\Visual\TestCaseGraph.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseKeyConfiguration.cs" />
|
<Compile Include="Tests\Visual\TestCaseKeyConfiguration.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user