1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-18 13:20:32 +08:00

Compare commits

...

720 Commits

348 changed files with 11942 additions and 3776 deletions
+14 -2
View File
@@ -2,13 +2,25 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"name": "Launch VisualTests",
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/osu.Desktop.VisualTests/bin/Debug/osu!.exe",
"args": [],
"cwd": "${workspaceRoot}",
"preLaunchTask": "",
"preLaunchTask": "build",
"runtimeExecutable": null,
"env": {},
"externalConsole": false
},
{
"name": "Launch Desktop",
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/osu.Desktop/bin/Debug/osu!.exe",
"args": [],
"cwd": "${workspaceRoot}",
"preLaunchTask": "build",
"runtimeExecutable": null,
"env": {},
"externalConsole": false
+9
View File
@@ -0,0 +1,9 @@
osu!lazer is currently in early stages of development and is not yet ready for end users. Please avoid creating issues or bugs if you do not personally intend to fix them. Some acceptable topics include:
- Discussions about technical design decisions
- Bugs that you have found and are personally willing and able to fix
- TODO lists of smaller tasks around larger features
Basically, issues are not a place for you to get help. They are a place for developers to collaborate on the game.
If your issue qualifies, replace this text with a detailed description of your issue with as much relevant information as you can provide.
+4
View File
@@ -6,6 +6,10 @@
Rhythm is just a *click* away. The future of osu! and the beginning of an open era!
# Status
This is still heavily under development and is not intended for end-user use. This repository is intended for developer collaboration. You're welcome to try and use it but please do not submit bug reports without a patch. Please do not ask for help building or using this software.
# Requirements
- A desktop platform which can compile .NET 4.5.
+33
View File
@@ -0,0 +1,33 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using NUnit.Framework;
using osu.Desktop.VisualTests;
using osu.Framework.Desktop.Platform;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
using osu.Game.Modes.Mania;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Taiko;
namespace osu.Desktop.Tests
{
[TestFixture]
public class BenchmarkTest
{
[Test]
public void TestBenchmark()
{
using (var host = new HeadlessGameHost())
{
Ruleset.Register(new OsuRuleset());
Ruleset.Register(new TaikoRuleset());
Ruleset.Register(new ManiaRuleset());
Ruleset.Register(new CatchRuleset());
host.Add(new Benchmark());
host.Run();
}
}
}
}
+11
View 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>
+117
View File
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>osu.Desktop.Tests</RootNamespace>
<AssemblyName>osu.Desktop.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<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>
<Private>True</Private>
</Reference>
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<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="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>
<Reference Include="OpenTK">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="BenchmarkTest.cs" />
</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-resources\osu.Game.Resources\osu.Game.Resources.csproj">
<Project>{d9a367c9-4c1a-489f-9b05-a0cea2b53b58}</Project>
<Name>osu.Game.Resources</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Desktop.VisualTests\osu.Desktop.VisualTests.csproj">
<Project>{69051C69-12AE-4E7D-A3E6-460D2E282312}</Project>
<Name>osu.Desktop.VisualTests</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Catch\osu.Game.Modes.Catch.csproj">
<Project>{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}</Project>
<Name>osu.Game.Modes.Catch</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Mania\osu.Game.Modes.Mania.csproj">
<Project>{48F4582B-7687-4621-9CBE-5C24197CB536}</Project>
<Name>osu.Game.Modes.Mania</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj">
<Project>{C92A607B-1FDD-4954-9F92-03FF547D9080}</Project>
<Name>osu.Game.Modes.Osu</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Taiko\osu.Game.Modes.Taiko.csproj">
<Project>{F167E17A-7DE6-4AF5-B920-A5112296C695}</Project>
<Name>osu.Game.Modes.Taiko</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
<Project>{0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}</Project>
<Name>osu.Game</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="NUnit" version="3.5.0" 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>
+56
View File
@@ -0,0 +1,56 @@
// 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 System.Linq;
using System.Text;
using System.Threading.Tasks;
using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Desktop.Platform;
using osu.Framework.GameModes.Testing;
using osu.Game;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
using osu.Game.Modes.Mania;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Taiko;
namespace osu.Desktop.VisualTests
{
public class Benchmark : OsuGameBase
{
private double timePerTest = 200;
[BackgroundDependencyLoader]
private void load(BaseGame game)
{
Host.MaximumDrawHz = int.MaxValue;
Host.MaximumUpdateHz = int.MaxValue;
Host.MaximumInactiveHz = int.MaxValue;
}
protected override void LoadComplete()
{
base.LoadComplete();
TestBrowser f = new TestBrowser();
Add(f);
Console.WriteLine($@"{Time}: Running {f.TestCount} tests for {timePerTest}ms each...");
for (int i = 1; i < f.TestCount; i++)
{
int loadableCase = i;
Scheduler.AddDelayed(delegate
{
f.LoadTest(loadableCase);
Console.WriteLine($@"{Time}: Switching to test #{loadableCase}");
}, loadableCase * timePerTest);
}
Scheduler.AddDelayed(Host.Exit, f.TestCount * timePerTest);
}
}
}
@@ -1,3 +1,8 @@
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
+28 -25
View File
@@ -1,26 +1,29 @@
using osu.Framework;
using osu.Framework.Desktop.Platform;
using SQLite.Net;
using SQLite.Net.Interop;
using SQLite.Net.Platform.Generic;
using SQLite.Net.Platform.Win32;
namespace osu.Desktop.VisualTests.Platform
{
public class TestStorage : DesktopStorage
{
public TestStorage(string baseName) : base(baseName)
{
}
public override SQLiteConnection GetDatabase(string name)
{
ISQLitePlatform platform;
if (RuntimeInfo.IsWindows)
platform = new SQLitePlatformWin32();
else
platform = new SQLitePlatformGeneric();
return new SQLiteConnection(platform, $@":memory:");
}
}
// 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;
using osu.Framework.Desktop.Platform;
using SQLite.Net;
using SQLite.Net.Interop;
using SQLite.Net.Platform.Generic;
using SQLite.Net.Platform.Win32;
namespace osu.Desktop.VisualTests.Platform
{
public class TestStorage : DesktopStorage
{
public TestStorage(string baseName) : base(baseName)
{
}
public override SQLiteConnection GetDatabase(string name)
{
ISQLitePlatform platform;
if (RuntimeInfo.IsWindows)
platform = new SQLitePlatformWin32();
else
platform = new SQLitePlatformGeneric();
return new SQLiteConnection(platform, $@":memory:");
}
}
}
+9 -4
View File
@@ -1,5 +1,5 @@
// Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE
// 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 osu.Framework.Desktop;
@@ -18,14 +18,19 @@ namespace osu.Desktop.VisualTests
[STAThread]
public static void Main(string[] args)
{
using (BasicGameHost host = Host.GetSuitableHost(@"osu-visual-tests"))
bool benchmark = args.Length > 0 && args[0] == @"-benchmark";
using (BasicGameHost host = Host.GetSuitableHost(@"osu"))
{
Ruleset.Register(new OsuRuleset());
Ruleset.Register(new TaikoRuleset());
Ruleset.Register(new ManiaRuleset());
Ruleset.Register(new CatchRuleset());
host.Add(new VisualTestGame());
if (benchmark)
host.Add(new Benchmark());
else
host.Add(new VisualTestGame());
host.Run();
}
}
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Collections.Generic;
using System.Diagnostics;
@@ -14,9 +14,9 @@ using osu.Game;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.Chat;
using osu.Game.Online.Chat.Display;
using OpenTK;
using osu.Framework.Allocation;
using osu.Game.Online.Chat.Drawables;
namespace osu.Desktop.VisualTests.Tests
{
@@ -45,7 +45,7 @@ namespace osu.Desktop.VisualTests.Tests
{
base.Reset();
if (api.State != APIAccess.APIState.Online)
if (api.State != APIState.Online)
api.OnStateChange += delegate { initializeChannels(); };
else
initializeChannels();
@@ -65,7 +65,7 @@ namespace osu.Desktop.VisualTests.Tests
{
careChannels = new List<Channel>();
if (api.State != APIAccess.APIState.Online)
if (api.State != APIState.Online)
return;
Add(flow = new FlowContainer
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Collections.Generic;
using osu.Framework.GameModes.Testing;
@@ -42,7 +42,8 @@ namespace osu.Desktop.VisualTests.Tests
objects.Add(new HitCircle()
{
StartTime = time,
Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384))
Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)),
Scale = RNG.NextSingle(0.5f, 1.0f),
});
time += RNG.Next(50, 500);
@@ -57,39 +58,33 @@ namespace osu.Desktop.VisualTests.Tests
{
new OsuHitRenderer
{
Objects = beatmap.HitObjects,
Beatmap = beatmap,
Scale = new Vector2(0.5f),
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft
},
new TaikoHitRenderer
{
Objects = beatmap.HitObjects,
Beatmap = beatmap,
Scale = new Vector2(0.5f),
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight
},
new CatchHitRenderer
{
Objects = beatmap.HitObjects,
Beatmap = beatmap,
Scale = new Vector2(0.5f),
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft
},
new ManiaHitRenderer
{
Objects = beatmap.HitObjects,
Beatmap = beatmap,
Scale = new Vector2(0.5f),
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight
}
});
}
protected override void Update()
{
base.Update();
Clock.ProcessFrame();
}
}
}
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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;
using osu.Framework.GameModes.Testing;
@@ -12,6 +12,7 @@ using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.Objects.Drawables;
using osu.Framework.Graphics.Containers;
using osu.Game.Modes;
namespace osu.Desktop.VisualTests.Tests
{
@@ -21,7 +22,7 @@ namespace osu.Desktop.VisualTests.Tests
public TestCaseHitObjects()
{
var swClock = new StopwatchClock(true) { Rate = 1 };
var swClock = new StopwatchClock(true) { Rate = 0.2f };
Clock = new FramedClock(swClock);
}
@@ -31,7 +32,7 @@ namespace osu.Desktop.VisualTests.Tests
Clock.ProcessFrame();
Container approachContainer = new Container { Depth = float.MaxValue, };
Container approachContainer = new Container { Depth = float.MinValue, };
Add(approachContainer);
@@ -41,27 +42,22 @@ namespace osu.Desktop.VisualTests.Tests
{
var h = new HitCircle
{
StartTime = Clock.CurrentTime + 1000 + i * 80,
StartTime = Clock.CurrentTime + 600 + i * 80,
Position = new Vector2((i - count / 2) * 14),
};
DrawableHitCircle d = new DrawableHitCircle(h)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Depth = -i,
State = ArmedState.Armed,
Depth = i,
State = ArmedState.Hit,
Judgement = new OsuJudgementInfo { Result = HitResult.Hit }
};
approachContainer.Add(d.ApproachCircle.CreateProxy());
Add(d);
}
}
protected override void Update()
{
base.Update();
Clock.ProcessFrame();
}
}
}
@@ -1,10 +1,19 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.GameModes.Testing;
using osu.Framework.Graphics;
using osu.Game.Graphics.UserInterface;
using OpenTK.Input;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Configuration;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.MathUtils;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
@@ -18,22 +27,68 @@ namespace osu.Desktop.VisualTests.Tests
{
base.Reset();
Children = new[]
KeyCounterCollection kc = new KeyCounterCollection
{
new KeyCounterCollection
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
IsCounting = true,
Children = new KeyCounter[]
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
IsCounting = true,
Counters = new KeyCounter[]
{
new KeyCounterKeyboard(@"Z", Key.Z),
new KeyCounterKeyboard(@"X", Key.X),
new KeyCounterMouse(@"M1", MouseButton.Left),
new KeyCounterMouse(@"M2", MouseButton.Right),
},
new KeyCounterKeyboard(@"Z", Key.Z),
new KeyCounterKeyboard(@"X", Key.X),
new KeyCounterMouse(@"M1", MouseButton.Left),
new KeyCounterMouse(@"M2", MouseButton.Right),
},
};
BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 };
bindable.ValueChanged += delegate { kc.FadeTime = bindable.Value; };
AddButton("Add Random", () =>
{
Key key = (Key)((int)Key.A + RNG.Next(26));
kc.Add(new KeyCounterKeyboard(key.ToString(), key));
});
ButtonsContainer.Add(new SpriteText { Text = "FadeTime" });
ButtonsContainer.Add(new TestSliderBar<int>
{
Width = 150,
Height = 10,
SelectionColor = Color4.Orange,
Bindable = bindable
});
Add(kc);
}
private class TestSliderBar<T> : SliderBar<T> where T : struct
{
public Color4 Color
{
get { return Box.Colour; }
set { Box.Colour = value; }
}
public Color4 SelectionColor
{
get { return SelectionBox.Colour; }
set { SelectionBox.Colour = value; }
}
protected readonly Box SelectionBox;
protected readonly Box Box;
public TestSliderBar()
{
Children = new Drawable[]
{
Box = new Box { RelativeSizeAxes = Axes.Both },
SelectionBox = new Box { RelativeSizeAxes = Axes.Both }
};
}
protected override void UpdateValue(float value)
{
SelectionBox.ScaleTo(
new Vector2(value, 1),
300, EasingTypes.OutQuint);
}
}
}
}
@@ -1,8 +1,11 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.GameModes.Testing;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Sprites;
using osu.Game.Screens.Menu;
using OpenTK.Graphics;
namespace osu.Desktop.VisualTests.Tests
{
@@ -15,6 +18,11 @@ namespace osu.Desktop.VisualTests.Tests
{
base.Reset();
Add(new Box
{
ColourInfo = ColourInfo.GradientVertical(Color4.Gray, Color4.WhiteSmoke),
RelativeSizeAxes = Framework.Graphics.Axes.Both,
});
Add(new ButtonSystem());
}
}
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.GameModes.Testing;
using osu.Framework.Graphics;
@@ -13,7 +13,7 @@ namespace osu.Desktop.VisualTests.Tests
public override string Name => @"Music Controller";
public override string Description => @"Tests music controller ui.";
protected MusicController mc;
private MusicController mc;
public TestCaseMusicController()
{
@@ -32,11 +32,5 @@ namespace osu.Desktop.VisualTests.Tests
Add(mc);
AddToggle(@"Show", mc.ToggleVisibility);
}
protected override void Update()
{
base.Update();
Clock.ProcessFrame();
}
}
}
@@ -0,0 +1,121 @@
// 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.Collections.Generic;
using osu.Framework.Graphics;
using osu.Framework.GameModes.Testing;
using osu.Framework.MathUtils;
using osu.Framework.Timing;
using osu.Game.Overlays;
using System.Linq;
using osu.Game.Overlays.Notifications;
using osu.Game.Screens.Backgrounds;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseNotificationManager : TestCase
{
public override string Name => @"Notification Manager";
public override string Description => @"I handle notifications";
NotificationManager manager;
public override void Reset()
{
base.Reset();
progressingNotifications.Clear();
AddInternal(new BackgroundModeDefault() { Depth = 10 });
Content.Add(manager = new NotificationManager
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
});
AddToggle(@"show", manager.ToggleVisibility);
AddButton(@"simple #1", sendNotification1);
AddButton(@"simple #2", sendNotification2);
AddButton(@"progress #1", sendProgress1);
AddButton(@"progress #2", sendProgress2);
AddButton(@"barrage", () => sendBarrage());
}
private void sendBarrage(int remaining = 100)
{
switch (RNG.Next(0, 4))
{
case 0:
sendNotification1();
break;
case 1:
sendNotification2();
break;
case 2:
sendProgress1();
break;
case 3:
sendProgress2();
break;
}
if (remaining > 0)
{
Delay(80);
Schedule(() => sendBarrage(remaining - 1));
}
}
protected override void Update()
{
base.Update();
progressingNotifications.RemoveAll(n => n.State == ProgressNotificationState.Completed);
while (progressingNotifications.Count(n => n.State == ProgressNotificationState.Active) < 3)
{
var p = progressingNotifications.FirstOrDefault(n => n.IsLoaded && n.State == ProgressNotificationState.Queued);
if (p == null)
break;
p.State = ProgressNotificationState.Active;
}
foreach (var n in progressingNotifications.FindAll(n => n.State == ProgressNotificationState.Active))
{
if (n.Progress < 1)
n.Progress += (float)(Time.Elapsed / 2000) * RNG.NextSingle();
else
n.Complete();
}
}
private void sendProgress2()
{
var n = new ProgressNotification(@"Downloading Haitai...");
manager.Post(n);
progressingNotifications.Add(n);
}
List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
private void sendProgress1()
{
var n = new ProgressNotification(@"Uploading to BSS...");
manager.Post(n);
progressingNotifications.Add(n);
}
private void sendNotification2()
{
manager.Post(new SimpleNotification(@"You are amazing"));
}
private void sendNotification1()
{
manager.Post(new SimpleNotification(@"Welcome to osu!. Enjoy your stay!"));
}
}
}
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.GameModes.Testing;
using osu.Framework.Graphics;
@@ -0,0 +1,47 @@
// 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.Graphics;
using osu.Framework.Logging;
using osu.Framework.Graphics;
using osu.Game.Overlays.Pause;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Colour;
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics.UserInterface;
namespace osu.Desktop.VisualTests.Tests
{
class TestCasePauseOverlay : TestCase
{
public override string Name => @"PauseOverlay";
public override string Description => @"Tests the pause overlay";
private PauseOverlay pauseOverlay;
private int retryCount;
public override void Reset()
{
base.Reset();
Add(pauseOverlay = new PauseOverlay
{
Depth = -1,
OnResume = () => Logger.Log(@"Resume"),
OnRetry = () => Logger.Log(@"Retry"),
OnQuit = () => Logger.Log(@"Quit")
});
AddButton("Pause", pauseOverlay.Show);
AddButton("Add Retry", delegate
{
retryCount++;
pauseOverlay.Retries = retryCount;
});
retryCount = 0;
}
}
}
@@ -1,31 +1,32 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Desktop.VisualTests.Platform;
using osu.Framework.GameModes.Testing;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Screens.Select;
namespace osu.Desktop.VisualTests.Tests
{
class TestCasePlaySongSelect : TestCase
{
private BeatmapDatabase db;
private TestStorage storage;
public override string Name => @"Song Select";
// 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.Collections.Generic;
using osu.Desktop.VisualTests.Platform;
using osu.Framework.GameModes.Testing;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Screens.Select;
namespace osu.Desktop.VisualTests.Tests
{
class TestCasePlaySongSelect : TestCase
{
private BeatmapDatabase db, oldDb;
private TestStorage storage;
public override string Name => @"Song Select";
public override string Description => @"with fake data";
public override void Reset()
{
public override void Reset()
{
base.Reset();
oldDb = Dependencies.Get<BeatmapDatabase>();
if (db == null)
{
storage = new TestStorage(@"TestCasePlaySongSelect");
db = new BeatmapDatabase(storage);
Dependencies.Cache(db, true);
var sets = new List<BeatmapSetInfo>();
@@ -34,20 +35,30 @@ namespace osu.Desktop.VisualTests.Tests
db.Import(sets);
}
Add(new PlaySongSelect());
}
protected override void Dispose(bool isDisposing)
{
if (oldDb != null)
{
Dependencies.Cache(oldDb, true);
db = null;
}
Add(new PlaySongSelect(db));
base.Dispose(isDisposing);
}
private BeatmapSetInfo createTestBeatmapSet(int i)
{
return new BeatmapSetInfo
{
BeatmapSetID = 1234 + i,
OnlineBeatmapSetID = 1234 + i,
Hash = "d8e8fca2dc0f896fd7cb4cb0031ba249",
Path = string.Empty,
Metadata = new BeatmapMetadata
{
BeatmapSetID = 1234 + i,
OnlineBeatmapSetID = 1234 + i,
Artist = "MONACA",
Title = "Black Song",
Author = "Some Guy",
@@ -56,7 +67,7 @@ namespace osu.Desktop.VisualTests.Tests
{
new BeatmapInfo
{
BeatmapID = 1234 + i,
OnlineBeatmapID = 1234 + i,
Mode = PlayMode.Osu,
Path = "normal.osu",
Version = "Normal",
@@ -67,7 +78,7 @@ namespace osu.Desktop.VisualTests.Tests
},
new BeatmapInfo
{
BeatmapID = 1235 + i,
OnlineBeatmapID = 1235 + i,
Mode = PlayMode.Osu,
Path = "hard.osu",
Version = "Hard",
@@ -78,7 +89,7 @@ namespace osu.Desktop.VisualTests.Tests
},
new BeatmapInfo
{
BeatmapID = 1236 + i,
OnlineBeatmapID = 1236 + i,
Mode = PlayMode.Osu,
Path = "insane.osu",
Version = "Insane",
@@ -89,6 +100,6 @@ namespace osu.Desktop.VisualTests.Tests
},
}),
};
}
}
}
}
}
}
+41 -32
View File
@@ -1,7 +1,8 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.GameModes.Testing;
using osu.Framework.MathUtils;
using osu.Framework.Timing;
@@ -9,6 +10,8 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using OpenTK;
using osu.Framework.Graphics.Sprites;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Screens.Play;
@@ -18,42 +21,53 @@ namespace osu.Desktop.VisualTests.Tests
{
class TestCasePlayer : TestCase
{
private WorkingBeatmap beatmap;
public override string Name => @"Player";
public override string Description => @"Showing everything to play the game.";
[BackgroundDependencyLoader]
private void load(BeatmapDatabase db)
{
var beatmapInfo = db.Query<BeatmapInfo>().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault();
if (beatmapInfo != null)
beatmap = db.GetWorkingBeatmap(beatmapInfo);
}
public override void Reset()
{
base.Reset();
//ensure we are at offset 0
Clock = new FramedClock();
var objects = new List<HitObject>();
int time = 1500;
for (int i = 0; i < 50; i++)
if (beatmap?.Track == null)
{
objects.Add(new HitCircle()
var objects = new List<HitObject>();
int time = 1500;
for (int i = 0; i < 50; i++)
{
StartTime = time,
Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512,
i % 4 < 2 ? 0 : 384),
NewCombo = i % 4 == 0
});
objects.Add(new HitCircle()
{
StartTime = time,
Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512,
i % 4 < 2 ? 0 : 384),
NewCombo = i % 4 == 0
});
time += 500;
time += 500;
}
var decoder = new ConstructableBeatmapDecoder();
Beatmap b = new Beatmap
{
HitObjects = objects
};
decoder.Process(b);
beatmap = new WorkingBeatmap(b);
}
var decoder = new ConstructableBeatmapDecoder();
Beatmap b = new Beatmap
{
HitObjects = objects
};
decoder.Process(b);
Add(new Box
{
RelativeSizeAxes = Framework.Graphics.Axes.Both,
@@ -62,14 +76,9 @@ namespace osu.Desktop.VisualTests.Tests
Add(new Player
{
Beatmap = new WorkingBeatmap(b)
PreferredPlayMode = PlayMode.Osu,
Beatmap = beatmap
});
}
protected override void Update()
{
base.Update();
Clock.ProcessFrame();
}
}
}
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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 osu.Framework.GameModes.Testing;
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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 osu.Framework.GameModes.Testing;
@@ -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 osu.Framework.GameModes.Testing;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Menu;
using osu.Game.Screens.Play;
using OpenTK.Graphics;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseTwoLayerButton : TestCase
{
public override string Name => @"TwoLayerButton";
public override string Description => @"Back and skip and what not";
public override void Reset()
{
base.Reset();
Add(new BackButton());
Add(new SkipButton());
}
}
}
+2 -3
View File
@@ -1,5 +1,5 @@
// Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE
// 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;
using osu.Framework.GameModes.Testing;
@@ -10,7 +10,6 @@ using osu.Framework.Desktop.Platform;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using SQLiteNetExtensions.Extensions;
using osu.Framework.Allocation;
namespace osu.Desktop.VisualTests
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<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>
@@ -59,6 +59,7 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -73,6 +74,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<Win32Resource>
@@ -100,13 +102,12 @@
<Reference Include="OpenTK">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="OpenTK.dll.config" />
</ItemGroup>
@@ -150,7 +151,7 @@
<Project>{d9a367c9-4c1a-489f-9b05-a0cea2b53b58}</Project>
<Name>osu.Game.Resources</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Mode.Osu\osu.Game.Modes.Osu.csproj">
<ProjectReference Include="..\osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj">
<Project>{c92a607b-1fdd-4954-9f92-03ff547d9080}</Project>
<Name>osu.Game.Modes.Osu</Name>
</ProjectReference>
@@ -172,10 +173,12 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Benchmark.cs" />
<Compile Include="Program.cs" />
<Compile Include="Tests\TestCaseChatDisplay.cs" />
<Compile Include="Tests\TestCaseGamefield.cs" />
<Compile Include="Tests\TestCaseMusicController.cs" />
<Compile Include="Tests\TestCaseNotificationManager.cs" />
<Compile Include="Tests\TestCasePlayer.cs" />
<Compile Include="Tests\TestCaseHitObjects.cs" />
<Compile Include="Tests\TestCaseKeyCounter.cs" />
@@ -183,9 +186,11 @@
<Compile Include="Tests\TestCaseScoreCounter.cs" />
<Compile Include="Tests\TestCaseTextAwesome.cs" />
<Compile Include="Tests\TestCasePlaySongSelect.cs" />
<Compile Include="Tests\TestCaseTwoLayerButton.cs" />
<Compile Include="VisualTestGame.cs" />
<Compile Include="Platform\TestStorage.cs" />
<Compile Include="Tests\TestCaseOptions.cs" />
<Compile Include="Tests\TestCasePauseOverlay.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup />
+11 -7
View File
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1339" 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" />
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1339" 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>
@@ -1,4 +1,7 @@
using System;
// 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.IO;
using System.Collections.Generic;
using System.Linq;
+58
View File
@@ -0,0 +1,58 @@
// 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.Game;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using osu.Framework.Platform;
using osu.Framework.Desktop.Platform;
using osu.Game.Database;
namespace osu.Desktop
{
class OsuGameDesktop : OsuGame
{
public OsuGameDesktop(string[] args = null)
: base(args)
{
}
public override void SetHost(BasicGameHost host)
{
base.SetHost(host);
var desktopWindow = host.Window as DesktopGameWindow;
if (desktopWindow != null)
{
desktopWindow.DragEnter += dragEnter;
desktopWindow.DragDrop += dragDrop;
}
}
private void dragDrop(DragEventArgs e)
{
// this method will only be executed if e.Effect in dragEnter gets set to something other that None.
var dropData = e.Data.GetData(DataFormats.FileDrop) as object[];
var filePaths = dropData.Select(f => f.ToString()).ToArray();
ImportBeatmaps(filePaths);
}
private void dragEnter(DragEventArgs e)
{
// dragDrop will only be executed if e.Effect gets set to something other that None in this method.
bool isFile = e.Data.GetDataPresent(DataFormats.FileDrop);
if (isFile)
{
var paths = (e.Data.GetData(DataFormats.FileDrop) as object[]).Select(f => f.ToString()).ToArray();
if (paths.Any(p => !p.EndsWith(".osz")))
e.Effect = DragDropEffects.None;
else
e.Effect = DragDropEffects.Copy;
}
}
}
}
+13 -6
View File
@@ -1,9 +1,10 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.IO;
using System.Linq;
using System.Threading;
using osu.Desktop.Beatmaps.IO;
using osu.Framework;
using osu.Framework.Desktop;
@@ -26,16 +27,22 @@ namespace osu.Desktop
{
LegacyFilesystemReader.Register();
// Back up the cwd before DesktopGameHost changes it
var cwd = Environment.CurrentDirectory;
using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true))
{
if (!host.IsPrimaryInstance)
{
var importer = new BeatmapImporter(host);
// Restore the cwd so relative paths given at the command line work correctly
Directory.SetCurrentDirectory(cwd);
foreach (var file in args)
if (!importer.Import(file).Wait(1000))
{
Console.WriteLine(@"Importing {0}", file);
if (!importer.Import(Path.GetFullPath(file)).Wait(3000))
throw new TimeoutException(@"IPC took too long to send");
Console.WriteLine(@"Sent import requests to running instance");
}
}
else
{
@@ -44,7 +51,7 @@ namespace osu.Desktop
Ruleset.Register(new ManiaRuleset());
Ruleset.Register(new CatchRuleset());
BaseGame osu = new OsuGame(args);
BaseGame osu = new OsuGameDesktop(args);
host.Add(osu);
host.Run();
}
+6 -1
View File
@@ -59,6 +59,7 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<Commandlineparameters>
</Commandlineparameters>
</PropertyGroup>
@@ -75,13 +76,16 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<Win32Resource>osu!.res</Win32Resource>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4" />
<Reference Include="System" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<None Include="..\osu.licenseheader">
@@ -130,7 +134,7 @@
<Project>{d9a367c9-4c1a-489f-9b05-a0cea2b53b58}</Project>
<Name>osu.Game.Resources</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Mode.Osu\osu.Game.Modes.Osu.csproj">
<ProjectReference Include="..\osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj">
<Project>{c92a607b-1fdd-4954-9f92-03ff547d9080}</Project>
<Name>osu.Game.Modes.Osu</Name>
</ProjectReference>
@@ -152,6 +156,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="OsuGameDesktop.cs" />
<Compile Include="Program.cs" />
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />
</ItemGroup>
@@ -1,137 +0,0 @@
//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.Transformations;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class DrawableHitCircle : DrawableHitObject
{
private OsuHitObject osuObject;
public ApproachCircle ApproachCircle;
private CirclePiece circle;
private RingPiece ring;
private FlashPiece flash;
private ExplodePiece explode;
private NumberPiece number;
private GlowPiece glow;
private HitExplosion explosion;
public DrawableHitCircle(HitCircle h) : base(h)
{
osuObject = h;
Origin = Anchor.Centre;
Position = osuObject.Position;
Children = new Drawable[]
{
glow = new GlowPiece
{
Colour = osuObject.Colour
},
circle = new CirclePiece
{
Colour = osuObject.Colour,
Hit = Hit,
},
number = new NumberPiece(),
ring = new RingPiece(),
flash = new FlashPiece(),
explode = new ExplodePiece
{
Colour = osuObject.Colour,
},
ApproachCircle = new ApproachCircle()
{
Colour = osuObject.Colour,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
//may not be so correct
Size = circle.DrawSize;
//force application of the state that was set before we loaded.
UpdateState(State);
}
protected override void UpdateState(ArmedState state)
{
if (!IsLoaded) return;
Flush(true); //move to DrawableHitObject
ApproachCircle.Flush(true);
double t = HitTime ?? osuObject.StartTime;
Alpha = 0;
//sane defaults
ring.Alpha = circle.Alpha = number.Alpha = glow.Alpha = 1;
ApproachCircle.Alpha = 0;
ApproachCircle.Scale = new Vector2(2);
explode.Alpha = 0;
Scale = new Vector2(0.5f); //this will probably need to be moved to DrawableHitObject at some point.
const float preempt = 600;
const float fadein = 400;
Delay(t - Time.Current - preempt, true);
FadeIn(fadein);
ApproachCircle.FadeIn(Math.Min(fadein * 2, preempt));
ApproachCircle.ScaleTo(0.6f, preempt);
Delay(preempt, true);
ApproachCircle.FadeOut();
glow.FadeOut(400);
switch (state)
{
case ArmedState.Disarmed:
Delay(osuObject.Duration + 200);
FadeOut(200);
explosion?.Expire();
explosion = null;
break;
case ArmedState.Armed:
const double flash_in = 30;
flash.FadeTo(0.8f, flash_in);
flash.Delay(flash_in);
flash.FadeOut(100);
explode.FadeIn(flash_in);
Schedule(() => Add(explosion = new HitExplosion(Judgement.Hit300)));
Delay(flash_in, true);
//after the flash, we can hide some elements that were behind it
ring.FadeOut();
circle.FadeOut();
number.FadeOut();
FadeOut(800);
ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad);
break;
}
}
}
}
@@ -1,50 +0,0 @@
using osu.Framework.Graphics;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
class DrawableSlider : DrawableHitObject
{
public DrawableSlider(Slider h) : base(h)
{
Origin = Anchor.Centre;
RelativePositionAxes = Axes.Both;
Position = new Vector2(h.Position.X / 512, h.Position.Y / 384);
for (float i = 0; i <= 1; i += 0.1f)
{
Add(new CirclePiece
{
Colour = h.Colour,
Hit = Hit,
Position = h.Curve.PositionAt(i) - h.Position //non-relative?
});
}
}
protected override void LoadComplete()
{
base.LoadComplete();
//force application of the state that was set before we loaded.
UpdateState(State);
}
protected override void UpdateState(ArmedState state)
{
if (!IsLoaded) return;
Flush(true); //move to DrawableHitObject
Alpha = 0;
Delay(HitObject.StartTime - 200 - Time.Current, true);
FadeIn(200);
Delay(200 + HitObject.Duration);
FadeOut(200);
}
}
}
@@ -1,50 +0,0 @@
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class HitExplosion : FlowContainer
{
private SpriteText line1;
private SpriteText line2;
public HitExplosion(Judgement judgement, ComboJudgement comboJudgement = ComboJudgement.None)
{
AutoSizeAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Direction = FlowDirection.VerticalOnly;
Spacing = new Vector2(0, 2);
Children = new Drawable[]
{
line1 = new SpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Text = judgement.GetDescription(),
Font = @"Venera",
TextSize = 20,
},
line2 = new SpriteText
{
Text = comboJudgement.GetDescription(),
Font = @"Venera",
TextSize = 14,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
line1.TransformSpacingTo(14, 1800, EasingTypes.OutQuint);
line2.TransformSpacingTo(14, 1800, EasingTypes.OutQuint);
}
}
}
@@ -1,34 +0,0 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class RingPiece : Container
{
private Sprite ring;
public RingPiece()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Children = new Drawable[]
{
ring = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
}
};
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
ring.Texture = textures.Get(@"Play/osu/ring@2x");
}
}
}
-9
View File
@@ -1,9 +0,0 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Osu.Objects
{
public class HitCircle : OsuHitObject
{
}
}
-29
View File
@@ -1,29 +0,0 @@
//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.Game.Beatmaps.Samples;
using osu.Game.Modes.Objects;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects
{
public abstract class OsuHitObject : HitObject
{
public Vector2 Position { get; set; }
[Flags]
internal enum HitObjectType
{
Circle = 1,
Slider = 2,
NewCombo = 4,
CircleNewCombo = 5,
SliderNewCombo = 6,
Spinner = 8,
ColourHax = 122,
Hold = 128,
ManiaLong = 128,
}
}
}
@@ -1,21 +0,0 @@
//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.Collections.Generic;
using osu.Game.Modes.Objects;
namespace osu.Game.Modes.Osu.Objects
{
public class OsuHitObjectConverter : HitObjectConverter<OsuHitObject>
{
public override List<OsuHitObject> Convert(List<HitObject> input)
{
List<OsuHitObject> output = new List<OsuHitObject>();
foreach (HitObject h in input)
output.Add(h as OsuHitObject);
return output;
}
}
}
-9
View File
@@ -1,9 +0,0 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Osu.Objects
{
public class Spinner : OsuHitObject
{
}
}
-22
View File
@@ -1,22 +0,0 @@
//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.Collections.Generic;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Osu
{
public class OsuRuleset : Ruleset
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(List<HitObject> objects) => new OsuHitRenderer { Objects = objects };
public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
protected override PlayMode PlayMode => PlayMode.Osu;
}
}
-4
View File
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ppy.OpenTK" version="2.0.50727.1339" targetFramework="net452" />
</packages>
+9 -3
View File
@@ -1,12 +1,14 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Collections.Generic;
using osu.Game.Graphics;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
using osu.Game.Beatmaps;
namespace osu.Game.Modes.Catch
{
@@ -14,10 +16,14 @@ namespace osu.Game.Modes.Catch
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(List<HitObject> objects) => new CatchHitRenderer { Objects = objects };
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new CatchHitRenderer { Beatmap = beatmap };
protected override PlayMode PlayMode => PlayMode.Catch;
public override FontAwesome Icon => FontAwesome.fa_osu_fruits_o;
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null;
public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Game.Modes.Objects;
@@ -1,19 +1,20 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Collections.Generic;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Beatmaps;
namespace osu.Game.Modes.Catch.Objects
{
class CatchConverter : HitObjectConverter<CatchBaseHit>
{
public override List<CatchBaseHit> Convert(List<HitObject> input)
public override List<CatchBaseHit> Convert(Beatmap beatmap)
{
List<CatchBaseHit> output = new List<CatchBaseHit>();
foreach (HitObject i in input)
foreach (HitObject i in beatmap.HitObjects)
{
CatchBaseHit h = i as CatchBaseHit;
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Framework.Graphics;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Catch.Objects
{
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Catch.Objects
{
+5
View File
@@ -1,3 +1,8 @@
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
@@ -1,4 +1,7 @@
using System.Reflection;
// 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.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Game.Modes.Osu.UI;
using OpenTK.Graphics;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Game.Modes.Catch.Objects;
using osu.Game.Modes.Objects;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Sprites;
@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
@@ -57,6 +59,9 @@
<Compile Include="CatchRuleset.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="OpenTK.dll.config" />
<None Include="packages.config" />
</ItemGroup>
@@ -65,7 +70,7 @@
<Project>{C76BF5B3-985E-4D39-95FE-97C9C879B83A}</Project>
<Name>osu.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Mode.Osu\osu.Game.Modes.Osu.csproj">
<ProjectReference Include="..\osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj">
<Project>{C92A607B-1FDD-4954-9F92-03FF547D9080}</Project>
<Name>osu.Game.Modes.Osu</Name>
</ProjectReference>
+5
View File
@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="ppy.OpenTK" version="2.0.50727.1339" targetFramework="net45" />
</packages>
+9 -3
View File
@@ -1,13 +1,15 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Collections.Generic;
using osu.Game.Graphics;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
using osu.Game.Beatmaps;
namespace osu.Game.Modes.Mania
{
@@ -15,10 +17,14 @@ namespace osu.Game.Modes.Mania
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(List<HitObject> objects) => new ManiaHitRenderer { Objects = objects };
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new ManiaHitRenderer { Beatmap = beatmap };
protected override PlayMode PlayMode => PlayMode.Mania;
public override FontAwesome Icon => FontAwesome.fa_osu_mania_o;
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null;
public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
}
}
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Framework.Graphics.Sprites;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Mania.Objects
{
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Game.Modes.Objects;
@@ -1,10 +1,11 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Beatmaps;
namespace osu.Game.Modes.Mania.Objects
{
@@ -17,11 +18,11 @@ namespace osu.Game.Modes.Mania.Objects
this.columns = columns;
}
public override List<ManiaBaseHit> Convert(List<HitObject> input)
public override List<ManiaBaseHit> Convert(Beatmap beatmap)
{
List<ManiaBaseHit> output = new List<ManiaBaseHit>();
foreach (HitObject i in input)
foreach (HitObject i in beatmap.HitObjects)
{
ManiaBaseHit h = i as ManiaBaseHit;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Mania.Objects
{
+5
View File
@@ -1,3 +1,8 @@
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
@@ -1,4 +1,7 @@
using System.Reflection;
// 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.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Transformations;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Game.Modes.Mania.Objects;
using osu.Game.Modes.Objects;
+2 -2
View File
@@ -1,5 +1,5 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Sprites;
+5
View File
@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
@@ -61,7 +63,7 @@
<Project>{C76BF5B3-985E-4D39-95FE-97C9C879B83A}</Project>
<Name>osu.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Mode.Osu\osu.Game.Modes.Osu.csproj">
<ProjectReference Include="..\osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj">
<Project>{C92A607B-1FDD-4954-9F92-03FF547D9080}</Project>
<Name>osu.Game.Modes.Osu</Name>
</ProjectReference>
@@ -75,6 +77,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="app.config" />
<None Include="OpenTK.dll.config" />
<None Include="packages.config" />
+5
View File
@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="ppy.OpenTK" version="2.0.50727.1339" targetFramework="net45" />
</packages>
@@ -1,57 +1,11 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
// 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.Collections.Generic;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects
{
public class Slider : OsuHitObject
{
public override double EndTime => StartTime + (RepeatCount + 1) * Curve.Length;
public int RepeatCount;
public SliderCurve Curve;
}
public class SliderCurve
{
public double Length;
public List<Vector2> Path;
public CurveTypes CurveType;
private List<Vector2> calculatedPath;
public void Calculate()
{
switch (CurveType)
{
case CurveTypes.Linear:
calculatedPath = Path;
break;
default:
var bezier = new BezierApproximator(Path);
calculatedPath = bezier.CreateBezier();
break;
}
}
public Vector2 PositionAt(double progress)
{
int index = (int)(progress * (calculatedPath.Count - 1));
Vector2 pos = calculatedPath[index];
if (index != progress)
pos += (calculatedPath[index + 1] - pos) * (float)(progress - index);
return pos;
}
}
public class BezierApproximator
{
private int count;
@@ -59,8 +13,8 @@ namespace osu.Game.Modes.Osu.Objects
private Vector2[] subdivisionBuffer1;
private Vector2[] subdivisionBuffer2;
private const float TOLERANCE = 0.5f;
private const float TOLERANCE_SQ = TOLERANCE * TOLERANCE;
private const float tolerance = 0.25f;
private const float tolerance_sq = tolerance * tolerance;
public BezierApproximator(List<Vector2> controlPoints)
{
@@ -79,10 +33,10 @@ namespace osu.Game.Modes.Osu.Objects
/// </summary>
/// <param name="controlPoints">The control points to check for flatness.</param>
/// <returns>Whether the control points are flat enough.</returns>
private static bool IsFlatEnough(Vector2[] controlPoints)
private static bool isFlatEnough(Vector2[] controlPoints)
{
for (int i = 1; i < controlPoints.Length - 1; i++)
if ((controlPoints[i - 1] - 2 * controlPoints[i] + controlPoints[i + 1]).LengthSquared > TOLERANCE_SQ)
if ((controlPoints[i - 1] - 2 * controlPoints[i] + controlPoints[i + 1]).LengthSquared > tolerance_sq * 4)
return false;
return true;
@@ -96,7 +50,7 @@ namespace osu.Game.Modes.Osu.Objects
/// <param name="controlPoints">The control points to split.</param>
/// <param name="l">Output: The control points corresponding to the left half of the curve.</param>
/// <param name="r">Output: The control points corresponding to the right half of the curve.</param>
private void Subdivide(Vector2[] controlPoints, Vector2[] l, Vector2[] r)
private void subdivide(Vector2[] controlPoints, Vector2[] l, Vector2[] r)
{
Vector2[] midpoints = subdivisionBuffer1;
@@ -119,12 +73,12 @@ namespace osu.Game.Modes.Osu.Objects
/// </summary>
/// <param name="controlPoints">The control points describing the bezier curve to be approximated.</param>
/// <param name="output">The points representing the resulting piecewise-linear approximation.</param>
private void Approximate(Vector2[] controlPoints, List<Vector2> output)
private void approximate(Vector2[] controlPoints, List<Vector2> output)
{
Vector2[] l = subdivisionBuffer2;
Vector2[] r = subdivisionBuffer1;
Subdivide(controlPoints, l, r);
subdivide(controlPoints, l, r);
for (int i = 0; i < count - 1; ++i)
l[count + i] = r[i + 1];
@@ -142,7 +96,6 @@ namespace osu.Game.Modes.Osu.Objects
/// Creates a piecewise-linear approximation of a bezier curve, by adaptively repeatedly subdividing
/// the control points until their approximation error vanishes below a given threshold.
/// </summary>
/// <param name="controlPoints">The control points describing the curve.</param>
/// <returns>A list of vectors representing the piecewise-linear approximation.</returns>
public List<Vector2> CreateBezier()
{
@@ -166,13 +119,13 @@ namespace osu.Game.Modes.Osu.Objects
while (toFlatten.Count > 0)
{
Vector2[] parent = toFlatten.Pop();
if (IsFlatEnough(parent))
if (isFlatEnough(parent))
{
// If the control points we currently operate on are sufficiently "flat", we use
// an extension to De Casteljau's algorithm to obtain a piecewise-linear approximation
// of the bezier curve represented by our control points, consisting of the same amount
// of points as there are control points.
Approximate(parent, output);
approximate(parent, output);
freeBuffers.Push(parent);
continue;
}
@@ -180,7 +133,7 @@ namespace osu.Game.Modes.Osu.Objects
// If we do not yet have a sufficiently "flat" (in other words, detailed) approximation we keep
// subdividing the curve we are currently operating on.
Vector2[] rightChild = freeBuffers.Count > 0 ? freeBuffers.Pop() : new Vector2[count];
Subdivide(parent, leftChild, rightChild);
subdivide(parent, leftChild, rightChild);
// We re-use the buffer of the parent for one of the children, so that we save one allocation per iteration.
for (int i = 0; i < count; ++i)
@@ -194,12 +147,4 @@ namespace osu.Game.Modes.Osu.Objects
return output;
}
}
public enum CurveTypes
{
Catmull,
Bezier,
Linear,
PerfectCurve
};
}
}
@@ -0,0 +1,102 @@
// 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.MathUtils;
using System;
using System.Collections.Generic;
namespace osu.Game.Modes.Osu.Objects
{
public class CircularArcApproximator
{
private Vector2 a;
private Vector2 b;
private Vector2 c;
private int amountPoints;
private const float tolerance = 0.1f;
public CircularArcApproximator(Vector2 a, Vector2 b, Vector2 c)
{
this.a = a;
this.b = b;
this.c = c;
}
/// <summary>
/// Creates a piecewise-linear approximation of a circular arc curve.
/// </summary>
/// <returns>A list of vectors representing the piecewise-linear approximation.</returns>
public List<Vector2> CreateArc()
{
float aSq = (b - c).LengthSquared;
float bSq = (a - c).LengthSquared;
float cSq = (a - b).LengthSquared;
// If we have a degenerate triangle where a side-length is almost zero, then give up and fall
// back to a more numerically stable method.
if (Precision.AlmostEquals(aSq, 0) || Precision.AlmostEquals(bSq, 0) || Precision.AlmostEquals(cSq, 0))
return new List<Vector2>();
float s = aSq * (bSq + cSq - aSq);
float t = bSq * (aSq + cSq - bSq);
float u = cSq * (aSq + bSq - cSq);
float sum = s + t + u;
// If we have a degenerate triangle with an almost-zero size, then give up and fall
// back to a more numerically stable method.
if (Precision.AlmostEquals(sum, 0))
return new List<Vector2>();
Vector2 centre = (s * a + t * b + u * c) / sum;
Vector2 dA = a - centre;
Vector2 dC = c - centre;
float r = dA.Length;
double thetaStart = Math.Atan2(dA.Y, dA.X);
double thetaEnd = Math.Atan2(dC.Y, dC.X);
while (thetaEnd < thetaStart)
thetaEnd += 2 * Math.PI;
double dir = 1;
double thetaRange = thetaEnd - thetaStart;
// Decide in which direction to draw the circle, depending on which side of
// AC B lies.
Vector2 orthoAtoC = c - a;
orthoAtoC = new Vector2(orthoAtoC.Y, -orthoAtoC.X);
if (Vector2.Dot(orthoAtoC, b - a) < 0)
{
dir = -dir;
thetaRange = 2 * Math.PI - thetaRange;
}
// We select the amount of points for the approximation by requiring the discrete curvature
// to be smaller than the provided tolerance. The exact angle required to meet the tolerance
// is: 2 * Math.Acos(1 - TOLERANCE / r)
if (2 * r <= tolerance)
// This special case is required for extremely short sliders where the radius is smaller than
// the tolerance. This is a pathological rather than a realistic case.
amountPoints = 2;
else
amountPoints = Math.Max(2, (int)Math.Ceiling(thetaRange / (2 * Math.Acos(1 - tolerance / r))));
List<Vector2> output = new List<Vector2>(amountPoints);
for (int i = 0; i < amountPoints; ++i)
{
double fract = (double)i / (amountPoints - 1);
double theta = thetaStart + dir * fract * thetaRange;
Vector2 o = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * r;
output.Add(centre + o);
}
return output;
}
}
}
@@ -0,0 +1,160 @@
// 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.ComponentModel;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Transformations;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class DrawableHitCircle : DrawableOsuHitObject
{
private HitCircle osuObject;
public ApproachCircle ApproachCircle;
private CirclePiece circle;
private RingPiece ring;
private FlashPiece flash;
private ExplodePiece explode;
private NumberPiece number;
private GlowPiece glow;
public DrawableHitCircle(HitCircle h) : base(h)
{
osuObject = h;
Origin = Anchor.Centre;
Position = osuObject.StackedPosition;
Scale = new Vector2(osuObject.Scale);
Children = new Drawable[]
{
glow = new GlowPiece
{
Colour = osuObject.Colour
},
circle = new CirclePiece
{
Colour = osuObject.Colour,
Hit = () =>
{
if (Judgement.Result.HasValue) return false;
((PositionalJudgementInfo)Judgement).PositionOffset = Vector2.Zero; //todo: set to correct value
UpdateJudgement(true);
return true;
},
},
number = new NumberPiece(),
ring = new RingPiece(),
flash = new FlashPiece(),
explode = new ExplodePiece
{
Colour = osuObject.Colour,
},
ApproachCircle = new ApproachCircle()
{
Colour = osuObject.Colour,
}
};
//may not be so correct
Size = circle.DrawSize;
}
double hit50 = 150;
double hit100 = 80;
double hit300 = 30;
protected override void CheckJudgement(bool userTriggered)
{
if (!userTriggered)
{
if (Judgement.TimeOffset > hit50)
Judgement.Result = HitResult.Miss;
return;
}
double hitOffset = Math.Abs(Judgement.TimeOffset);
if (hitOffset < hit50)
{
Judgement.Result = HitResult.Hit;
OsuJudgementInfo osuInfo = Judgement as OsuJudgementInfo;
if (hitOffset < hit300)
osuInfo.Score = OsuScoreResult.Hit300;
else if (hitOffset < hit100)
osuInfo.Score = OsuScoreResult.Hit100;
else if (hitOffset < hit50)
osuInfo.Score = OsuScoreResult.Hit50;
}
else
Judgement.Result = HitResult.Miss;
}
protected override void UpdateInitialState()
{
base.UpdateInitialState();
//sane defaults
ring.Alpha = circle.Alpha = number.Alpha = glow.Alpha = 1;
ApproachCircle.Alpha = 0;
ApproachCircle.Scale = new Vector2(4);
explode.Alpha = 0;
}
protected override void UpdatePreemptState()
{
base.UpdatePreemptState();
ApproachCircle.FadeIn(Math.Min(TIME_FADEIN * 2, TIME_PREEMPT));
ApproachCircle.ScaleTo(1.1f, TIME_PREEMPT);
}
protected override void UpdateState(ArmedState state)
{
if (!IsLoaded) return;
base.UpdateState(state);
ApproachCircle.FadeOut();
glow.FadeOut(400);
switch (state)
{
case ArmedState.Idle:
Delay(osuObject.Duration + TIME_PREEMPT);
FadeOut(TIME_FADEOUT);
break;
case ArmedState.Miss:
FadeOut(TIME_FADEOUT / 5);
break;
case ArmedState.Hit:
const double flash_in = 40;
flash.FadeTo(0.8f, flash_in);
flash.Delay(flash_in);
flash.FadeOut(100);
explode.FadeIn(flash_in);
Delay(flash_in, true);
//after the flash, we can hide some elements that were behind it
ring.FadeOut();
circle.FadeOut();
number.FadeOut();
FadeOut(800);
ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad);
break;
}
}
}
}
@@ -0,0 +1,76 @@
// 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.ComponentModel;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class DrawableOsuHitObject : DrawableHitObject
{
public const float TIME_PREEMPT = 600;
public const float TIME_FADEIN = 400;
public const float TIME_FADEOUT = 500;
public DrawableOsuHitObject(OsuHitObject hitObject)
: base(hitObject)
{
}
public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo();
protected override void UpdateState(ArmedState state)
{
if (!IsLoaded) return;
Flush();
UpdateInitialState();
Delay(HitObject.StartTime - Time.Current - TIME_PREEMPT + Judgement.TimeOffset, true);
UpdatePreemptState();
Delay(TIME_PREEMPT, true);
}
protected virtual void UpdatePreemptState()
{
FadeIn(TIME_FADEIN);
}
protected virtual void UpdateInitialState()
{
Alpha = 0;
}
}
public class OsuJudgementInfo : PositionalJudgementInfo
{
public OsuScoreResult Score;
public ComboResult Combo;
}
public enum ComboResult
{
[Description(@"")]
None,
[Description(@"Good")]
Good,
[Description(@"Amazing")]
Perfect
}
public enum OsuScoreResult
{
[Description(@"Miss")]
Miss,
[Description(@"50")]
Hit50,
[Description(@"100")]
Hit100,
[Description(@"300")]
Hit300,
}
}
@@ -0,0 +1,142 @@
// 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.Collections.Generic;
using osu.Framework.Graphics;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using OpenTK;
using osu.Framework.Input;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
class DrawableSlider : DrawableOsuHitObject
{
private Slider slider;
private DrawableHitCircle initialCircle;
private List<ISliderProgress> components = new List<ISliderProgress>();
SliderBody body;
SliderBall ball;
SliderBouncer bouncer1, bouncer2;
public DrawableSlider(Slider s) : base(s)
{
slider = s;
Children = new Drawable[]
{
body = new SliderBody(s)
{
Position = s.StackedPosition,
PathWidth = s.Scale * 64,
},
bouncer1 = new SliderBouncer(s, false)
{
Position = s.Curve.PositionAt(1),
Scale = new Vector2(s.Scale),
},
bouncer2 = new SliderBouncer(s, true)
{
Position = s.StackedPosition,
Scale = new Vector2(s.Scale),
},
ball = new SliderBall(s)
{
Scale = new Vector2(s.Scale),
},
initialCircle = new DrawableHitCircle(new HitCircle
{
StartTime = s.StartTime,
Position = s.StackedPosition,
Scale = s.Scale,
Colour = s.Colour,
Sample = s.Sample,
}),
};
components.Add(body);
components.Add(ball);
components.Add(bouncer1);
components.Add(bouncer2);
}
// Since the DrawableSlider itself is just a container without a size we need to
// pass all input through.
public override bool Contains(Vector2 screenSpacePos) => true;
int currentRepeat;
protected override void Update()
{
base.Update();
double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
int repeat = (int)(progress * slider.RepeatCount);
progress = (progress * slider.RepeatCount) % 1;
if (repeat > currentRepeat)
{
if (ball.Tracking)
PlaySample();
currentRepeat = repeat;
}
if (repeat % 2 == 1)
progress = 1 - progress;
bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0);
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
if (initialCircle.Judgement?.Result != HitResult.Hit)
initialCircle.Position = slider.Curve.PositionAt(progress);
components.ForEach(c => c.UpdateProgress(progress, repeat));
}
protected override void CheckJudgement(bool userTriggered)
{
var j = Judgement as OsuJudgementInfo;
var sc = initialCircle.Judgement as OsuJudgementInfo;
if (!userTriggered && Time.Current >= HitObject.EndTime)
{
j.Score = sc.Score;
j.Result = sc.Result;
}
}
protected override void UpdateInitialState()
{
base.UpdateInitialState();
body.Alpha = 1;
//we need to be present to handle input events. note that we still don't get enough events (we don't get a position if the mouse hasn't moved since the slider appeared).
ball.AlwaysPresent = true;
ball.Alpha = 0;
}
protected override void UpdateState(ArmedState state)
{
base.UpdateState(state);
ball.FadeIn();
Delay(HitObject.Duration, true);
body.FadeOut(160);
ball.FadeOut(160);
FadeOut(800);
}
}
internal interface ISliderProgress
{
void UpdateProgress(double progress, int repeat);
}
}
@@ -0,0 +1,84 @@
// 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.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Game.Modes.Objects.Drawables;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class HitExplosion : FlowContainer
{
private readonly OsuJudgementInfo judgement;
private SpriteText line1;
private SpriteText line2;
public HitExplosion(OsuJudgementInfo judgement, OsuHitObject h = null)
{
this.judgement = judgement;
AutoSizeAxes = Axes.Both;
Origin = Anchor.Centre;
Direction = FlowDirection.VerticalOnly;
Spacing = new Vector2(0, 2);
Position = (h?.StackedEndPosition ?? Vector2.Zero) + judgement.PositionOffset;
Children = new Drawable[]
{
line1 = new SpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Text = judgement.Score.GetDescription(),
Font = @"Venera",
TextSize = 16,
},
line2 = new SpriteText
{
Text = judgement.Combo.GetDescription(),
Font = @"Venera",
TextSize = 11,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
if (judgement.Result == HitResult.Miss)
{
FadeInFromZero(60);
ScaleTo(1.6f);
ScaleTo(1, 100, EasingTypes.In);
MoveToOffset(new Vector2(0, 100), 800, EasingTypes.InQuint);
RotateTo(40, 800, EasingTypes.InQuint);
Delay(600);
FadeOut(200);
}
else
{
line1.TransformSpacingTo(new Vector2(14, 0), 1800, EasingTypes.OutQuint);
line2.TransformSpacingTo(new Vector2(14, 0), 1800, EasingTypes.OutQuint);
FadeOut(500);
}
switch (judgement.Result)
{
case HitResult.Miss:
Colour = Color4.Red;
break;
}
Expire();
}
}
}
@@ -1,4 +1,7 @@
using System;
// 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 osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -29,7 +32,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
approachCircle.Texture = textures.Get(@"Play/osu/approachcircle@2x");
approachCircle.Texture = textures.Get(@"Play/osu/approachcircle");
}
}
}
@@ -1,4 +1,7 @@
using System;
// 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 osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -19,9 +22,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
public CirclePiece()
{
Size = new Vector2(144);
Size = new Vector2(128);
Masking = true;
CornerRadius = DrawSize.X / 2;
CornerRadius = Size.X / 2;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
@@ -44,13 +47,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
disc.Texture = textures.Get(@"Play/osu/disc@2x");
disc.Texture = textures.Get(@"Play/osu/disc");
}
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
Hit?.Invoke();
return true;
return Hit?.Invoke() ?? false;
}
}
}
@@ -1,4 +1,7 @@
using osu.Framework.Graphics;
// 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 OpenTK;
@@ -8,7 +11,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public ExplodePiece()
{
Size = new Vector2(144);
Size = new Vector2(128);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
@@ -1,4 +1,7 @@
using osu.Framework.Graphics;
// 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.Sprites;
using OpenTK;
@@ -9,7 +12,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public FlashPiece()
{
Size = new Vector2(144);
Size = new Vector2(128);
Masking = true;
CornerRadius = Size.X / 2;
@@ -1,4 +1,7 @@
using osu.Framework.Allocation;
// 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.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
@@ -30,7 +33,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
layer.Texture = textures.Get(@"Play/osu/ring-glow@2x");
layer.Texture = textures.Get(@"Play/osu/ring-glow");
}
}
}
@@ -1,4 +1,7 @@
using osu.Framework.Allocation;
// 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.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
@@ -29,7 +32,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
number.Texture = textures.Get(@"Play/osu/number@2x");
number.Texture = textures.Get(@"Play/osu/number");
}
}
}
@@ -0,0 +1,40 @@
// 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.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class RingPiece : Container
{
public RingPiece()
{
Size = new Vector2(128);
Masking = true;
CornerRadius = Size.X / 2;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
BorderThickness = 10;
BorderColour = Color4.White;
Children = new Drawable[]
{
new Box
{
AlwaysPresent = true,
Alpha = 0,
RelativeSizeAxes = Axes.Both
}
};
}
}
}
@@ -0,0 +1,116 @@
// 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.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Framework.Input;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SliderBall : Container, ISliderProgress
{
private readonly Slider slider;
private Box follow;
const float width = 128;
public SliderBall(Slider slider)
{
this.slider = slider;
Masking = true;
AutoSizeAxes = Axes.Both;
BlendingMode = BlendingMode.Additive;
Origin = Anchor.Centre;
BorderThickness = 10;
BorderColour = Color4.Orange;
Children = new Drawable[]
{
follow = new Box
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Colour = Color4.Orange,
Width = width,
Height = width,
Alpha = 0,
},
new Container
{
Masking = true,
AutoSizeAxes = Axes.Both,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
BorderThickness = 10,
BorderColour = Color4.White,
Alpha = 1,
CornerRadius = width / 2,
Children = new[]
{
new Box
{
Colour = slider.Colour,
Alpha = 0.4f,
Width = width,
Height = width,
},
}
}
};
}
private InputState lastState;
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
lastState = state;
return base.OnMouseDown(state, args);
}
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
{
lastState = state;
return base.OnMouseUp(state, args);
}
protected override bool OnMouseMove(InputState state)
{
lastState = state;
return base.OnMouseMove(state);
}
bool tracking;
public bool Tracking
{
get { return tracking; }
set
{
if (value == tracking) return;
tracking = value;
follow.ScaleTo(tracking ? 2.8f : 1, 300, EasingTypes.OutQuint);
follow.FadeTo(tracking ? 0.2f : 0, 300, EasingTypes.OutQuint);
}
}
private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime;
protected override void Update()
{
base.Update();
CornerRadius = DrawWidth / 2;
Tracking = canCurrentlyTrack && lastState != null && Contains(lastState.Mouse.NativeState.Position) && lastState.Mouse.HasMainButtonPressed;
}
public void UpdateProgress(double progress, int repeat)
{
Position = slider.Curve.PositionAt(progress);
}
}
}
@@ -0,0 +1,163 @@
// 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.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.OpenGL.Textures;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Configuration;
using OpenTK;
using OpenTK.Graphics.ES30;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SliderBody : Container, ISliderProgress
{
private Path path;
private BufferedContainer container;
public float PathWidth
{
get { return path.PathWidth; }
set
{
path.PathWidth = value;
}
}
public double? SnakedStart { get; private set; }
public double? SnakedEnd { get; private set; }
private Slider slider;
public SliderBody(Slider s)
{
slider = s;
Children = new Drawable[]
{
container = new BufferedContainer
{
CacheDrawnFrameBuffer = true,
Children = new Drawable[]
{
path = new Path
{
BlendingMode = BlendingMode.None,
},
}
},
};
container.Attach(RenderbufferInternalFormat.DepthComponent16);
}
public void SetRange(double p0, double p1)
{
if (p0 > p1)
MathHelper.Swap(ref p0, ref p1);
if (updateSnaking(p0, p1))
{
// Autosizing does not give us the desired behaviour here.
// We want the container to have the same size as the slider,
// and to be positioned such that the slider head is at (0,0).
container.Size = path.Size;
container.Position = -path.PositionInBoundingBox(slider.Curve.PositionAt(0) - currentCurve[0]);
container.ForceRedraw();
}
}
private Bindable<bool> snakingIn;
private Bindable<bool> snakingOut;
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
snakingIn = config.GetBindable<bool>(OsuConfig.SnakingInSliders);
snakingOut = config.GetBindable<bool>(OsuConfig.SnakingOutSliders);
int textureWidth = (int)PathWidth * 2;
//initialise background
var upload = new TextureUpload(textureWidth * 4);
var bytes = upload.Data;
const float aa_portion = 0.02f;
const float border_portion = 0.128f;
const float gradient_portion = 1 - border_portion;
const float opacity_at_centre = 0.3f;
const float opacity_at_edge = 0.8f;
for (int i = 0; i < textureWidth; i++)
{
float progress = (float)i / (textureWidth - 1);
if (progress <= border_portion)
{
bytes[i * 4] = 255;
bytes[i * 4 + 1] = 255;
bytes[i * 4 + 2] = 255;
bytes[i * 4 + 3] = (byte)(Math.Min(progress / aa_portion, 1) * 255);
}
else
{
progress -= border_portion;
bytes[i * 4] = (byte)(slider.Colour.R * 255);
bytes[i * 4 + 1] = (byte)(slider.Colour.G * 255);
bytes[i * 4 + 2] = (byte)(slider.Colour.B * 255);
bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (slider.Colour.A * 255));
}
}
var texture = new Texture(textureWidth, 1);
texture.SetData(upload);
path.Texture = texture;
}
private List<Vector2> currentCurve = new List<Vector2>();
private bool updateSnaking(double p0, double p1)
{
if (SnakedStart == p0 && SnakedEnd == p1) return false;
SnakedStart = p0;
SnakedEnd = p1;
slider.Curve.GetPathToProgress(currentCurve, p0, p1);
path.ClearVertices();
foreach (Vector2 p in currentCurve)
path.AddVertex(p - currentCurve[0]);
return true;
}
public void UpdateProgress(double progress, int repeat)
{
double start = 0;
double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - DrawableOsuHitObject.TIME_PREEMPT)) / DrawableOsuHitObject.TIME_FADEIN, 0, 1) : 1;
if (repeat >= slider.RepeatCount - 1)
{
if (Math.Min(repeat, slider.RepeatCount - 1) % 2 == 1)
{
start = 0;
end = snakingOut ? progress : 1;
}
else
{
start = snakingOut ? progress : 0;
}
}
SetRange(start, end);
}
}
}
@@ -0,0 +1,58 @@
// 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 System.Linq;
using System.Text;
using System.Threading.Tasks;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SliderBouncer : Container, ISliderProgress
{
private readonly Slider slider;
private readonly bool isEnd;
private TextAwesome icon;
public SliderBouncer(Slider slider, bool isEnd)
{
this.slider = slider;
this.isEnd = isEnd;
AutoSizeAxes = Axes.Both;
BlendingMode = BlendingMode.Additive;
Origin = Anchor.Centre;
Children = new Drawable[]
{
icon = new TextAwesome
{
Icon = FontAwesome.fa_eercast,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
TextSize = 48,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
icon.RotateTo(360, 1000);
icon.Loop();
}
public void UpdateProgress(double progress, int repeat)
{
if (Time.Current < slider.StartTime)
Alpha = 0;
Alpha = repeat + 1 < slider.RepeatCount && repeat % 2 == (isEnd ? 0 : 1) ? 1 : 0;
}
}
}
@@ -1,4 +1,7 @@
using osu.Framework.Allocation;
// 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.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
@@ -8,29 +11,26 @@ using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class Triangles : Container
public class Triangles : Container<Triangle>
{
private Texture triangle;
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
triangle = textures.Get(@"Play/osu/triangle@2x");
}
public override bool HandleInput => false;
protected override void LoadComplete()
{
base.LoadComplete();
const float size = 100;
for (int i = 0; i < 10; i++)
{
Add(new Sprite
Add(new Triangle
{
Texture = triangle,
Origin = Anchor.Centre,
RelativePositionAxes = Axes.Both,
Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()),
Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f),
Alpha = RNG.NextSingle() * 0.3f
// Scaling height by 0.866 results in equiangular triangles (== 60° and equal side length)
Size = new Vector2(size, 0.866f * size),
Alpha = RNG.NextSingle() * 0.3f,
});
}
}
+9
View File
@@ -0,0 +1,9 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Osu.Objects
{
public class HitCircle : OsuHitObject
{
}
}
@@ -0,0 +1,49 @@
// 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 osu.Game.Beatmaps.Samples;
using osu.Game.Modes.Objects;
using OpenTK;
using osu.Game.Beatmaps;
namespace osu.Game.Modes.Osu.Objects
{
public abstract class OsuHitObject : HitObject
{
public Vector2 Position { get; set; }
public Vector2 StackedPosition => Position + StackOffset;
public virtual Vector2 EndPosition => Position;
public Vector2 StackedEndPosition => EndPosition + StackOffset;
public virtual int StackHeight { get; set; }
public Vector2 StackOffset => new Vector2(StackHeight * Scale * -6.4f);
public float Scale { get; set; } = 1;
public override void SetDefaultsFromBeatmap(Beatmap beatmap)
{
base.SetDefaultsFromBeatmap(beatmap);
Scale = (1.0f - 0.7f * (beatmap.BeatmapInfo.BaseDifficulty.CircleSize - 5) / 5) / 2;
}
[Flags]
internal enum HitObjectType
{
Circle = 1,
Slider = 2,
NewCombo = 4,
CircleNewCombo = 5,
SliderNewCombo = 6,
Spinner = 8,
ColourHax = 122,
Hold = 128,
ManiaLong = 128,
}
}
}
@@ -0,0 +1,170 @@
// 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.Collections.Generic;
using osu.Game.Modes.Objects;
using osu.Game.Beatmaps;
using osu.Game.Modes.Osu.Objects.Drawables;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects
{
public class OsuHitObjectConverter : HitObjectConverter<OsuHitObject>
{
public override List<OsuHitObject> Convert(Beatmap beatmap)
{
List<OsuHitObject> output = new List<OsuHitObject>();
foreach (HitObject h in beatmap.HitObjects)
output.Add(h as OsuHitObject);
UpdateStacking(output, beatmap.BeatmapInfo?.StackLeniency ?? 0.7f);
return output;
}
public static void UpdateStacking(List<OsuHitObject> hitObjects, float stackLeniency, int startIndex = 0, int endIndex = -1)
{
if (endIndex == -1)
endIndex = hitObjects.Count - 1;
int stackDistance = 3;
float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * stackLeniency;
// Reset stacking inside the update range
for (int i = startIndex; i <= endIndex; i++)
hitObjects[i].StackHeight = 0;
// Extend the end index to include objects they are stacked on
int extendedEndIndex = endIndex;
for (int i = endIndex; i >= startIndex; i--)
{
int stackBaseIndex = i;
for (int n = stackBaseIndex + 1; n < hitObjects.Count; n++)
{
OsuHitObject stackBaseObject = hitObjects[stackBaseIndex];
if (stackBaseObject is Spinner) break;
OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) continue;
if (objectN.StartTime - stackBaseObject.EndTime > stackThreshold)
//We are no longer within stacking range of the next object.
break;
if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stackDistance ||
(stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stackDistance))
{
stackBaseIndex = n;
// HitObjects after the specified update range haven't been reset yet
objectN.StackHeight = 0;
}
}
if (stackBaseIndex > extendedEndIndex)
{
extendedEndIndex = stackBaseIndex;
if (extendedEndIndex == hitObjects.Count - 1)
break;
}
}
//Reverse pass for stack calculation.
int extendedStartIndex = startIndex;
for (int i = extendedEndIndex; i > startIndex; i--)
{
int n = i;
/* We should check every note which has not yet got a stack.
* Consider the case we have two interwound stacks and this will make sense.
*
* o <-1 o <-2
* o <-3 o <-4
*
* We first process starting from 4 and handle 2,
* then we come backwards on the i loop iteration until we reach 3 and handle 1.
* 2 and 1 will be ignored in the i loop because they already have a stack value.
*/
OsuHitObject objectI = hitObjects[i];
if (objectI.StackHeight != 0 || objectI is Spinner) continue;
/* If this object is a hitcircle, then we enter this "special" case.
* It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider.
* Any other case is handled by the "is Slider" code below this.
*/
if (objectI is HitCircle)
{
while (--n >= 0)
{
OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) continue;
if (objectI.StartTime - objectN.EndTime > stackThreshold)
//We are no longer within stacking range of the previous object.
break;
// HitObjects before the specified update range haven't been reset yet
if (n < extendedStartIndex)
{
objectN.StackHeight = 0;
extendedStartIndex = n;
}
/* This is a special case where hticircles are moved DOWN and RIGHT (negative stacking) if they are under the *last* slider in a stacked pattern.
* o==o <- slider is at original location
* o <- hitCircle has stack of -1
* o <- hitCircle has stack of -2
*/
if (objectN is Slider && Vector2.Distance(objectN.EndPosition, objectI.Position) < stackDistance)
{
int offset = objectI.StackHeight - objectN.StackHeight + 1;
for (int j = n + 1; j <= i; j++)
{
//For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
OsuHitObject objectJ = hitObjects[j];
if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stackDistance)
objectJ.StackHeight -= offset;
}
//We have hit a slider. We should restart calculation using this as the new base.
//Breaking here will mean that the slider still has StackCount of 0, so will be handled in the i-outer-loop.
break;
}
if (Vector2.Distance(objectN.Position, objectI.Position) < stackDistance)
{
//Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out.
//NOTE: Sliders with start positions stacking are a special case that is also handled here.
objectN.StackHeight = objectI.StackHeight + 1;
objectI = objectN;
}
}
}
else if (objectI is Slider)
{
/* We have hit the first slider in a possible stack.
* From this point on, we ALWAYS stack positive regardless.
*/
while (--n >= startIndex)
{
OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) continue;
if (objectI.StartTime - objectN.StartTime > stackThreshold)
//We are no longer within stacking range of the previous object.
break;
if (Vector2.Distance(objectN.EndPosition, objectI.Position) < stackDistance)
{
objectN.StackHeight = objectI.StackHeight + 1;
objectI = objectN;
}
}
}
}
}
}
}
@@ -1,4 +1,7 @@
using System;
// 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 System.Globalization;
using System.Linq;
@@ -80,7 +83,7 @@ namespace osu.Game.Modes.Osu.Objects
s.Curve = new SliderCurve
{
Path = points,
ControlPoints = points,
Length = length,
CurveType = curveType
};
@@ -98,7 +101,10 @@ namespace osu.Game.Modes.Osu.Objects
}
result.Position = new Vector2(int.Parse(split[0]), int.Parse(split[1]));
result.StartTime = double.Parse(split[2]);
result.Sample = new HitSampleInfo { Type = (SampleType)int.Parse(split[4]) };
result.Sample = new HitSampleInfo {
Type = (SampleType)int.Parse(split[4]),
Set = SampleSet.Soft,
};
result.NewCombo = combo;
// TODO: "addition" field
return result;
+48
View File
@@ -0,0 +1,48 @@
// 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.Game.Beatmaps;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects
{
public class Slider : OsuHitObject
{
public override double EndTime => StartTime + RepeatCount * Curve.Length / Velocity;
public override Vector2 EndPosition => RepeatCount % 2 == 0 ? Position : Curve.PositionAt(1);
private int stackHeight;
public override int StackHeight
{
get { return stackHeight; }
set
{
stackHeight = value;
if (Curve != null)
Curve.Offset = StackOffset;
}
}
public double Velocity;
public override void SetDefaultsFromBeatmap(Beatmap beatmap)
{
base.SetDefaultsFromBeatmap(beatmap);
Velocity = 100 / beatmap.BeatLengthAt(StartTime, true) * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier;
}
public int RepeatCount;
public SliderCurve Curve;
}
public enum CurveTypes
{
Catmull,
Bezier,
Linear,
PerfectCurve
}
}
+203
View File
@@ -0,0 +1,203 @@
// 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.Collections.Generic;
using OpenTK;
using System.Linq;
using osu.Framework.MathUtils;
using System.Diagnostics;
namespace osu.Game.Modes.Osu.Objects
{
public class SliderCurve
{
public double Length;
public List<Vector2> ControlPoints;
public CurveTypes CurveType;
public Vector2 Offset;
private List<Vector2> calculatedPath = new List<Vector2>();
private List<double> cumulativeLength = new List<double>();
private List<Vector2> calculateSubpath(List<Vector2> subControlPoints)
{
switch (CurveType)
{
case CurveTypes.Linear:
return subControlPoints;
case CurveTypes.PerfectCurve:
// If we have a different amount than 3 control points, use bezier for perfect curves.
if (ControlPoints.Count != 3)
return new BezierApproximator(subControlPoints).CreateBezier();
else
{
Debug.Assert(subControlPoints.Count == 3);
// Here we have exactly 3 control points. Attempt to fit a circular arc.
List<Vector2> subpath = new CircularArcApproximator(subControlPoints[0], subControlPoints[1], subControlPoints[2]).CreateArc();
if (subpath.Count == 0)
// For some reason a circular arc could not be fit to the 3 given points. Fall back
// to a numerically stable bezier approximation.
subpath = new BezierApproximator(subControlPoints).CreateBezier();
return subpath;
}
default:
return new BezierApproximator(subControlPoints).CreateBezier();
}
}
private void calculatePath()
{
calculatedPath.Clear();
// Sliders may consist of various subpaths separated by two consecutive vertices
// with the same position. The following loop parses these subpaths and computes
// their shape independently, consecutively appending them to calculatedPath.
List<Vector2> subControlPoints = new List<Vector2>();
for (int i = 0; i < ControlPoints.Count; ++i)
{
subControlPoints.Add(ControlPoints[i]);
if (i == ControlPoints.Count - 1 || ControlPoints[i] == ControlPoints[i + 1])
{
List<Vector2> subpath = calculateSubpath(subControlPoints);
for (int j = 0; j < subpath.Count; ++j)
// Only add those vertices that add a new segment to the path.
if (calculatedPath.Count == 0 || calculatedPath.Last() != subpath[j])
calculatedPath.Add(subpath[j]);
subControlPoints.Clear();
}
}
}
private void calculateCumulativeLengthAndTrimPath()
{
double l = 0;
cumulativeLength.Clear();
cumulativeLength.Add(l);
for (int i = 0; i < calculatedPath.Count - 1; ++i)
{
Vector2 diff = calculatedPath[i + 1] - calculatedPath[i];
double d = diff.Length;
// Shorten slider curves that are too long compared to what's
// in the .osu file.
if (Length - l < d)
{
calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((Length - l) / d);
calculatedPath.RemoveRange(i + 2, calculatedPath.Count - 2 - i);
l = Length;
cumulativeLength.Add(l);
break;
}
l += d;
cumulativeLength.Add(l);
}
//TODO: Figure out if the following code is needed in some cases. Judging by the map
// "Transform" http://osu.ppy.sh/s/484689 it seems like we should _not_ be doing this.
// Lengthen slider curves that are too short compared to what's
// in the .osu file.
/*if (l < Length && calculatedPath.Count > 1)
{
Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2];
double d = diff.Length;
if (d <= 0)
return;
calculatedPath[calculatedPath.Count - 1] += diff * (float)((Length - l) / d);
cumulativeLength[calculatedPath.Count - 1] = Length;
}*/
}
public void Calculate()
{
calculatePath();
calculateCumulativeLengthAndTrimPath();
}
private int indexOfDistance(double d)
{
int i = cumulativeLength.BinarySearch(d);
if (i < 0) i = ~i;
return i;
}
private double progressToDistance(double progress)
{
return MathHelper.Clamp(progress, 0, 1) * Length;
}
private Vector2 interpolateVertices(int i, double d)
{
if (calculatedPath.Count == 0)
return Vector2.Zero;
if (i <= 0)
return calculatedPath.First();
else if (i >= calculatedPath.Count)
return calculatedPath.Last();
Vector2 p0 = calculatedPath[i - 1];
Vector2 p1 = calculatedPath[i];
double d0 = cumulativeLength[i - 1];
double d1 = cumulativeLength[i];
// Avoid division by and almost-zero number in case two points are extremely close to each other.
if (Precision.AlmostEquals(d0, d1))
return p0;
double w = (d - d0) / (d1 - d0);
return p0 + (p1 - p0) * (float)w;
}
/// <summary>
/// Computes the slider curve until a given progress that ranges from 0 (beginning of the slider)
/// to 1 (end of the slider) and stores the generated path in the given list.
/// </summary>
/// <param name="path">The list to be filled with the computed curve.</param>
/// <param name="p0">Start progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider).</param>
/// <param name="p1">End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider).</param>
public void GetPathToProgress(List<Vector2> path, double p0, double p1)
{
double d0 = progressToDistance(p0);
double d1 = progressToDistance(p1);
path.Clear();
int i = 0;
for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i);
path.Add(interpolateVertices(i, d0) + Offset);
for (; i < calculatedPath.Count && cumulativeLength[i] <= d1; ++i)
path.Add(calculatedPath[i] + Offset);
path.Add(interpolateVertices(i, d1) + Offset);
}
/// <summary>
/// Computes the position on the slider at a given progress that ranges from 0 (beginning of the slider)
/// to 1 (end of the slider).
/// </summary>
/// <param name="progress">Ranges from 0 (beginning of the slider) to 1 (end of the slider).</param>
/// <returns></returns>
public Vector2 PositionAt(double progress)
{
double d = progressToDistance(progress);
return interpolateVertices(indexOfDistance(d), d) + Offset;
}
}
}
+9
View File
@@ -0,0 +1,9 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Osu.Objects
{
public class Spinner : OsuHitObject
{
}
}
@@ -1,3 +1,8 @@
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
+45
View File
@@ -0,0 +1,45 @@
// 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.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Osu
{
public class OsuRuleset : Ruleset
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new OsuHitRenderer { Beatmap = beatmap };
public override IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new[]
{
new BeatmapStatistic
{
Name = @"Circle count",
Content = beatmap.Beatmap.HitObjects.Count(h => h is HitCircle).ToString(),
Icon = FontAwesome.fa_dot_circle_o
},
new BeatmapStatistic
{
Name = @"Slider count",
Content = beatmap.Beatmap.HitObjects.Count(h => h is Slider).ToString(),
Icon = FontAwesome.fa_circle_o
}
};
public override FontAwesome Icon => FontAwesome.fa_osu_osu_o;
public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => new OsuScoreProcessor(hitObjectCount);
protected override PlayMode PlayMode => PlayMode.Osu;
}
}
+15
View File
@@ -0,0 +1,15 @@
// 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 System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace osu.Game.Modes.Osu
{
class OsuScore : Score
{
}
}
+63
View File
@@ -0,0 +1,63 @@
// 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.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables;
namespace osu.Game.Modes.Osu
{
class OsuScoreProcessor : ScoreProcessor
{
public OsuScoreProcessor(int hitObjectCount)
: base(hitObjectCount)
{
Health.Value = 1;
}
protected override void UpdateCalculations(JudgementInfo judgement)
{
if (judgement != null)
{
switch (judgement.Result)
{
case HitResult.Hit:
Combo.Value++;
Health.Value += 0.1f;
break;
case HitResult.Miss:
Combo.Value = 0;
Health.Value -= 0.2f;
break;
}
}
int score = 0;
int maxScore = 0;
foreach (OsuJudgementInfo j in Judgements)
{
switch (j.Score)
{
case OsuScoreResult.Miss:
maxScore += 300;
break;
case OsuScoreResult.Hit50:
score += 50;
maxScore += 300;
break;
case OsuScoreResult.Hit100:
score += 100;
maxScore += 300;
break;
case OsuScoreResult.Hit300:
score += 300;
maxScore += 300;
break;
}
}
TotalScore.Value = score;
Accuracy.Value = (double)score / maxScore;
}
}
}

Some files were not shown because too many files have changed in this diff Show More