mirror of
https://github.com/ppy/osu.git
synced 2025-01-14 02:13:21 +08:00
commit
debea59bab
@ -1 +1 @@
|
||||
Subproject commit ca807cf81ae3706972937d4e1009376cfaa0b266
|
||||
Subproject commit 0505cf0d3b317667dbc95346f57b67fdbcdb4dee
|
29
osu.Desktop.VisualTests/Platform/TestStorage.cs
Normal file
29
osu.Desktop.VisualTests/Platform/TestStorage.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Desktop.Platform;
|
||||
using SQLite.Net;
|
||||
using SQLite.Net.Platform.Generic;
|
||||
using SQLite.Net.Interop;
|
||||
using SQLite.Net.Platform.Win32;
|
||||
|
||||
namespace osu.Desktop.Platform
|
||||
{
|
||||
public class TestStorage : DesktopStorage
|
||||
{
|
||||
public TestStorage(string baseName) : base(baseName)
|
||||
{
|
||||
}
|
||||
|
||||
public override SQLiteConnection GetDatabase(string name)
|
||||
{
|
||||
Directory.CreateDirectory(BasePath);
|
||||
ISQLitePlatform platform;
|
||||
if (RuntimeInfo.IsWindows)
|
||||
platform = new SQLitePlatformWin32();
|
||||
else
|
||||
platform = new SQLitePlatformGeneric();
|
||||
return new SQLiteConnection(platform, $@":memory:");
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Desktop;
|
||||
using osu.Framework.Desktop.Platform;
|
||||
using osu.Framework.Platform;
|
||||
|
||||
namespace osu.Desktop.VisualTests
|
||||
|
31
osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs
Normal file
31
osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs
Normal file
@ -0,0 +1,31 @@
|
||||
//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.GameModes.Testing;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Online.Chat.Display;
|
||||
using osu.Framework;
|
||||
using osu.Game.GameModes.Play;
|
||||
|
||||
namespace osu.Desktop.Tests
|
||||
{
|
||||
class TestCasePlaySongSelect : TestCase
|
||||
{
|
||||
public override string Name => @"Song Select";
|
||||
public override string Description => @"Testing song selection UI";
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
Add(new PlaySongSelect());
|
||||
}
|
||||
}
|
||||
}
|
@ -3,16 +3,81 @@
|
||||
|
||||
using osu.Framework;
|
||||
using osu.Framework.GameModes.Testing;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Database;
|
||||
using osu.Game;
|
||||
using osu.Framework.Desktop.Platform;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.GameModes.Play;
|
||||
using SQLiteNetExtensions.Extensions;
|
||||
using osu.Desktop.Platform;
|
||||
|
||||
namespace osu.Desktop.VisualTests
|
||||
{
|
||||
class VisualTestGame : OsuGameBase
|
||||
{
|
||||
private void InsertTestMap(int i)
|
||||
{
|
||||
var beatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
BeatmapSetID = 1234 + i,
|
||||
Hash = "d8e8fca2dc0f896fd7cb4cb0031ba249",
|
||||
Path = "/foo/bar/baz",
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
BeatmapSetID = 1234 + i,
|
||||
Artist = "MONACA",
|
||||
Title = "Black Song",
|
||||
Author = "Some Guy",
|
||||
},
|
||||
Beatmaps = new List<BeatmapInfo>(new[]
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
BeatmapID = 1234 + i,
|
||||
Mode = PlayMode.Osu,
|
||||
Path = "normal.osu",
|
||||
Version = "Normal",
|
||||
BaseDifficulty = new BaseDifficulty
|
||||
{
|
||||
OverallDifficulty = 3.5f,
|
||||
}
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
BeatmapID = 1235 + i,
|
||||
Mode = PlayMode.Osu,
|
||||
Path = "hard.osu",
|
||||
Version = "Hard",
|
||||
BaseDifficulty = new BaseDifficulty
|
||||
{
|
||||
OverallDifficulty = 5,
|
||||
}
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
BeatmapID = 1236 + i,
|
||||
Mode = PlayMode.Osu,
|
||||
Path = "insane.osu",
|
||||
Version = "Insane",
|
||||
BaseDifficulty = new BaseDifficulty
|
||||
{
|
||||
OverallDifficulty = 7,
|
||||
}
|
||||
},
|
||||
}),
|
||||
};
|
||||
BeatmapDatabase.Connection.InsertWithChildren(beatmapSet, true);
|
||||
}
|
||||
|
||||
public override void Load(BaseGame game)
|
||||
{
|
||||
Host.Storage = new TestStorage(@"visual-tests");
|
||||
base.Load(game);
|
||||
|
||||
for (int i = 0; i < 100; i += 10)
|
||||
InsertTestMap(i);
|
||||
Add(new TestBrowser());
|
||||
}
|
||||
}
|
||||
|
@ -81,15 +81,32 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ppy.OpenTK.2.0.50727.1337\lib\net20\OpenTK.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1337\lib\net20\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLiteNetExtensions">
|
||||
<HintPath>$(SolutionDir)\packages\SQLiteNetExtensions.1.3.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\SQLiteNetExtensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net.Platform.Win32">
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.1.1\lib\net4\SQLite.Net.Platform.Win32.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net.Platform.Generic">
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.1.1\lib\net40\SQLite.Net.Platform.Generic.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\osu.licenseheader">
|
||||
<Link>osu.licenseheader</Link>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
@ -146,9 +163,14 @@
|
||||
<Compile Include="Tests\TestCaseMenuButtonSystem.cs" />
|
||||
<Compile Include="Tests\TestCaseScoreCounter.cs" />
|
||||
<Compile Include="Tests\TestCaseTextAwesome.cs" />
|
||||
<Compile Include="Tests\TestCasePlaySongSelect.cs" />
|
||||
<Compile Include="VisualTestGame.cs" />
|
||||
<Compile Include="Platform\TestStorage.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Folder Include="Platform\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
@ -169,4 +191,4 @@
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
7
osu.Desktop.VisualTests/packages.config
Normal file
7
osu.Desktop.VisualTests/packages.config
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
|
||||
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
||||
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
||||
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
|
||||
</packages>
|
@ -2,20 +2,41 @@
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Desktop;
|
||||
using osu.Framework.Desktop.Platform;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game;
|
||||
using osu.Game.IPC;
|
||||
|
||||
namespace osu.Desktop
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
BasicGameHost host = Host.GetSuitableHost(@"osu");
|
||||
host.Add(new OsuGame(args));
|
||||
host.Run();
|
||||
DesktopGameHost host = Host.GetSuitableHost(@"osu", true);
|
||||
|
||||
if (!host.IsPrimaryInstance)
|
||||
{
|
||||
var importer = new BeatmapImporter(host);
|
||||
|
||||
foreach (var file in args)
|
||||
if (!importer.Import(file).Wait(1000))
|
||||
throw new TimeoutException(@"IPC took too long to send");
|
||||
Console.WriteLine(@"Sent import requests to running instance");
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseGame osu = new OsuGame(args);
|
||||
host.Add(osu);
|
||||
host.Run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
109
osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
Normal file
109
osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Desktop.Platform;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IPC;
|
||||
|
||||
namespace osu.Game.Tests.Beatmaps.IO
|
||||
{
|
||||
[TestFixture]
|
||||
public class ImportBeatmapTest
|
||||
{
|
||||
const string osz_path = @"../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz";
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportWhenClosed()
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
HeadlessGameHost host = new HeadlessGameHost();
|
||||
|
||||
var osu = loadOsu(host);
|
||||
osu.Beatmaps.Import(osz_path);
|
||||
ensureLoaded(osu);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportOverIPC()
|
||||
{
|
||||
HeadlessGameHost host = new HeadlessGameHost("host", true);
|
||||
HeadlessGameHost client = new HeadlessGameHost("client", true);
|
||||
|
||||
Assert.IsTrue(host.IsPrimaryInstance);
|
||||
Assert.IsTrue(!client.IsPrimaryInstance);
|
||||
|
||||
var osu = loadOsu(host);
|
||||
|
||||
var importer = new BeatmapImporter(client);
|
||||
if (!importer.Import(osz_path).Wait(1000))
|
||||
Assert.Fail(@"IPC took too long to send");
|
||||
|
||||
ensureLoaded(osu, 10000);
|
||||
}
|
||||
|
||||
private OsuGameBase loadOsu(BasicGameHost host)
|
||||
{
|
||||
var osu = new OsuGameBase();
|
||||
host.Add(osu);
|
||||
|
||||
//reset beatmap database (sqlite and storage backing)
|
||||
osu.Beatmaps.Reset();
|
||||
|
||||
return osu;
|
||||
}
|
||||
|
||||
private void ensureLoaded(OsuGameBase osu, int timeout = 100)
|
||||
{
|
||||
IEnumerable<BeatmapSetInfo> resultSets = null;
|
||||
|
||||
Action waitAction = () =>
|
||||
{
|
||||
while ((resultSets = osu.Beatmaps.Query<BeatmapSetInfo>().Where(s => s.BeatmapSetID == 241526)).Count() != 1)
|
||||
Thread.Sleep(1);
|
||||
};
|
||||
|
||||
Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout),
|
||||
@"BeatmapSet did not import to the database");
|
||||
|
||||
//ensure we were stored to beatmap database backing...
|
||||
|
||||
Assert.IsTrue(resultSets.Count() == 1);
|
||||
|
||||
IEnumerable<BeatmapInfo> resultBeatmaps = null;
|
||||
|
||||
//if we don't re-check here, the set will be inserted but the beatmaps won't be present yet.
|
||||
waitAction = () =>
|
||||
{
|
||||
while ((resultBeatmaps = osu.Beatmaps.Query<BeatmapInfo>().Where(s => s.BeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() != 12)
|
||||
Thread.Sleep(1);
|
||||
};
|
||||
|
||||
Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout),
|
||||
@"Beatmaps did not import to the database");
|
||||
|
||||
//fetch children and check we can load from the post-storage path...
|
||||
var set = osu.Beatmaps.GetChildren(resultSets.First());
|
||||
|
||||
Assert.IsTrue(set.Beatmaps.Count == resultBeatmaps.Count());
|
||||
|
||||
foreach (BeatmapInfo b in resultBeatmaps)
|
||||
Assert.IsTrue(set.Beatmaps.Any(c => c.BeatmapID == b.BeatmapID));
|
||||
|
||||
Assert.IsTrue(set.Beatmaps.Count > 0);
|
||||
|
||||
var beatmap = osu.Beatmaps.GetBeatmap(set.Beatmaps[0]);
|
||||
|
||||
Assert.IsTrue(beatmap.HitObjects.Count > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
osu.Game.Tests/app.config
Normal file
11
osu.Game.Tests/app.config
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@ -28,22 +28,44 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="nunit.framework">
|
||||
<HintPath>$(SolutionDir)\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="SQLite.Net">
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net.Platform.Win32">
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.1.1\lib\net4\SQLite.Net.Platform.Win32.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net.Platform.Generic">
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.1.1\lib\net40\SQLite.Net.Platform.Generic.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="OpenTK.dll.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework.Desktop\osu.Framework.Desktop.csproj">
|
||||
<Project>{65DC628F-A640-4111-AB35-3A5652BC1E17}</Project>
|
||||
<Name>osu.Framework.Desktop</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||
<Project>{c76bf5b3-985e-4d39-95fe-97c9c879b83a}</Project>
|
||||
<Name>osu.Framework</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
||||
<Project>{0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}</Project>
|
||||
<Name>osu.Game</Name>
|
||||
@ -53,14 +75,10 @@
|
||||
<Name>osu.Game.Resources</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
<Folder Include="Beatmaps\" />
|
||||
<Folder Include="Beatmaps\IO\" />
|
||||
<Folder Include="Beatmaps\Formats\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Compile Include="Beatmaps\IO\OszArchiveReaderTest.cs" />
|
||||
<Compile Include="Beatmaps\IO\ImportBeatmapTest.cs" />
|
||||
<Compile Include="Resources\Resource.cs" />
|
||||
<Compile Include="Beatmaps\Formats\OsuLegacyDecoderTest.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net45" />
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net45" />
|
||||
<package id="ppy.OpenTK" version="2.0.50727.1339" targetFramework="net45" />
|
||||
</packages>
|
||||
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
||||
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
||||
</packages>
|
||||
|
@ -17,4 +17,4 @@ namespace osu.Game.Beatmaps
|
||||
public List<ControlPoint> ControlPoints { get; set; }
|
||||
public List<Color4> ComboColors { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
141
osu.Game/Beatmaps/Drawable/BeatmapGroup.cs
Normal file
141
osu.Game/Beatmaps/Drawable/BeatmapGroup.cs
Normal file
@ -0,0 +1,141 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Database;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawable
|
||||
{
|
||||
class BeatmapGroup : Container, IStateful<BeatmapGroupState>
|
||||
{
|
||||
private const float collapsedAlpha = 0.5f;
|
||||
private const float collapsedWidth = 0.8f;
|
||||
|
||||
private BeatmapPanel selectedPanel;
|
||||
|
||||
/// <summary>
|
||||
/// Fires when one of our difficulties was selected. Will fire on first expand.
|
||||
/// </summary>
|
||||
public Action<BeatmapGroup, BeatmapInfo> SelectionChanged;
|
||||
|
||||
private BeatmapSetInfo beatmapSet;
|
||||
private BeatmapSetHeader header;
|
||||
private FlowContainer difficulties;
|
||||
|
||||
private BeatmapGroupState state;
|
||||
|
||||
public BeatmapGroupState State
|
||||
{
|
||||
get { return state; }
|
||||
set
|
||||
{
|
||||
state = value;
|
||||
switch (state)
|
||||
{
|
||||
case BeatmapGroupState.Expanded:
|
||||
FadeTo(1, 250);
|
||||
difficulties.Show();
|
||||
|
||||
//todo: header should probably have a state, with this logic moved inside it.
|
||||
header.Width = 1;
|
||||
header.GlowRadius = 5;
|
||||
header.BorderColour = new Color4(header.BorderColour.R, header.BorderColour.G, header.BorderColour.B, 255);
|
||||
|
||||
if (selectedPanel == null)
|
||||
(difficulties.Children.FirstOrDefault() as BeatmapPanel).Selected = true;
|
||||
SelectionChanged?.Invoke(this, selectedPanel?.Beatmap);
|
||||
break;
|
||||
case BeatmapGroupState.Collapsed:
|
||||
FadeTo(collapsedAlpha, 250);
|
||||
difficulties.Hide();
|
||||
|
||||
//todo: header should probably have a state, with this logic moved inside it.
|
||||
header.Width = collapsedWidth;
|
||||
header.GlowRadius = 0;
|
||||
header.BorderColour = new Color4(header.BorderColour.R, header.BorderColour.G, header.BorderColour.B, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BeatmapGroup(BeatmapSetInfo beatmapSet)
|
||||
{
|
||||
this.beatmapSet = beatmapSet;
|
||||
Alpha = 0;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Children = new[]
|
||||
{
|
||||
new FlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Children = new Framework.Graphics.Drawable[]
|
||||
{
|
||||
header = new BeatmapSetHeader(beatmapSet)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = collapsedWidth,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
difficulties = new FlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Margin = new MarginPadding { Top = 5 },
|
||||
Padding = new MarginPadding { Left = 75 },
|
||||
Spacing = new Vector2(0, 5),
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Alpha = 0,
|
||||
Children = this.beatmapSet.Beatmaps.Select(b =>
|
||||
new BeatmapPanel(this.beatmapSet, b)
|
||||
{
|
||||
GainedSelection = panelGainedSelection,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override void Load(BaseGame game)
|
||||
{
|
||||
base.Load(game);
|
||||
State = BeatmapGroupState.Collapsed;
|
||||
}
|
||||
|
||||
private void panelGainedSelection(BeatmapPanel panel)
|
||||
{
|
||||
if (selectedPanel != null) selectedPanel.Selected = false;
|
||||
selectedPanel = panel;
|
||||
|
||||
SelectionChanged?.Invoke(this, panel.Beatmap);
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
State = BeatmapGroupState.Expanded;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public enum BeatmapGroupState
|
||||
{
|
||||
Collapsed,
|
||||
Expanded,
|
||||
}
|
||||
}
|
110
osu.Game/Beatmaps/Drawable/BeatmapPanel.cs
Normal file
110
osu.Game/Beatmaps/Drawable/BeatmapPanel.cs
Normal file
@ -0,0 +1,110 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawable
|
||||
{
|
||||
class BeatmapPanel : Container
|
||||
{
|
||||
public BeatmapInfo Beatmap;
|
||||
|
||||
public Action<BeatmapPanel> GainedSelection;
|
||||
|
||||
private bool selected;
|
||||
|
||||
public bool Selected
|
||||
{
|
||||
get { return selected; }
|
||||
set
|
||||
{
|
||||
if (selected == value)
|
||||
return;
|
||||
selected = value;
|
||||
BorderColour = new Color4(
|
||||
BorderColour.R,
|
||||
BorderColour.G,
|
||||
BorderColour.B,
|
||||
selected ? 255 : 0);
|
||||
GlowRadius = selected ? 3 : 0;
|
||||
|
||||
if (selected) GainedSelection?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
public BeatmapPanel(BeatmapSetInfo set, BeatmapInfo beatmap)
|
||||
{
|
||||
Beatmap = beatmap;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
BorderThickness = 2;
|
||||
BorderColour = new Color4(221, 255, 255, 0);
|
||||
GlowColour = new Color4(166, 221, 251, 0.75f); // TODO: Get actual color for this
|
||||
Children = new Framework.Graphics.Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = new Color4(40, 86, 102, 255), // TODO: gradient
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = Vector2.One,
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
Padding = new MarginPadding(5),
|
||||
Direction = FlowDirection.HorizontalOnly,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Framework.Graphics.Drawable[]
|
||||
{
|
||||
new DifficultyIcon(FontAwesome.dot_circle_o, new Color4(159, 198, 0, 255)),
|
||||
new FlowContainer
|
||||
{
|
||||
Padding = new MarginPadding { Left = 10 },
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Framework.Graphics.Drawable[]
|
||||
{
|
||||
new FlowContainer
|
||||
{
|
||||
Direction = FlowDirection.HorizontalOnly,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
new SpriteText
|
||||
{
|
||||
Text = beatmap.Version,
|
||||
TextSize = 20,
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = string.Format(" mapped by {0}",
|
||||
(beatmap.Metadata ?? set.Metadata).Author),
|
||||
TextSize = 16,
|
||||
},
|
||||
}
|
||||
},
|
||||
new StarCounter { Count = beatmap.BaseDifficulty?.OverallDifficulty ?? 5, StarSize = 8 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
Selected = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
80
osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs
Normal file
80
osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs
Normal file
@ -0,0 +1,80 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawable
|
||||
{
|
||||
class BeatmapSetHeader : Container
|
||||
{
|
||||
public BeatmapSetHeader(BeatmapSetInfo beatmapSet)
|
||||
{
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
BorderThickness = 2;
|
||||
BorderColour = new Color4(221, 255, 255, 0);
|
||||
GlowColour = new Color4(166, 221, 251, 0.5f); // TODO: Get actual color for this
|
||||
Children = new Framework.Graphics.Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = new Color4(85, 85, 85, 255),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = Vector2.One,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = Vector2.One,
|
||||
Children = new Framework.Graphics.Drawable[]
|
||||
{
|
||||
new Box // TODO: Gradient
|
||||
{
|
||||
Colour = new Color4(0, 0, 0, 100),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = Vector2.One,
|
||||
}
|
||||
}
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Spacing = new Vector2(0, 2),
|
||||
Padding = new MarginPadding { Top = 3, Left = 20, Right = 20, Bottom = 3 },
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
// TODO: Make these italic
|
||||
new SpriteText
|
||||
{
|
||||
Text = beatmapSet.Metadata.Title ?? beatmapSet.Metadata.TitleUnicode,
|
||||
TextSize = 20
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = beatmapSet.Metadata.Artist ?? beatmapSet.Metadata.ArtistUnicode,
|
||||
TextSize = 16
|
||||
},
|
||||
new FlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
new DifficultyIcon(FontAwesome.dot_circle_o, new Color4(159, 198, 0, 255)),
|
||||
new DifficultyIcon(FontAwesome.dot_circle_o, new Color4(246, 101, 166, 255)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
30
osu.Game/Beatmaps/Drawable/DifficultyIcon.cs
Normal file
30
osu.Game/Beatmaps/Drawable/DifficultyIcon.cs
Normal file
@ -0,0 +1,30 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawable
|
||||
{
|
||||
class DifficultyIcon : Container
|
||||
{
|
||||
public DifficultyIcon(FontAwesome icon, Color4 color)
|
||||
{
|
||||
const float size = 20;
|
||||
Size = new Vector2(size);
|
||||
Children = new[]
|
||||
{
|
||||
new TextAwesome
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
TextSize = size,
|
||||
Colour = color,
|
||||
Icon = icon
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -23,4 +23,4 @@ namespace osu.Game.Beatmaps.Formats
|
||||
|
||||
public abstract Beatmap Decode(TextReader stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ namespace osu.Game.Beatmaps.Formats
|
||||
AddDecoder<OsuLegacyDecoder>(@"osu file format v12");
|
||||
AddDecoder<OsuLegacyDecoder>(@"osu file format v11");
|
||||
AddDecoder<OsuLegacyDecoder>(@"osu file format v10");
|
||||
AddDecoder<OsuLegacyDecoder>(@"osu file format v9");
|
||||
// TODO: Not sure how far back to go, or differences between versions
|
||||
}
|
||||
|
||||
@ -213,7 +214,11 @@ namespace osu.Game.Beatmaps.Formats
|
||||
HitObjects = new List<HitObject>(),
|
||||
ControlPoints = new List<ControlPoint>(),
|
||||
ComboColors = new List<Color4>(),
|
||||
BeatmapInfo = new BeatmapInfo(),
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata(),
|
||||
BaseDifficulty = new BaseDifficulty(),
|
||||
},
|
||||
};
|
||||
|
||||
var section = Section.None;
|
||||
@ -223,7 +228,6 @@ namespace osu.Game.Beatmaps.Formats
|
||||
line = stream.ReadLine();
|
||||
if (line == null)
|
||||
break;
|
||||
line = line.Trim();
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
if (line.StartsWith(@"osu file format v"))
|
||||
@ -274,4 +278,4 @@ namespace osu.Game.Beatmaps.Formats
|
||||
return beatmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,13 +19,15 @@ namespace osu.Game.Beatmaps.IO
|
||||
});
|
||||
OsuLegacyDecoder.Register();
|
||||
}
|
||||
|
||||
private ZipFile archive { get; set; }
|
||||
private string[] beatmaps { get; set; }
|
||||
private Beatmap firstMap { get; set; }
|
||||
|
||||
private Stream archiveStream;
|
||||
private ZipFile archive;
|
||||
private string[] beatmaps;
|
||||
private Beatmap firstMap;
|
||||
|
||||
public OszArchiveReader(Stream archiveStream)
|
||||
{
|
||||
this.archiveStream = archiveStream;
|
||||
archive = ZipFile.Read(archiveStream);
|
||||
beatmaps = archive.Entries.Where(e => e.FileName.EndsWith(@".osu"))
|
||||
.Select(e => e.FileName).ToArray();
|
||||
@ -59,6 +61,7 @@ namespace osu.Game.Beatmaps.IO
|
||||
public override void Dispose()
|
||||
{
|
||||
archive.Dispose();
|
||||
archiveStream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,15 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Security.Cryptography;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Beatmaps.IO;
|
||||
using osu.Game.IPC;
|
||||
using SQLite.Net;
|
||||
using SQLiteNetExtensions.Extensions;
|
||||
|
||||
@ -14,67 +17,96 @@ namespace osu.Game.Database
|
||||
{
|
||||
public class BeatmapDatabase
|
||||
{
|
||||
private static SQLiteConnection connection { get; set; }
|
||||
public static SQLiteConnection Connection { get; set; }
|
||||
private BasicStorage storage;
|
||||
|
||||
public BeatmapDatabase(BasicStorage storage)
|
||||
public event Action<BeatmapSetInfo> BeatmapSetAdded;
|
||||
|
||||
private BeatmapImporter ipc;
|
||||
|
||||
public BeatmapDatabase(BasicGameHost host)
|
||||
{
|
||||
this.storage = storage;
|
||||
if (connection == null)
|
||||
this.storage = host.Storage;
|
||||
|
||||
ipc = new BeatmapImporter(host, this);
|
||||
|
||||
if (Connection == null)
|
||||
{
|
||||
connection = storage.GetDatabase(@"beatmaps");
|
||||
connection.CreateTable<BeatmapMetadata>();
|
||||
connection.CreateTable<BaseDifficulty>();
|
||||
connection.CreateTable<BeatmapSetInfo>();
|
||||
connection.CreateTable<BeatmapInfo>();
|
||||
Connection = storage.GetDatabase(@"beatmaps");
|
||||
Connection.CreateTable<BeatmapMetadata>();
|
||||
Connection.CreateTable<BaseDifficulty>();
|
||||
Connection.CreateTable<BeatmapSetInfo>();
|
||||
Connection.CreateTable<BeatmapInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
public void ImportBeatmap(string path)
|
||||
public void Reset()
|
||||
{
|
||||
string hash = null;
|
||||
var reader = ArchiveReader.GetReader(storage, path);
|
||||
var metadata = reader.ReadMetadata();
|
||||
if (connection.Table<BeatmapSetInfo>().Count(b => b.BeatmapSetID == metadata.BeatmapSetID) != 0)
|
||||
return; // TODO: Update this beatmap instead
|
||||
if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader
|
||||
foreach (var setInfo in Query<BeatmapSetInfo>())
|
||||
storage.Delete(setInfo.Path);
|
||||
|
||||
Connection.DeleteAll<BeatmapMetadata>();
|
||||
Connection.DeleteAll<BaseDifficulty>();
|
||||
Connection.DeleteAll<BeatmapSetInfo>();
|
||||
Connection.DeleteAll<BeatmapInfo>();
|
||||
}
|
||||
|
||||
public void Import(params string[] paths)
|
||||
{
|
||||
foreach (string p in paths)
|
||||
{
|
||||
using (var md5 = MD5.Create())
|
||||
using (var input = storage.GetStream(path))
|
||||
var path = p;
|
||||
string hash = null;
|
||||
|
||||
BeatmapMetadata metadata;
|
||||
|
||||
using (var reader = ArchiveReader.GetReader(storage, path))
|
||||
metadata = reader.ReadMetadata();
|
||||
|
||||
if (Connection.Table<BeatmapSetInfo>().Count(b => b.BeatmapSetID == metadata.BeatmapSetID) != 0)
|
||||
return; // TODO: Update this beatmap instead
|
||||
|
||||
if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader
|
||||
{
|
||||
hash = BitConverter.ToString(md5.ComputeHash(input)).Replace("-", "").ToLowerInvariant();
|
||||
input.Seek(0, SeekOrigin.Begin);
|
||||
var outputPath = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash);
|
||||
using (var output = storage.GetStream(outputPath, FileAccess.Write))
|
||||
input.CopyTo(output);
|
||||
using (var md5 = MD5.Create())
|
||||
using (var input = storage.GetStream(path))
|
||||
{
|
||||
hash = BitConverter.ToString(md5.ComputeHash(input)).Replace("-", "").ToLowerInvariant();
|
||||
input.Seek(0, SeekOrigin.Begin);
|
||||
path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash);
|
||||
using (var output = storage.GetStream(path, FileAccess.Write))
|
||||
input.CopyTo(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
string[] mapNames = reader.ReadBeatmaps();
|
||||
var beatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
BeatmapSetID = metadata.BeatmapSetID,
|
||||
Path = path,
|
||||
Hash = hash,
|
||||
};
|
||||
var maps = new List<BeatmapInfo>();
|
||||
foreach (var name in mapNames)
|
||||
{
|
||||
using (var stream = new StreamReader(reader.ReadFile(name)))
|
||||
var beatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
Beatmap beatmap = decoder.Decode(stream);
|
||||
beatmap.BeatmapInfo.Path = name;
|
||||
// TODO: Diff beatmap metadata with set metadata and insert if necessary
|
||||
beatmap.BeatmapInfo.Metadata = null;
|
||||
maps.Add(beatmap.BeatmapInfo);
|
||||
connection.Insert(beatmap.BeatmapInfo.BaseDifficulty);
|
||||
connection.Insert(beatmap.BeatmapInfo);
|
||||
connection.UpdateWithChildren(beatmap.BeatmapInfo);
|
||||
BeatmapSetID = metadata.BeatmapSetID,
|
||||
Beatmaps = new List<BeatmapInfo>(),
|
||||
Path = path,
|
||||
Hash = hash,
|
||||
Metadata = metadata
|
||||
};
|
||||
|
||||
using (var reader = ArchiveReader.GetReader(storage, path))
|
||||
{
|
||||
string[] mapNames = reader.ReadBeatmaps();
|
||||
foreach (var name in mapNames)
|
||||
{
|
||||
using (var stream = new StreamReader(reader.ReadFile(name)))
|
||||
{
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
Beatmap beatmap = decoder.Decode(stream);
|
||||
beatmap.BeatmapInfo.Path = name;
|
||||
|
||||
// TODO: Diff beatmap metadata with set metadata and leave it here if necessary
|
||||
beatmap.BeatmapInfo.Metadata = null;
|
||||
|
||||
beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
Connection.InsertWithChildren(beatmapSet, true);
|
||||
BeatmapSetAdded?.Invoke(beatmapSet);
|
||||
}
|
||||
connection.Insert(beatmapSet);
|
||||
beatmapSet.BeatmapMetadataID = connection.Insert(metadata);
|
||||
connection.UpdateWithChildren(beatmapSet);
|
||||
}
|
||||
|
||||
public ArchiveReader GetReader(BeatmapSetInfo beatmapSet)
|
||||
@ -104,7 +136,26 @@ namespace osu.Game.Database
|
||||
|
||||
public TableQuery<T> Query<T>() where T : class
|
||||
{
|
||||
return connection.Table<T>();
|
||||
return Connection.Table<T>();
|
||||
}
|
||||
|
||||
public T GetWithChildren<T>(object id) where T : class
|
||||
{
|
||||
return Connection.GetWithChildren<T>(id);
|
||||
}
|
||||
|
||||
public List<T> GetAllWithChildren<T>(Expression<Func<T, bool>> filter = null,
|
||||
bool recursive = true) where T : class
|
||||
{
|
||||
return Connection.GetAllWithChildren<T>(filter, recursive);
|
||||
}
|
||||
|
||||
public T GetChildren<T>(T item, bool recursive = true)
|
||||
{
|
||||
if (item == null) return default(T);
|
||||
|
||||
Connection.GetChildren(item, recursive);
|
||||
return item;
|
||||
}
|
||||
|
||||
readonly Type[] validTypes = new[]
|
||||
@ -114,15 +165,15 @@ namespace osu.Game.Database
|
||||
typeof(BeatmapMetadata),
|
||||
typeof(BaseDifficulty),
|
||||
};
|
||||
|
||||
|
||||
public void Update<T>(T record, bool cascade = true) where T : class
|
||||
{
|
||||
if (!validTypes.Any(t => t == typeof(T)))
|
||||
throw new ArgumentException(nameof(T), "Must be a type managed by BeatmapDatabase");
|
||||
if (cascade)
|
||||
connection.UpdateWithChildren(record);
|
||||
Connection.UpdateWithChildren(record);
|
||||
else
|
||||
connection.Update(record);
|
||||
Connection.Update(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,23 +9,25 @@ namespace osu.Game.Database
|
||||
{
|
||||
public class BeatmapInfo
|
||||
{
|
||||
public BeatmapInfo()
|
||||
{
|
||||
BaseDifficulty = new BaseDifficulty();
|
||||
Metadata = new BeatmapMetadata();
|
||||
}
|
||||
|
||||
[PrimaryKey]
|
||||
public int BeatmapID { get; set; }
|
||||
[NotNull, Indexed]
|
||||
public int BeatmapID { get; set; }
|
||||
|
||||
[ForeignKey(typeof(BeatmapSetInfo))]
|
||||
public int BeatmapSetID { get; set; }
|
||||
|
||||
[ManyToOne]
|
||||
public BeatmapSetInfo BeatmapSet { get; set; }
|
||||
|
||||
[ForeignKey(typeof(BeatmapMetadata))]
|
||||
public int BeatmapMetadataID { get; set; }
|
||||
|
||||
[OneToOne(CascadeOperations = CascadeOperation.All)]
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
|
||||
[ForeignKey(typeof(BaseDifficulty)), NotNull]
|
||||
public int BaseDifficultyID { get; set; }
|
||||
[OneToOne]
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
[OneToOne]
|
||||
|
||||
[OneToOne(CascadeOperations = CascadeOperation.All)]
|
||||
public BaseDifficulty BaseDifficulty { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
|
@ -8,7 +8,7 @@ namespace osu.Game.Database
|
||||
{
|
||||
public class BeatmapMetadata
|
||||
{
|
||||
[PrimaryKey]
|
||||
[PrimaryKey, AutoIncrement]
|
||||
public int ID { get; set; }
|
||||
|
||||
public int BeatmapSetID { get; set; }
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using SQLite.Net.Attributes;
|
||||
using System.Collections.Generic;
|
||||
using SQLite.Net.Attributes;
|
||||
using SQLiteNetExtensions.Attributes;
|
||||
|
||||
namespace osu.Game.Database
|
||||
@ -7,12 +8,19 @@ namespace osu.Game.Database
|
||||
public class BeatmapSetInfo
|
||||
{
|
||||
[PrimaryKey]
|
||||
public int BeatmapSetID { get; set; }
|
||||
[OneToOne]
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
[NotNull, ForeignKey(typeof(BeatmapMetadata))]
|
||||
public int BeatmapSetID { get; set; }
|
||||
|
||||
[OneToOne(CascadeOperations = CascadeOperation.All)]
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
|
||||
[NotNull, ForeignKey(typeof(BeatmapMetadata))]
|
||||
public int BeatmapMetadataID { get; set; }
|
||||
public string Hash { get; set; }
|
||||
|
||||
[OneToMany(CascadeOperations = CascadeOperation.All)]
|
||||
public List<BeatmapInfo> Beatmaps { get; set; }
|
||||
|
||||
public string Hash { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace osu.Game.GameModes.Play.Osu
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuPlayfield();
|
||||
|
||||
protected override DrawableHitObject GetVisualRepresentation(OsuBaseHit h) => new DrawableCircle(h as Circle);
|
||||
protected override DrawableHitObject GetVisualRepresentation(OsuBaseHit h)
|
||||
=> h is Circle ? new DrawableCircle(h as Circle) : null;
|
||||
}
|
||||
}
|
||||
|
@ -2,43 +2,173 @@
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.GameModes.Backgrounds;
|
||||
using osu.Framework;
|
||||
using osu.Game.Database;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Game.Beatmaps.Drawable;
|
||||
|
||||
namespace osu.Game.GameModes.Play
|
||||
{
|
||||
class PlaySongSelect : GameModeWhiteBox
|
||||
public class PlaySongSelect : OsuGameMode
|
||||
{
|
||||
private Bindable<PlayMode> playMode;
|
||||
|
||||
private BeatmapDatabase beatmaps;
|
||||
private BeatmapGroup selectedBeatmapGroup;
|
||||
private BeatmapInfo selectedBeatmap;
|
||||
// TODO: use currently selected track as bg
|
||||
protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4");
|
||||
private ScrollContainer scrollContainer;
|
||||
private FlowContainer setList;
|
||||
|
||||
protected override IEnumerable<Type> PossibleChildren => new[] {
|
||||
typeof(ModSelect),
|
||||
typeof(Player)
|
||||
};
|
||||
public PlaySongSelect()
|
||||
{
|
||||
const float scrollWidth = 640;
|
||||
const float bottomToolHeight = 50;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = Vector2.One,
|
||||
Padding = new MarginPadding { Right = scrollWidth - 200 },
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(1, 0.5f),
|
||||
Colour = new Color4(0, 0, 0, 0.5f),
|
||||
Shear = new Vector2(0.15f, 0),
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Size = new Vector2(1, -0.5f),
|
||||
Position = new Vector2(0, 1),
|
||||
Colour = new Color4(0, 0, 0, 0.5f),
|
||||
Shear = new Vector2(-0.15f, 0),
|
||||
},
|
||||
}
|
||||
},
|
||||
scrollContainer = new ScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Size = new Vector2(scrollWidth, 1),
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
setList = new FlowContainer
|
||||
{
|
||||
Padding = new MarginPadding { Left = 25, Top = 25, Bottom = 25 + bottomToolHeight },
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FlowDirection.VerticalOnly,
|
||||
Spacing = new Vector2(0, 5),
|
||||
}
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = bottomToolHeight,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = Vector2.One,
|
||||
Colour = new Color4(0, 0, 0, 0.5f),
|
||||
},
|
||||
new Button
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 100,
|
||||
Text = "Play",
|
||||
Colour = new Color4(238, 51, 153, 255),
|
||||
Action = () => Push(new Player { Beatmap = beatmaps.GetBeatmap(selectedBeatmap) }),
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override void Load(BaseGame game)
|
||||
{
|
||||
base.Load(game);
|
||||
|
||||
OsuGame osu = game as OsuGame;
|
||||
OsuGame osuGame = game as OsuGame;
|
||||
if (osuGame != null)
|
||||
{
|
||||
playMode = osuGame.PlayMode;
|
||||
playMode.ValueChanged += PlayMode_ValueChanged;
|
||||
// Temporary:
|
||||
scrollContainer.Padding = new MarginPadding { Top = osuGame.Toolbar.Height };
|
||||
}
|
||||
|
||||
playMode = osu.PlayMode;
|
||||
playMode.ValueChanged += PlayMode_ValueChanged;
|
||||
beatmaps = (game as OsuGameBase).Beatmaps;
|
||||
beatmaps.BeatmapSetAdded += bset => Scheduler.Add(() => addBeatmapSet(bset));
|
||||
Task.Factory.StartNew(addBeatmapSets);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
playMode.ValueChanged -= PlayMode_ValueChanged;
|
||||
if (playMode != null)
|
||||
playMode.ValueChanged -= PlayMode_ValueChanged;
|
||||
}
|
||||
|
||||
private void PlayMode_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void selectBeatmap(BeatmapGroup group, BeatmapInfo beatmap)
|
||||
{
|
||||
if (selectedBeatmapGroup == group)
|
||||
return;
|
||||
|
||||
if (selectedBeatmapGroup != null)
|
||||
selectedBeatmapGroup.State = BeatmapGroupState.Collapsed;
|
||||
|
||||
selectedBeatmapGroup = group;
|
||||
selectedBeatmap = beatmap;
|
||||
}
|
||||
|
||||
private void addBeatmapSet(BeatmapSetInfo beatmapSet)
|
||||
{
|
||||
beatmapSet = beatmaps.GetWithChildren<BeatmapSetInfo>(beatmapSet.BeatmapSetID);
|
||||
beatmapSet.Beatmaps.ForEach(b => beatmaps.GetChildren(b));
|
||||
beatmapSet.Beatmaps = beatmapSet.Beatmaps.OrderBy(b => b.BaseDifficulty.OverallDifficulty).ToList();
|
||||
Schedule(() =>
|
||||
{
|
||||
var group = new BeatmapGroup(beatmapSet) { SelectionChanged = selectBeatmap };
|
||||
setList.Add(group);
|
||||
if (setList.Children.Count() == 1)
|
||||
{
|
||||
group.State = BeatmapGroupState.Expanded;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addBeatmapSets()
|
||||
{
|
||||
foreach (var beatmapSet in beatmaps.Query<BeatmapSetInfo>())
|
||||
addBeatmapSet(beatmapSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
osu.Game/IPC/BeatmapImporter.cs
Normal file
46
osu.Game/IPC/BeatmapImporter.cs
Normal file
@ -0,0 +1,46 @@
|
||||
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
|
||||
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.IPC
|
||||
{
|
||||
public class BeatmapImporter
|
||||
{
|
||||
private IpcChannel<BeatmapImportMessage> channel;
|
||||
private BeatmapDatabase beatmaps;
|
||||
|
||||
public BeatmapImporter(BasicGameHost host, BeatmapDatabase beatmaps = null)
|
||||
{
|
||||
this.beatmaps = beatmaps;
|
||||
|
||||
channel = new IpcChannel<BeatmapImportMessage>(host);
|
||||
channel.MessageReceived += messageReceived;
|
||||
}
|
||||
|
||||
public async Task Import(string path)
|
||||
{
|
||||
if (beatmaps != null)
|
||||
beatmaps.Import(path);
|
||||
else
|
||||
{
|
||||
await channel.SendMessage(new BeatmapImportMessage { Path = path });
|
||||
}
|
||||
}
|
||||
|
||||
private void messageReceived(BeatmapImportMessage msg)
|
||||
{
|
||||
Debug.Assert(beatmaps != null);
|
||||
|
||||
Import(msg.Path);
|
||||
}
|
||||
}
|
||||
|
||||
public class BeatmapImportMessage
|
||||
{
|
||||
public string Path;
|
||||
}
|
||||
}
|
@ -9,19 +9,13 @@ using osu.Game.GameModes.Menu;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.GameModes;
|
||||
using osu.Game.Graphics.Background;
|
||||
using osu.Game.GameModes.Play;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Input;
|
||||
using OpenTK.Input;
|
||||
using System.IO;
|
||||
using osu.Game.Beatmaps.IO;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Graphics.UserInterface.Volume;
|
||||
|
||||
@ -29,23 +23,18 @@ namespace osu.Game
|
||||
{
|
||||
public class OsuGame : OsuGameBase
|
||||
{
|
||||
private class ImportBeatmap
|
||||
{
|
||||
public string Path;
|
||||
}
|
||||
|
||||
public Toolbar Toolbar;
|
||||
public ChatConsole Chat;
|
||||
public MainMenu MainMenu => intro?.ChildGameMode as MainMenu;
|
||||
private Intro intro;
|
||||
private string[] args;
|
||||
private IpcChannel<ImportBeatmap> BeatmapIPC;
|
||||
|
||||
private VolumeControl volume;
|
||||
|
||||
public Bindable<PlayMode> PlayMode;
|
||||
|
||||
public OsuGame(string[] args)
|
||||
string[] args;
|
||||
|
||||
public OsuGame(string[] args = null)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
@ -59,36 +48,17 @@ namespace osu.Game
|
||||
|
||||
public override void Load(BaseGame game)
|
||||
{
|
||||
BeatmapIPC = new IpcChannel<ImportBeatmap>(Host);
|
||||
|
||||
if (!Host.IsPrimaryInstance)
|
||||
{
|
||||
if (args.Length == 1 && File.Exists(args[0]))
|
||||
{
|
||||
BeatmapIPC.SendMessage(new ImportBeatmap { Path = args[0] }).Wait();
|
||||
Logger.Log(@"Sent file to running instance");
|
||||
}
|
||||
else
|
||||
Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error);
|
||||
Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
BeatmapIPC.MessageReceived += message =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Beatmaps.ImportBeatmap(message.Path);
|
||||
// TODO: Switch to beatmap list and select the new song
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// TODO: Show the user some info?
|
||||
Logger.Log($@"Failed to import beatmap: {ex}", LoggingTarget.Runtime, LogLevel.Error);
|
||||
}
|
||||
};
|
||||
|
||||
base.Load(game);
|
||||
|
||||
if (args?.Length > 0)
|
||||
Schedule(delegate { Beatmaps.Import(args); });
|
||||
|
||||
//attach our bindables to the audio subsystem.
|
||||
Audio.Volume.Weld(Config.GetBindable<double>(OsuConfig.VolumeGlobal));
|
||||
Audio.VolumeSample.Weld(Config.GetBindable<double>(OsuConfig.VolumeEffect));
|
||||
|
@ -10,6 +10,7 @@ using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Graphics.Processing;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
@ -18,7 +19,7 @@ namespace osu.Game
|
||||
public class OsuGameBase : BaseGame
|
||||
{
|
||||
internal OsuConfigManager Config = new OsuConfigManager();
|
||||
internal BeatmapDatabase Beatmaps { get; private set; }
|
||||
public BeatmapDatabase Beatmaps { get; private set; }
|
||||
|
||||
protected override string MainResourceFile => @"osu.Game.Resources.dll";
|
||||
|
||||
@ -47,7 +48,7 @@ namespace osu.Game
|
||||
base.Load(game);
|
||||
|
||||
OszArchiveReader.Register();
|
||||
Beatmaps = new BeatmapDatabase(Host.Storage);
|
||||
Beatmaps = new BeatmapDatabase(Host);
|
||||
|
||||
//this completely overrides the framework default. will need to change once we make a proper FontStore.
|
||||
Fonts = new TextureStore() { ScaleAdjust = 0.01f };
|
||||
@ -72,8 +73,11 @@ namespace osu.Game
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
//refresh token may have changed.
|
||||
Config.Set(OsuConfig.Token, API.Token);
|
||||
Config.Save();
|
||||
if (Config != null && API != null)
|
||||
{
|
||||
Config.Set(OsuConfig.Token, API.Token);
|
||||
Config.Save();
|
||||
}
|
||||
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
|
@ -64,6 +64,8 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Beatmaps\Beatmap.cs" />
|
||||
<Compile Include="Beatmaps\Drawable\BeatmapSetHeader.cs" />
|
||||
<Compile Include="Beatmaps\Drawable\DifficultyIcon.cs" />
|
||||
<Compile Include="Beatmaps\Objects\Catch\CatchConverter.cs" />
|
||||
<Compile Include="Beatmaps\Objects\Catch\Drawable\DrawableFruit.cs" />
|
||||
<Compile Include="Beatmaps\Objects\DrawableHitObject.cs" />
|
||||
@ -116,6 +118,8 @@
|
||||
<Compile Include="GameModes\OsuGameMode.cs" />
|
||||
<Compile Include="GameModes\Play\ModSelect.cs" />
|
||||
<Compile Include="GameModes\Play\Osu\ScoreOverlayOsu.cs" />
|
||||
<Compile Include="Beatmaps\Drawable\BeatmapGroup.cs" />
|
||||
<Compile Include="Beatmaps\Drawable\BeatmapPanel.cs" />
|
||||
<Compile Include="GameModes\Play\Player.cs" />
|
||||
<Compile Include="GameModes\Charts\ChartListing.cs" />
|
||||
<Compile Include="GameModes\Play\PlayMode.cs" />
|
||||
@ -155,6 +159,7 @@
|
||||
<Compile Include="GameModes\Play\Catch\CatchComboCounter.cs" />
|
||||
<Compile Include="GameModes\Play\Osu\OsuComboCounter.cs" />
|
||||
<Compile Include="Graphics\UserInterface\StarCounter.cs" />
|
||||
<Compile Include="IPC\BeatmapImporter.cs" />
|
||||
<Compile Include="Online\API\APIAccess.cs" />
|
||||
<Compile Include="Online\API\APIRequest.cs" />
|
||||
<Compile Include="Online\API\OAuth.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user