mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 03:53:21 +08:00
Merge https://github.com/ppy/osu into playlist
This commit is contained in:
commit
963cd09bd0
@ -10,7 +10,7 @@ install:
|
||||
- cmd: git submodule update --init --recursive
|
||||
- cmd: choco install resharper-clt -y
|
||||
- cmd: choco install nvika -y
|
||||
- cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.1/CodeFileSanity.exe
|
||||
- cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.2.2/CodeFileSanity.exe
|
||||
before_build:
|
||||
- cmd: CodeFileSanity.exe
|
||||
- cmd: nuget restore
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 51737ec1320b4ea9dce4978f24e1d77a28f0a98e
|
||||
Subproject commit 45e75163b272b7aa023afec7801ea079aba4ee69
|
@ -1 +1 @@
|
||||
Subproject commit f85c594c182db2b01233e29ca52639b7baa00402
|
||||
Subproject commit 0cba3cbc167cfe94e07fe5b629c925e190be939e
|
@ -4,7 +4,7 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("osu.Desktop.Deploy")]
|
||||
@ -16,8 +16,8 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
@ -27,11 +27,11 @@ using System.Runtime.InteropServices;
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
|
@ -13,10 +13,10 @@ using osu.Game.Modes.Taiko;
|
||||
namespace osu.Desktop.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BenchmarkTest
|
||||
public class VisualTests
|
||||
{
|
||||
[Test]
|
||||
public void TestBenchmark()
|
||||
public void TestVisualTests()
|
||||
{
|
||||
using (var host = new HeadlessGameHost())
|
||||
{
|
||||
@ -25,7 +25,7 @@ namespace osu.Desktop.Tests
|
||||
Ruleset.Register(new ManiaRuleset());
|
||||
Ruleset.Register(new CatchRuleset());
|
||||
|
||||
host.Run(new Benchmark());
|
||||
host.Run(new AutomatedVisualTestGame());
|
||||
}
|
||||
}
|
||||
}
|
@ -56,7 +56,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BenchmarkTest.cs" />
|
||||
<Compile Include="VisualTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework.Desktop\osu.Framework.Desktop.csproj">
|
||||
|
20
osu.Desktop.VisualTests/AutomatedVisualTestGame.cs
Normal file
20
osu.Desktop.VisualTests/AutomatedVisualTestGame.cs
Normal file
@ -0,0 +1,20 @@
|
||||
// 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.Testing;
|
||||
using osu.Game;
|
||||
|
||||
namespace osu.Desktop.VisualTests
|
||||
{
|
||||
public class AutomatedVisualTestGame : OsuGameBase
|
||||
{
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
// Have to construct this here, rather than in the constructor, because
|
||||
// we depend on some dependencies to be loaded within OsuGameBase.load().
|
||||
Add(new TestRunner(new TestBrowser()));
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ namespace osu.Desktop.VisualTests.Beatmaps
|
||||
}
|
||||
|
||||
private readonly Beatmap beatmap;
|
||||
|
||||
|
||||
protected override Beatmap GetBeatmap() => beatmap;
|
||||
protected override Texture GetBackground() => null;
|
||||
protected override Track GetTrack() => null;
|
||||
|
@ -1,45 +0,0 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Game;
|
||||
|
||||
namespace osu.Desktop.VisualTests
|
||||
{
|
||||
public class Benchmark : OsuGameBase
|
||||
{
|
||||
private const double time_per_test = 200;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
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 {time_per_test}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 * time_per_test);
|
||||
}
|
||||
|
||||
Scheduler.AddDelayed(Host.Exit, f.TestCount * time_per_test);
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ namespace osu.Desktop.VisualTests.Platform
|
||||
public TestStorage(string baseName) : base(baseName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override SQLiteConnection GetDatabase(string name)
|
||||
{
|
||||
ISQLitePlatform platform;
|
||||
|
@ -27,7 +27,7 @@ namespace osu.Desktop.VisualTests
|
||||
Ruleset.Register(new CatchRuleset());
|
||||
|
||||
if (benchmark)
|
||||
host.Run(new Benchmark());
|
||||
host.Run(new AutomatedVisualTestGame());
|
||||
else
|
||||
host.Run(new VisualTestGame());
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Select;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Screens.Select.Options;
|
||||
|
||||
@ -26,7 +26,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
|
||||
Add(overlay);
|
||||
|
||||
AddButton(@"Toggle", overlay.ToggleVisibility);
|
||||
AddStep(@"Toggle", overlay.ToggleVisibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,14 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCaseChatDisplay : TestCase
|
||||
{
|
||||
private ScheduledDelegate messageRequest;
|
||||
|
||||
public override string Description => @"Testing chat api and overlay";
|
||||
|
||||
public override void Reset()
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Dialog;
|
||||
@ -20,7 +20,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
|
||||
Add(overlay = new DialogOverlay());
|
||||
|
||||
AddButton("dialog #1", () => overlay.Push(new PopupDialog
|
||||
AddStep("dialog #1", () => overlay.Push(new PopupDialog
|
||||
{
|
||||
Icon = FontAwesome.fa_trash_o,
|
||||
HeaderText = @"Confirm deletion of",
|
||||
@ -40,7 +40,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
},
|
||||
}));
|
||||
|
||||
AddButton("dialog #2", () => overlay.Push(new PopupDialog
|
||||
AddStep("dialog #2", () => overlay.Push(new PopupDialog
|
||||
{
|
||||
Icon = FontAwesome.fa_gear,
|
||||
HeaderText = @"What do you want to do with",
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Tournament;
|
||||
using osu.Game.Screens.Tournament.Teams;
|
||||
using osu.Game.Users;
|
||||
|
@ -5,7 +5,7 @@ using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
|
@ -8,7 +8,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
@ -93,19 +93,28 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
|
||||
playbackSpeed.TriggerChange();
|
||||
|
||||
AddButton(@"circles", () => load(HitObjectType.Circle));
|
||||
AddButton(@"slider", () => load(HitObjectType.Slider));
|
||||
AddButton(@"spinner", () => load(HitObjectType.Spinner));
|
||||
AddStep(@"circles", () => load(HitObjectType.Circle));
|
||||
AddStep(@"slider", () => load(HitObjectType.Slider));
|
||||
AddStep(@"spinner", () => load(HitObjectType.Spinner));
|
||||
|
||||
AddToggle(@"auto", state => { auto = state; load(mode); });
|
||||
AddToggleStep(@"auto", state => { auto = state; load(mode); });
|
||||
|
||||
ButtonsContainer.Add(new SpriteText { Text = "Playback Speed" });
|
||||
ButtonsContainer.Add(new BasicSliderBar<double>
|
||||
Add(new Container
|
||||
{
|
||||
Width = 150,
|
||||
Height = 10,
|
||||
SelectionColor = Color4.Orange,
|
||||
Bindable = playbackSpeed
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SpriteText { Text = "Playback Speed" },
|
||||
new BasicSliderBar<double>
|
||||
{
|
||||
Width = 150,
|
||||
Height = 10,
|
||||
SelectionColor = Color4.Orange,
|
||||
Value = playbackSpeed
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
framedClock.ProcessFrame();
|
||||
|
@ -1,16 +1,16 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
@ -38,19 +38,30 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
};
|
||||
BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 };
|
||||
bindable.ValueChanged += delegate { kc.FadeTime = bindable.Value; };
|
||||
AddButton("Add Random", () =>
|
||||
AddStep("Add Random", () =>
|
||||
{
|
||||
Key key = (Key)((int)Key.A + RNG.Next(26));
|
||||
kc.Add(new KeyCounterKeyboard(key));
|
||||
});
|
||||
ButtonsContainer.Add(new SpriteText { Text = "FadeTime" });
|
||||
ButtonsContainer.Add(new TestSliderBar<int>
|
||||
|
||||
Add(new Container
|
||||
{
|
||||
Width = 150,
|
||||
Height = 10,
|
||||
SelectionColor = Color4.Orange,
|
||||
Bindable = bindable
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SpriteText { Text = "FadeTime" },
|
||||
new TestSliderBar<int>
|
||||
{
|
||||
Width = 150,
|
||||
Height = 10,
|
||||
SelectionColor = Color4.Orange,
|
||||
Value = bindable
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Add(kc);
|
||||
}
|
||||
private class TestSliderBar<T> : SliderBar<T> where T : struct
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Game.Modes;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Modes.Mods;
|
||||
using osu.Game.Modes.Osu.Mods;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Users;
|
||||
|
||||
@ -218,7 +218,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Size = new Vector2(550f, 450f),
|
||||
});
|
||||
|
||||
AddButton(@"New Scores", newScores);
|
||||
AddStep(@"New Scores", newScores);
|
||||
newScores();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Screens.Menu;
|
||||
|
59
osu.Desktop.VisualTests/Tests/TestCaseMenuOverlays.cs
Normal file
59
osu.Desktop.VisualTests/Tests/TestCaseMenuOverlays.cs
Normal file
@ -0,0 +1,59 @@
|
||||
// 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.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCaseMenuOverlays : TestCase
|
||||
{
|
||||
public override string Description => @"Tests pause and fail overlays";
|
||||
|
||||
private PauseOverlay pauseOverlay;
|
||||
private FailOverlay failOverlay;
|
||||
private int retryCount;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
retryCount = 0;
|
||||
|
||||
Add(pauseOverlay = new PauseOverlay
|
||||
{
|
||||
OnResume = () => Logger.Log(@"Resume"),
|
||||
OnRetry = () => Logger.Log(@"Retry"),
|
||||
OnQuit = () => Logger.Log(@"Quit"),
|
||||
});
|
||||
Add(failOverlay = new FailOverlay
|
||||
{
|
||||
OnRetry = () => Logger.Log(@"Retry"),
|
||||
OnQuit = () => Logger.Log(@"Quit"),
|
||||
});
|
||||
|
||||
AddStep(@"Pause", delegate {
|
||||
if(failOverlay.State == Visibility.Visible)
|
||||
{
|
||||
failOverlay.Hide();
|
||||
}
|
||||
pauseOverlay.Show();
|
||||
});
|
||||
AddStep("Fail", delegate {
|
||||
if (pauseOverlay.State == Visibility.Visible)
|
||||
{
|
||||
pauseOverlay.Hide();
|
||||
}
|
||||
failOverlay.Show();
|
||||
});
|
||||
AddStep("Add Retry", delegate
|
||||
{
|
||||
retryCount++;
|
||||
pauseOverlay.Retries = retryCount;
|
||||
failOverlay.Retries = retryCount;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Modes;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
@ -25,11 +25,11 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Anchor = Anchor.BottomCentre,
|
||||
});
|
||||
|
||||
AddButton("Toggle", modSelect.ToggleVisibility);
|
||||
AddButton("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu);
|
||||
AddButton("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko);
|
||||
AddButton("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch);
|
||||
AddButton("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania);
|
||||
AddStep("Toggle", modSelect.ToggleVisibility);
|
||||
AddStep("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu);
|
||||
AddStep("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko);
|
||||
AddStep("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch);
|
||||
AddStep("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Overlays;
|
||||
@ -30,7 +30,9 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Anchor = Anchor.Centre
|
||||
};
|
||||
Add(mc);
|
||||
AddToggle(@"Show", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||
|
||||
AddToggleStep(@"toggle visibility", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||
AddStep(@"show", () => mc.State = Visibility.Visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Overlays;
|
||||
using System.Linq;
|
||||
@ -30,13 +30,13 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Origin = Anchor.TopRight,
|
||||
});
|
||||
|
||||
AddToggle(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||
AddToggleStep(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||
|
||||
AddButton(@"simple #1", sendNotification1);
|
||||
AddButton(@"simple #2", sendNotification2);
|
||||
AddButton(@"progress #1", sendProgress1);
|
||||
AddButton(@"progress #2", sendProgress2);
|
||||
AddButton(@"barrage", () => sendBarrage());
|
||||
AddStep(@"simple #1", sendNotification1);
|
||||
AddStep(@"simple #2", sendNotification2);
|
||||
AddStep(@"progress #1", sendProgress1);
|
||||
AddStep(@"progress #2", sendProgress2);
|
||||
AddStep(@"barrage", () => sendBarrage());
|
||||
}
|
||||
|
||||
private void sendBarrage(int remaining = 100)
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
|
@ -1,38 +0,0 @@
|
||||
// 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.Logging;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCasePauseOverlay : TestCase
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Desktop.VisualTests.Platform;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Modes;
|
||||
@ -14,7 +14,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCasePlaySongSelect : TestCase
|
||||
{
|
||||
private BeatmapDatabase db, oldDb;
|
||||
private BeatmapDatabase db;
|
||||
private TestStorage storage;
|
||||
private PlaySongSelect songSelect;
|
||||
|
||||
@ -23,12 +23,10 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
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>();
|
||||
|
||||
@ -40,22 +38,19 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
|
||||
Add(songSelect = new PlaySongSelect());
|
||||
|
||||
AddButton(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
|
||||
AddButton(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
|
||||
AddButton(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
|
||||
AddButton(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
|
||||
AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
|
||||
AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
|
||||
AddStep(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
|
||||
AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
if (oldDb != null)
|
||||
{
|
||||
Dependencies.Cache(oldDb, true);
|
||||
db = null;
|
||||
}
|
||||
//protected override void Dispose(bool isDisposing)
|
||||
//{
|
||||
// if (oldDb != null)
|
||||
// db = null;
|
||||
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
// base.Dispose(isDisposing);
|
||||
//}
|
||||
|
||||
private BeatmapSetInfo createTestBeatmapSet(int i)
|
||||
{
|
||||
|
@ -4,7 +4,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
@ -1,24 +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 osu.Framework.Input.Handlers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Mods;
|
||||
using osu.Game.Modes.Osu.Mods;
|
||||
using osu.Game.Screens.Play;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCaseReplay : TestCasePlayer
|
||||
{
|
||||
private WorkingBeatmap beatmap;
|
||||
|
||||
private InputHandler replay;
|
||||
|
||||
private Func<Stream> getReplayStream;
|
||||
|
||||
public override string Description => @"Testing replay playback.";
|
||||
|
||||
protected override Player CreatePlayer(WorkingBeatmap beatmap)
|
||||
|
@ -6,7 +6,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Modes.UI;
|
||||
|
||||
@ -22,8 +22,6 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
|
||||
int numerator = 0, denominator = 0;
|
||||
|
||||
bool maniaHold = false;
|
||||
|
||||
ScoreCounter score = new ScoreCounter(7)
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
@ -68,7 +66,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
};
|
||||
Add(starsLabel);
|
||||
|
||||
AddButton(@"Reset all", delegate
|
||||
AddStep(@"Reset all", delegate
|
||||
{
|
||||
score.Current.Value = 0;
|
||||
comboCounter.Current.Value = 0;
|
||||
@ -78,7 +76,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
starsLabel.Text = stars.Count.ToString("0.00");
|
||||
});
|
||||
|
||||
AddButton(@"Hit! :D", delegate
|
||||
AddStep(@"Hit! :D", delegate
|
||||
{
|
||||
score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
|
||||
comboCounter.Increment();
|
||||
@ -86,20 +84,20 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
accuracyCounter.SetFraction(numerator, denominator);
|
||||
});
|
||||
|
||||
AddButton(@"miss...", delegate
|
||||
AddStep(@"miss...", delegate
|
||||
{
|
||||
comboCounter.Current.Value = 0;
|
||||
denominator++;
|
||||
accuracyCounter.SetFraction(numerator, denominator);
|
||||
});
|
||||
|
||||
AddButton(@"Alter stars", delegate
|
||||
AddStep(@"Alter stars", delegate
|
||||
{
|
||||
stars.Count = RNG.NextSingle() * (stars.StarCount + 1);
|
||||
starsLabel.Text = stars.Count.ToString("0.00");
|
||||
});
|
||||
|
||||
AddButton(@"Stop counters", delegate
|
||||
AddStep(@"Stop counters", delegate
|
||||
{
|
||||
score.StopRolling();
|
||||
comboCounter.StopRolling();
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Select.Filter;
|
||||
@ -36,9 +36,9 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
filter.PinItem(GroupMode.All);
|
||||
filter.PinItem(GroupMode.RecentlyPlayed);
|
||||
|
||||
filter.ItemChanged += (sender, mode) =>
|
||||
filter.SelectedItem.ValueChanged += newFilter =>
|
||||
{
|
||||
text.Text = "Currently Selected: " + mode.ToString();
|
||||
text.Text = "Currently Selected: " + newFilter.ToString();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
121
osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs
Normal file
121
osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs
Normal file
@ -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.Linq;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCaseTaikoHitObjects : TestCase
|
||||
{
|
||||
public override string Description => "Taiko hit objects";
|
||||
|
||||
private bool kiai;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
AddToggleStep("Kiai", b =>
|
||||
{
|
||||
kiai = !kiai;
|
||||
updateKiaiState();
|
||||
});
|
||||
|
||||
Add(new CirclePiece
|
||||
{
|
||||
Position = new Vector2(100, 100),
|
||||
AccentColour = Color4.DarkRed,
|
||||
KiaiMode = kiai,
|
||||
Children = new[]
|
||||
{
|
||||
new CentreHitSymbolPiece()
|
||||
}
|
||||
});
|
||||
|
||||
Add(new CirclePiece(true)
|
||||
{
|
||||
Position = new Vector2(350, 100),
|
||||
AccentColour = Color4.DarkRed,
|
||||
KiaiMode = kiai,
|
||||
Children = new[]
|
||||
{
|
||||
new CentreHitSymbolPiece()
|
||||
}
|
||||
});
|
||||
|
||||
Add(new CirclePiece
|
||||
{
|
||||
Position = new Vector2(100, 300),
|
||||
AccentColour = Color4.DarkBlue,
|
||||
KiaiMode = kiai,
|
||||
Children = new[]
|
||||
{
|
||||
new RimHitSymbolPiece()
|
||||
}
|
||||
});
|
||||
|
||||
Add(new CirclePiece(true)
|
||||
{
|
||||
Position = new Vector2(350, 300),
|
||||
AccentColour = Color4.DarkBlue,
|
||||
KiaiMode = kiai,
|
||||
Children = new[]
|
||||
{
|
||||
new RimHitSymbolPiece()
|
||||
}
|
||||
});
|
||||
|
||||
Add(new CirclePiece
|
||||
{
|
||||
Position = new Vector2(100, 500),
|
||||
AccentColour = Color4.Orange,
|
||||
KiaiMode = kiai,
|
||||
Children = new[]
|
||||
{
|
||||
new SwellSymbolPiece()
|
||||
}
|
||||
});
|
||||
|
||||
Add(new ElongatedCirclePiece
|
||||
{
|
||||
Position = new Vector2(575, 100),
|
||||
AccentColour = Color4.Orange,
|
||||
KiaiMode = kiai,
|
||||
Length = 0.10f,
|
||||
PlayfieldLengthReference = () => DrawSize.X
|
||||
});
|
||||
|
||||
Add(new ElongatedCirclePiece(true)
|
||||
{
|
||||
Position = new Vector2(575, 300),
|
||||
AccentColour = Color4.Orange,
|
||||
KiaiMode = kiai,
|
||||
Length = 0.10f,
|
||||
PlayfieldLengthReference = () => DrawSize.X
|
||||
});
|
||||
}
|
||||
|
||||
private void updateKiaiState()
|
||||
{
|
||||
foreach (var c in Children.OfType<CirclePiece>())
|
||||
c.KiaiMode = kiai;
|
||||
}
|
||||
|
||||
private abstract class BaseCircle : Container
|
||||
{
|
||||
protected readonly CirclePiece Piece;
|
||||
|
||||
protected BaseCircle(CirclePiece piece)
|
||||
{
|
||||
Piece = piece;
|
||||
|
||||
Add(Piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +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 osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.Judgements;
|
||||
using osu.Game.Modes.Taiko.Objects;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.UI;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
@ -16,16 +20,40 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
|
||||
private TaikoPlayfield playfield;
|
||||
|
||||
protected override double TimePerAction => default_duration * 2;
|
||||
|
||||
private const double default_duration = 300;
|
||||
|
||||
private const float scroll_time = 1000;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
AddButton("Hit!", addHitJudgement);
|
||||
AddButton("Miss :(", addMissJudgement);
|
||||
AddStep("Hit!", addHitJudgement);
|
||||
AddStep("Miss :(", addMissJudgement);
|
||||
AddStep("DrumRoll", () => addDrumRoll(false));
|
||||
AddStep("Strong DrumRoll", () => addDrumRoll(true));
|
||||
AddStep("Swell", () => addSwell());
|
||||
AddStep("Centre", () => addCentreHit(false));
|
||||
AddStep("Strong Centre", () => addCentreHit(true));
|
||||
AddStep("Rim", () => addRimHit(false));
|
||||
AddStep("Strong Rim", () => addRimHit(true));
|
||||
AddStep("Add bar line", () => addBarLine(false));
|
||||
AddStep("Add major bar line", () => addBarLine(true));
|
||||
|
||||
Add(playfield = new TaikoPlayfield
|
||||
|
||||
var rateAdjustClock = new StopwatchClock(true) { Rate = 1 };
|
||||
|
||||
Add(new Container
|
||||
{
|
||||
Y = 200
|
||||
Clock = new FramedClock(rateAdjustClock),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Y = 200,
|
||||
Children = new[]
|
||||
{
|
||||
playfield = new TaikoPlayfield()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -41,7 +69,6 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Result = HitResult.Hit,
|
||||
TaikoResult = hitResult,
|
||||
TimeOffset = 0,
|
||||
ComboAtHit = 1,
|
||||
SecondHit = RNG.Next(10) == 0
|
||||
}
|
||||
});
|
||||
@ -54,12 +81,76 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Judgement = new TaikoJudgement
|
||||
{
|
||||
Result = HitResult.Miss,
|
||||
TimeOffset = 0,
|
||||
ComboAtHit = 0
|
||||
TimeOffset = 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addBarLine(bool major, double delay = scroll_time)
|
||||
{
|
||||
BarLine bl = new BarLine
|
||||
{
|
||||
StartTime = playfield.Time.Current + delay,
|
||||
ScrollTime = scroll_time
|
||||
};
|
||||
|
||||
playfield.AddBarLine(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl));
|
||||
}
|
||||
|
||||
private void addSwell(double duration = default_duration)
|
||||
{
|
||||
playfield.Add(new DrawableSwell(new Swell
|
||||
{
|
||||
StartTime = playfield.Time.Current + scroll_time,
|
||||
Duration = duration,
|
||||
ScrollTime = scroll_time
|
||||
}));
|
||||
}
|
||||
|
||||
private void addDrumRoll(bool strong, double duration = default_duration)
|
||||
{
|
||||
addBarLine(true);
|
||||
addBarLine(true, scroll_time + duration);
|
||||
|
||||
var d = new DrumRoll
|
||||
{
|
||||
StartTime = playfield.Time.Current + scroll_time,
|
||||
IsStrong = strong,
|
||||
Duration = duration,
|
||||
ScrollTime = scroll_time,
|
||||
};
|
||||
|
||||
playfield.Add(new DrawableDrumRoll(d));
|
||||
}
|
||||
|
||||
private void addCentreHit(bool strong)
|
||||
{
|
||||
Hit h = new Hit
|
||||
{
|
||||
StartTime = playfield.Time.Current + scroll_time,
|
||||
ScrollTime = scroll_time
|
||||
};
|
||||
|
||||
if (strong)
|
||||
playfield.Add(new DrawableCentreHitStrong(h));
|
||||
else
|
||||
playfield.Add(new DrawableCentreHit(h));
|
||||
}
|
||||
|
||||
private void addRimHit(bool strong)
|
||||
{
|
||||
Hit h = new Hit
|
||||
{
|
||||
StartTime = playfield.Time.Current + scroll_time,
|
||||
ScrollTime = scroll_time
|
||||
};
|
||||
|
||||
if (strong)
|
||||
playfield.Add(new DrawableRimHitStrong(h));
|
||||
else
|
||||
playfield.Add(new DrawableRimHit(h));
|
||||
}
|
||||
|
||||
private class DrawableTestHit : DrawableHitObject<TaikoHitObject, TaikoJudgement>
|
||||
{
|
||||
public DrawableTestHit(TaikoHitObject hitObject)
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.MathUtils;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
|
||||
@ -14,7 +14,7 @@ namespace osu.Desktop.VisualTests
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
new BackgroundScreenDefault { Depth = 10 }.LoadAsync(this, AddInternal);
|
||||
LoadComponentAsync(new BackgroundScreenDefault { Depth = 10 }, AddInternal);
|
||||
|
||||
// Have to construct this here, rather than in the constructor, because
|
||||
// we depend on some dependencies to be loaded within OsuGameBase.load().
|
||||
@ -24,6 +24,11 @@ namespace osu.Desktop.VisualTests
|
||||
public override void SetHost(GameHost host)
|
||||
{
|
||||
base.SetHost(host);
|
||||
|
||||
host.UpdateThread.InactiveHz = host.UpdateThread.ActiveHz;
|
||||
host.DrawThread.InactiveHz = host.DrawThread.ActiveHz;
|
||||
host.InputThread.InactiveHz = host.InputThread.ActiveHz;
|
||||
|
||||
host.Window.CursorState = CursorState.Hidden;
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,10 @@
|
||||
<Project>{65dc628f-a640-4111-ab35-3a5652bc1e17}</Project>
|
||||
<Name>osu.Framework.Desktop</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework.Testing\osu.Framework.Testing.csproj">
|
||||
<Project>{007b2356-ab6f-4bd9-96d5-116fc2dce69a}</Project>
|
||||
<Name>osu.Framework.Testing</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||
<Project>{c76bf5b3-985e-4d39-95fe-97c9c879b83a}</Project>
|
||||
<Name>osu.Framework</Name>
|
||||
@ -180,11 +184,12 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Benchmark.cs" />
|
||||
<Compile Include="AutomatedVisualTestGame.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Tests\TestCaseChatDisplay.cs" />
|
||||
<Compile Include="Tests\TestCaseDrawings.cs" />
|
||||
<Compile Include="Tests\TestCaseGamefield.cs" />
|
||||
<Compile Include="Tests\TestCaseMenuOverlays.cs" />
|
||||
<Compile Include="Tests\TestCaseMusicController.cs" />
|
||||
<Compile Include="Tests\TestCaseNotificationManager.cs" />
|
||||
<Compile Include="Tests\TestCasePlayer.cs" />
|
||||
@ -194,6 +199,7 @@
|
||||
<Compile Include="Tests\TestCaseReplay.cs" />
|
||||
<Compile Include="Tests\TestCaseScoreCounter.cs" />
|
||||
<Compile Include="Tests\TestCaseTabControl.cs" />
|
||||
<Compile Include="Tests\TestCaseTaikoHitObjects.cs" />
|
||||
<Compile Include="Tests\TestCaseTaikoPlayfield.cs" />
|
||||
<Compile Include="Tests\TestCaseTextAwesome.cs" />
|
||||
<Compile Include="Tests\TestCasePlaySongSelect.cs" />
|
||||
@ -201,7 +207,6 @@
|
||||
<Compile Include="VisualTestGame.cs" />
|
||||
<Compile Include="Platform\TestStorage.cs" />
|
||||
<Compile Include="Tests\TestCaseOptions.cs" />
|
||||
<Compile Include="Tests\TestCasePauseOverlay.cs" />
|
||||
<Compile Include="Tests\TestCaseModSelectOverlay.cs" />
|
||||
<Compile Include="Tests\TestCaseDialogOverlay.cs" />
|
||||
<Compile Include="Tests\TestCaseBeatmapOptionsOverlay.cs" />
|
||||
@ -211,9 +216,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Folder Include="Beatmaps\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
@ -3,10 +3,7 @@
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Beatmaps.IO;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Desktop.Beatmaps.IO
|
||||
{
|
||||
@ -18,20 +15,17 @@ namespace osu.Desktop.Beatmaps.IO
|
||||
public static void Register() => AddReader<LegacyFilesystemReader>((storage, path) => Directory.Exists(path));
|
||||
|
||||
private string basePath { get; }
|
||||
private Beatmap firstMap { get; }
|
||||
|
||||
public LegacyFilesystemReader(string path)
|
||||
{
|
||||
basePath = path;
|
||||
|
||||
BeatmapFilenames = Directory.GetFiles(basePath, @"*.osu").Select(Path.GetFileName).ToArray();
|
||||
|
||||
if (BeatmapFilenames.Length == 0)
|
||||
throw new FileNotFoundException(@"This directory contains no beatmaps");
|
||||
|
||||
StoryboardFilename = Directory.GetFiles(basePath, @"*.osb").Select(Path.GetFileName).FirstOrDefault();
|
||||
using (var stream = new StreamReader(GetStream(BeatmapFilenames[0])))
|
||||
{
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
firstMap = decoder.Decode(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream GetStream(string name)
|
||||
@ -39,11 +33,6 @@ namespace osu.Desktop.Beatmaps.IO
|
||||
return File.OpenRead(Path.Combine(basePath, name));
|
||||
}
|
||||
|
||||
public override BeatmapMetadata ReadMetadata()
|
||||
{
|
||||
return firstMap.BeatmapInfo.Metadata;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
// no-op
|
||||
|
29
osu.Desktop/OpenTK.dll.config
Normal file
29
osu.Desktop/OpenTK.dll.config
Normal file
@ -0,0 +1,29 @@
|
||||
<!--
|
||||
Copyright (c) 2007-2017 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"/>
|
||||
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||
</configuration>
|
@ -29,7 +29,7 @@ namespace osu.Desktop
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
versionManager.LoadAsync(this);
|
||||
LoadComponentAsync(versionManager);
|
||||
ScreenChanged += s =>
|
||||
{
|
||||
if (!versionManager.IsAlive && s is Intro)
|
||||
|
@ -4,7 +4,7 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("osu!lazer")]
|
||||
@ -16,8 +16,8 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
|
@ -123,7 +123,10 @@
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4" />
|
||||
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1340\lib\net45\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@ -150,6 +153,7 @@
|
||||
<None Include="..\osu.licenseheader">
|
||||
<Link>osu.licenseheader</Link>
|
||||
</None>
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="osu!.res" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\app.manifest" />
|
||||
|
@ -7,6 +7,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
||||
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
|
||||
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net45" />
|
||||
<package id="ppy.OpenTK" version="2.0.50727.1340" targetFramework="net45" />
|
||||
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
||||
<package id="squirrel.windows" version="1.5.2" targetFramework="net45" />
|
||||
</packages>
|
@ -10,6 +10,8 @@ using osu.Game.Modes.Mods;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Catch.Scoring;
|
||||
using osu.Game.Modes.Scoring;
|
||||
|
||||
namespace osu.Game.Modes.Catch
|
||||
{
|
||||
|
@ -7,8 +7,8 @@ namespace osu.Game.Modes.Catch.Judgements
|
||||
{
|
||||
public class CatchJudgement : Judgement
|
||||
{
|
||||
public override string ScoreString => string.Empty;
|
||||
public override string ResultString => string.Empty;
|
||||
|
||||
public override string MaxScoreString => string.Empty;
|
||||
public override string MaxResultString => string.Empty;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("osu.Game.Modes.Catch")]
|
||||
@ -16,8 +16,8 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
@ -27,11 +27,11 @@ using System.Runtime.InteropServices;
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
using osu.Game.Modes.Catch.Judgements;
|
||||
using osu.Game.Modes.Catch.Objects;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using osu.Game.Modes.UI;
|
||||
|
||||
namespace osu.Game.Modes.Catch
|
||||
namespace osu.Game.Modes.Catch.Scoring
|
||||
{
|
||||
internal class CatchScoreProcessor : ScoreProcessor<CatchBaseHit, CatchJudgement>
|
||||
{
|
||||
@ -18,7 +19,7 @@ namespace osu.Game.Modes.Catch
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateCalculations(CatchJudgement newJudgement)
|
||||
protected override void OnNewJudgement(CatchJudgement judgement)
|
||||
{
|
||||
}
|
||||
}
|
@ -5,7 +5,9 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Catch.Beatmaps;
|
||||
using osu.Game.Modes.Catch.Judgements;
|
||||
using osu.Game.Modes.Catch.Objects;
|
||||
using osu.Game.Modes.Catch.Scoring;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using osu.Game.Modes.UI;
|
||||
|
||||
namespace osu.Game.Modes.Catch.UI
|
||||
|
@ -50,7 +50,7 @@
|
||||
<Compile Include="Beatmaps\CatchBeatmapConverter.cs" />
|
||||
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
|
||||
<Compile Include="CatchDifficultyCalculator.cs" />
|
||||
<Compile Include="CatchScoreProcessor.cs" />
|
||||
<Compile Include="Scoring\CatchScoreProcessor.cs" />
|
||||
<Compile Include="Judgements\CatchJudgement.cs" />
|
||||
<Compile Include="Objects\CatchBaseHit.cs" />
|
||||
<Compile Include="Objects\Drawable\DrawableFruit.cs" />
|
||||
|
@ -7,8 +7,8 @@ namespace osu.Game.Modes.Mania.Judgements
|
||||
{
|
||||
public class ManiaJudgement : Judgement
|
||||
{
|
||||
public override string ScoreString => string.Empty;
|
||||
public override string ResultString => string.Empty;
|
||||
|
||||
public override string MaxScoreString => string.Empty;
|
||||
public override string MaxResultString => string.Empty;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ using osu.Game.Modes.Mods;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Mania.Scoring;
|
||||
using osu.Game.Modes.Scoring;
|
||||
|
||||
namespace osu.Game.Modes.Mania
|
||||
{
|
||||
|
@ -4,7 +4,7 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("osu.Game.Modes.Mania")]
|
||||
@ -16,8 +16,8 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
@ -27,11 +27,11 @@ using System.Runtime.InteropServices;
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
using osu.Game.Modes.Mania.Judgements;
|
||||
using osu.Game.Modes.Mania.Objects;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using osu.Game.Modes.UI;
|
||||
|
||||
namespace osu.Game.Modes.Mania
|
||||
namespace osu.Game.Modes.Mania.Scoring
|
||||
{
|
||||
internal class ManiaScoreProcessor : ScoreProcessor<ManiaBaseHit, ManiaJudgement>
|
||||
{
|
||||
@ -18,7 +19,7 @@ namespace osu.Game.Modes.Mania
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateCalculations(ManiaJudgement newJudgement)
|
||||
protected override void OnNewJudgement(ManiaJudgement judgement)
|
||||
{
|
||||
}
|
||||
}
|
@ -5,7 +5,9 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Mania.Beatmaps;
|
||||
using osu.Game.Modes.Mania.Judgements;
|
||||
using osu.Game.Modes.Mania.Objects;
|
||||
using osu.Game.Modes.Mania.Scoring;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using osu.Game.Modes.UI;
|
||||
|
||||
namespace osu.Game.Modes.Mania.UI
|
||||
|
@ -51,7 +51,7 @@
|
||||
<Compile Include="Beatmaps\ManiaBeatmapProcessor.cs" />
|
||||
<Compile Include="Judgements\ManiaJudgement.cs" />
|
||||
<Compile Include="ManiaDifficultyCalculator.cs" />
|
||||
<Compile Include="ManiaScoreProcessor.cs" />
|
||||
<Compile Include="Scoring\ManiaScoreProcessor.cs" />
|
||||
<Compile Include="Objects\Drawable\DrawableNote.cs" />
|
||||
<Compile Include="Objects\HoldNote.cs" />
|
||||
<Compile Include="Objects\ManiaBaseHit.cs" />
|
||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Modes.Osu.Beatmaps
|
||||
return new Slider
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
Samples = original.Samples,
|
||||
CurveObject = curveData,
|
||||
Position = positionData?.Position ?? Vector2.Zero,
|
||||
NewCombo = comboData?.NewCombo ?? false
|
||||
@ -55,7 +55,7 @@ namespace osu.Game.Modes.Osu.Beatmaps
|
||||
return new Spinner
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
Samples = original.Samples,
|
||||
Position = new Vector2(512, 384) / 2,
|
||||
EndTime = endTimeData.EndTime
|
||||
};
|
||||
@ -64,7 +64,7 @@ namespace osu.Game.Modes.Osu.Beatmaps
|
||||
return new HitCircle
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
Samples = original.Samples,
|
||||
Position = positionData?.Position ?? Vector2.Zero,
|
||||
NewCombo = comboData?.NewCombo ?? false
|
||||
};
|
||||
|
@ -25,9 +25,9 @@ namespace osu.Game.Modes.Osu.Judgements
|
||||
/// </summary>
|
||||
public OsuScoreResult MaxScore = OsuScoreResult.Hit300;
|
||||
|
||||
public override string ScoreString => Score.GetDescription();
|
||||
public override string ResultString => Score.GetDescription();
|
||||
|
||||
public override string MaxScoreString => MaxScore.GetDescription();
|
||||
public override string MaxResultString => MaxScore.GetDescription();
|
||||
|
||||
public int ScoreValue => scoreToInt(Score);
|
||||
|
||||
|
@ -7,6 +7,7 @@ using osu.Game.Modes.Mods;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Modes.Scoring;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Mods
|
||||
{
|
||||
|
@ -7,7 +7,6 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
|
||||
{
|
||||
@ -33,7 +32,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
|
||||
Colour = Color4.White.Opacity(0.2f),
|
||||
Radius = 4,
|
||||
};
|
||||
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
@ -39,7 +38,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
Colour = AccentColour,
|
||||
Hit = () =>
|
||||
{
|
||||
if (Judgement.Result.HasValue) return false;
|
||||
if (Judgement.Result != HitResult.None) return false;
|
||||
|
||||
Judgement.PositionOffset = Vector2.Zero; //todo: set to correct value
|
||||
UpdateJudgement(true);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 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.Transforms;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Judgements;
|
||||
using OpenTK;
|
||||
|
@ -67,7 +67,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
ComboIndex = s.ComboIndex,
|
||||
Scale = s.Scale,
|
||||
ComboColour = s.ComboColour,
|
||||
Sample = s.Sample,
|
||||
Samples = s.Samples,
|
||||
}),
|
||||
};
|
||||
|
||||
@ -111,7 +111,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
if (repeat > currentRepeat)
|
||||
{
|
||||
if (repeat < slider.RepeatCount && ball.Tracking)
|
||||
PlaySample();
|
||||
PlaySamples();
|
||||
currentRepeat = repeat;
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,8 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Judgements;
|
||||
using OpenTK;
|
||||
@ -54,22 +49,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
};
|
||||
}
|
||||
|
||||
private SampleChannel sample;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
string sampleSet = (HitObject.Sample?.Set ?? SampleSet.Normal).ToString().ToLower();
|
||||
|
||||
sample = audio.Sample.Get($@"Gameplay/{sampleSet}-slidertick");
|
||||
}
|
||||
|
||||
protected override void PlaySample()
|
||||
{
|
||||
sample?.Play();
|
||||
}
|
||||
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset >= 0)
|
||||
@ -78,7 +57,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
Judgement.Score = Tracking ? OsuScoreResult.SliderTick : OsuScoreResult.Miss;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void UpdatePreemptState()
|
||||
{
|
||||
var animIn = Math.Min(150, sliderTick.StartTime - FadeInTime);
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
|
||||
|
@ -4,7 +4,6 @@
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
|
@ -2,18 +2,24 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Database;
|
||||
using System.Linq;
|
||||
using osu.Game.Audio;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
public class Slider : OsuHitObject, IHasCurve
|
||||
{
|
||||
/// <summary>
|
||||
/// Scoring distance with a speed-adjusted beat length of 1 second.
|
||||
/// </summary>
|
||||
private const float base_scoring_distance = 100;
|
||||
|
||||
public IHasCurve CurveObject { get; set; }
|
||||
|
||||
public SliderCurve Curve => CurveObject.Curve;
|
||||
@ -51,13 +57,10 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
base.ApplyDefaults(timing, difficulty);
|
||||
|
||||
ControlPoint overridePoint;
|
||||
ControlPoint timingPoint = timing.TimingPointAt(StartTime, out overridePoint);
|
||||
var velocityAdjustment = overridePoint?.VelocityAdjustment ?? 1;
|
||||
var baseVelocity = 100 * difficulty.SliderMultiplier / velocityAdjustment;
|
||||
double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier / timing.SpeedMultiplierAt(StartTime);
|
||||
|
||||
Velocity = baseVelocity / timingPoint.BeatLength;
|
||||
TickDistance = baseVelocity / difficulty.SliderTickRate;
|
||||
Velocity = scoringDistance / timing.BeatLengthAt(StartTime);
|
||||
TickDistance = scoringDistance / difficulty.SliderTickRate;
|
||||
}
|
||||
|
||||
public IEnumerable<SliderTick> Ticks
|
||||
@ -93,11 +96,12 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
StackHeight = StackHeight,
|
||||
Scale = Scale,
|
||||
ComboColour = ComboColour,
|
||||
Sample = new HitSampleInfo
|
||||
Samples = Samples.Select(s => new SampleInfo
|
||||
{
|
||||
Type = SampleType.None,
|
||||
Set = SampleSet.Soft,
|
||||
},
|
||||
Bank = s.Bank,
|
||||
Name = @"slidertick",
|
||||
Volume = s.Volume
|
||||
}).ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
@ -10,11 +9,13 @@ using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using osu.Game.Modes.Replays;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
public class OsuAutoReplay : LegacyReplay
|
||||
public class OsuAutoReplay : Replay
|
||||
{
|
||||
private static readonly Vector2 spinner_centre = new Vector2(256, 192);
|
||||
|
||||
@ -29,17 +30,20 @@ namespace osu.Game.Modes.Osu
|
||||
createAutoReplay();
|
||||
}
|
||||
|
||||
internal class LegacyReplayFrameComparer : IComparer<LegacyReplayFrame>
|
||||
private class ReplayFrameComparer : IComparer<ReplayFrame>
|
||||
{
|
||||
public int Compare(LegacyReplayFrame f1, LegacyReplayFrame f2)
|
||||
public int Compare(ReplayFrame f1, ReplayFrame f2)
|
||||
{
|
||||
if (f1 == null) throw new NullReferenceException($@"{nameof(f1)} cannot be null");
|
||||
if (f2 == null) throw new NullReferenceException($@"{nameof(f2)} cannot be null");
|
||||
|
||||
return f1.Time.CompareTo(f2.Time);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly IComparer<LegacyReplayFrame> replay_frame_comparer = new LegacyReplayFrameComparer();
|
||||
private static readonly IComparer<ReplayFrame> replay_frame_comparer = new ReplayFrameComparer();
|
||||
|
||||
private int findInsertionIndex(LegacyReplayFrame frame)
|
||||
private int findInsertionIndex(ReplayFrame frame)
|
||||
{
|
||||
int index = Frames.BinarySearch(frame, replay_frame_comparer);
|
||||
|
||||
@ -59,7 +63,7 @@ namespace osu.Game.Modes.Osu
|
||||
return index;
|
||||
}
|
||||
|
||||
private void addFrameToReplay(LegacyReplayFrame frame) => Frames.Insert(findInsertionIndex(frame), frame);
|
||||
private void addFrameToReplay(ReplayFrame frame) => Frames.Insert(findInsertionIndex(frame), frame);
|
||||
|
||||
private static Vector2 circlePosition(double t, double radius) => new Vector2((float)(Math.Cos(t) * radius), (float)(Math.Sin(t) * radius));
|
||||
|
||||
@ -74,9 +78,9 @@ namespace osu.Game.Modes.Osu
|
||||
|
||||
EasingTypes preferredEasing = DelayedMovements ? EasingTypes.InOutCubic : EasingTypes.Out;
|
||||
|
||||
addFrameToReplay(new LegacyReplayFrame(-100000, 256, 500, LegacyButtonState.None));
|
||||
addFrameToReplay(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1500, 256, 500, LegacyButtonState.None));
|
||||
addFrameToReplay(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 256, 192, LegacyButtonState.None));
|
||||
addFrameToReplay(new ReplayFrame(-100000, 256, 500, ReplayButtonState.None));
|
||||
addFrameToReplay(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1500, 256, 500, ReplayButtonState.None));
|
||||
addFrameToReplay(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 256, 192, ReplayButtonState.None));
|
||||
|
||||
// We are using ApplyModsToRate and not ApplyModsToTime to counteract the speed up / slow down from HalfTime / DoubleTime so that we remain at a constant framerate of 60 fps.
|
||||
float frameDelay = (float)applyModsToRate(1000.0 / 60.0);
|
||||
@ -106,18 +110,18 @@ namespace osu.Game.Modes.Osu
|
||||
//Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
|
||||
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, ReplayButtonState.None));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, ReplayButtonState.None));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, ReplayButtonState.None));
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,13 +177,13 @@ namespace osu.Game.Modes.Osu
|
||||
// Do some nice easing for cursor movements
|
||||
if (Frames.Count > 0)
|
||||
{
|
||||
LegacyReplayFrame lastFrame = Frames[Frames.Count - 1];
|
||||
ReplayFrame lastFrame = Frames[Frames.Count - 1];
|
||||
|
||||
// Wait until Auto could "see and react" to the next note.
|
||||
double waitTime = h.StartTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime);
|
||||
if (waitTime > lastFrame.Time)
|
||||
{
|
||||
lastFrame = new LegacyReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState);
|
||||
lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState);
|
||||
addFrameToReplay(lastFrame);
|
||||
}
|
||||
|
||||
@ -196,7 +200,7 @@ namespace osu.Game.Modes.Osu
|
||||
for (double time = lastFrame.Time + frameDelay; time < h.StartTime; time += frameDelay)
|
||||
{
|
||||
Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPosition, lastFrame.Time, h.StartTime, easing);
|
||||
addFrameToReplay(new LegacyReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState));
|
||||
addFrameToReplay(new ReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState));
|
||||
}
|
||||
|
||||
buttonIndex = 0;
|
||||
@ -207,12 +211,12 @@ namespace osu.Game.Modes.Osu
|
||||
}
|
||||
}
|
||||
|
||||
LegacyButtonState button = buttonIndex % 2 == 0 ? LegacyButtonState.Left1 : LegacyButtonState.Right1;
|
||||
ReplayButtonState button = buttonIndex % 2 == 0 ? ReplayButtonState.Left1 : ReplayButtonState.Right1;
|
||||
|
||||
double hEndTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
|
||||
|
||||
LegacyReplayFrame newFrame = new LegacyReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button);
|
||||
LegacyReplayFrame endFrame = new LegacyReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, LegacyButtonState.None);
|
||||
ReplayFrame newFrame = new ReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button);
|
||||
ReplayFrame endFrame = new ReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, ReplayButtonState.None);
|
||||
|
||||
// Decrement because we want the previous frame, not the next one
|
||||
int index = findInsertionIndex(newFrame) - 1;
|
||||
@ -220,19 +224,19 @@ namespace osu.Game.Modes.Osu
|
||||
// Do we have a previous frame? No need to check for < replay.Count since we decremented!
|
||||
if (index >= 0)
|
||||
{
|
||||
LegacyReplayFrame previousFrame = Frames[index];
|
||||
ReplayFrame previousFrame = Frames[index];
|
||||
var previousButton = previousFrame.ButtonState;
|
||||
|
||||
// If a button is already held, then we simply alternate
|
||||
if (previousButton != LegacyButtonState.None)
|
||||
if (previousButton != ReplayButtonState.None)
|
||||
{
|
||||
Debug.Assert(previousButton != (LegacyButtonState.Left1 | LegacyButtonState.Right1));
|
||||
Debug.Assert(previousButton != (ReplayButtonState.Left1 | ReplayButtonState.Right1));
|
||||
|
||||
// Force alternation if we have the same button. Otherwise we can just keep the naturally to us assigned button.
|
||||
if (previousButton == button)
|
||||
{
|
||||
button = (LegacyButtonState.Left1 | LegacyButtonState.Right1) & ~button;
|
||||
newFrame.SetButtonStates(button);
|
||||
button = (ReplayButtonState.Left1 | ReplayButtonState.Right1) & ~button;
|
||||
newFrame.ButtonState = button;
|
||||
}
|
||||
|
||||
// We always follow the most recent slider / spinner, so remove any other frames that occur while it exists.
|
||||
@ -246,7 +250,7 @@ namespace osu.Game.Modes.Osu
|
||||
{
|
||||
// Don't affect frames which stop pressing a button!
|
||||
if (j < Frames.Count - 1 || Frames[j].ButtonState == previousButton)
|
||||
Frames[j].SetButtonStates(button);
|
||||
Frames[j].ButtonState = button;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -270,13 +274,13 @@ namespace osu.Game.Modes.Osu
|
||||
t = applyModsToTime(j - h.StartTime) * spinnerDirection;
|
||||
|
||||
Vector2 pos = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
|
||||
addFrameToReplay(new LegacyReplayFrame((int)j, pos.X, pos.Y, button));
|
||||
addFrameToReplay(new ReplayFrame((int)j, pos.X, pos.Y, button));
|
||||
}
|
||||
|
||||
t = applyModsToTime(s.EndTime - h.StartTime) * spinnerDirection;
|
||||
Vector2 endPosition = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
|
||||
|
||||
addFrameToReplay(new LegacyReplayFrame(s.EndTime, endPosition.X, endPosition.Y, button));
|
||||
addFrameToReplay(new ReplayFrame(s.EndTime, endPosition.X, endPosition.Y, button));
|
||||
|
||||
endFrame.MouseX = endPosition.X;
|
||||
endFrame.MouseY = endPosition.Y;
|
||||
@ -288,10 +292,10 @@ namespace osu.Game.Modes.Osu
|
||||
for (double j = frameDelay; j < s.Duration; j += frameDelay)
|
||||
{
|
||||
Vector2 pos = s.PositionAt(j / s.Duration);
|
||||
addFrameToReplay(new LegacyReplayFrame(h.StartTime + j, pos.X, pos.Y, button));
|
||||
addFrameToReplay(new ReplayFrame(h.StartTime + j, pos.X, pos.Y, button));
|
||||
}
|
||||
|
||||
addFrameToReplay(new LegacyReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button));
|
||||
addFrameToReplay(new ReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button));
|
||||
}
|
||||
|
||||
// We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed!
|
||||
|
@ -12,6 +12,8 @@ using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Modes.Osu.Scoring;
|
||||
using osu.Game.Modes.Scoring;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
|
@ -4,7 +4,7 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("osu.Game.Mode.Osu")]
|
||||
@ -16,8 +16,8 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
@ -27,11 +27,11 @@ using System.Runtime.InteropServices;
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
|
@ -1,7 +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
|
||||
using osu.Game.Modes.Scoring;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Scoring
|
||||
{
|
||||
internal class OsuScore : Score
|
||||
{
|
@ -4,9 +4,10 @@
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Judgements;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using osu.Game.Modes.UI;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
namespace osu.Game.Modes.Osu.Scoring
|
||||
{
|
||||
internal class OsuScoreProcessor : ScoreProcessor<OsuHitObject, OsuJudgement>
|
||||
{
|
||||
@ -27,7 +28,7 @@ namespace osu.Game.Modes.Osu
|
||||
Accuracy.Value = 1;
|
||||
}
|
||||
|
||||
protected override void UpdateCalculations(OsuJudgement judgement)
|
||||
protected override void OnNewJudgement(OsuJudgement judgement)
|
||||
{
|
||||
if (judgement != null)
|
||||
{
|
@ -7,6 +7,8 @@ using osu.Game.Modes.Osu.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Judgements;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Scoring;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
|
@ -21,6 +21,8 @@ namespace osu.Game.Modes.Osu.UI
|
||||
private readonly Container judgementLayer;
|
||||
private readonly ConnectionRenderer<OsuHitObject> connectionLayer;
|
||||
|
||||
public override bool ProvidingUserCursor => true;
|
||||
|
||||
public override Vector2 Size
|
||||
{
|
||||
get
|
||||
|
@ -72,8 +72,8 @@
|
||||
<Compile Include="OsuAutoReplay.cs" />
|
||||
<Compile Include="OsuDifficultyCalculator.cs" />
|
||||
<Compile Include="OsuKeyConversionInputManager.cs" />
|
||||
<Compile Include="OsuScore.cs" />
|
||||
<Compile Include="OsuScoreProcessor.cs" />
|
||||
<Compile Include="Scoring\OsuScore.cs" />
|
||||
<Compile Include="Scoring\OsuScoreProcessor.cs" />
|
||||
<Compile Include="UI\OsuHitRenderer.cs" />
|
||||
<Compile Include="UI\OsuPlayfield.cs" />
|
||||
<Compile Include="OsuRuleset.cs" />
|
||||
|
@ -2,75 +2,160 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using osu.Game.Modes.Taiko.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Audio;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Beatmaps
|
||||
{
|
||||
internal class TaikoBeatmapConverter : IBeatmapConverter<TaikoHitObject>
|
||||
{
|
||||
private const float legacy_velocity_scale = 1.4f;
|
||||
private const float bash_convert_factor = 1.65f;
|
||||
/// <summary>
|
||||
/// osu! is generally slower than taiko, so a factor is added to increase
|
||||
/// speed. This must be used everywhere slider length or beat length is used.
|
||||
/// </summary>
|
||||
private const float legacy_velocity_multiplier = 1.4f;
|
||||
|
||||
/// <summary>
|
||||
/// Because swells are easier in taiko than spinners are in osu!,
|
||||
/// legacy taiko multiplies a factor when converting the number of required hits.
|
||||
/// </summary>
|
||||
private const float swell_hit_multiplier = 1.65f;
|
||||
|
||||
/// <summary>
|
||||
/// Base osu! slider scoring distance.
|
||||
/// </summary>
|
||||
private const float osu_base_scoring_distance = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Drum roll distance that results in a duration of 1 speed-adjusted beat length.
|
||||
/// </summary>
|
||||
private const float taiko_base_distance = 100;
|
||||
|
||||
public Beatmap<TaikoHitObject> Convert(Beatmap original)
|
||||
{
|
||||
if (original is LegacyBeatmap)
|
||||
original.TimingInfo.ControlPoints.ForEach(c => c.VelocityAdjustment /= legacy_velocity_scale);
|
||||
BeatmapInfo info = original.BeatmapInfo.DeepClone<BeatmapInfo>();
|
||||
info.Difficulty.SliderMultiplier *= legacy_velocity_multiplier;
|
||||
|
||||
return new Beatmap<TaikoHitObject>(original)
|
||||
{
|
||||
HitObjects = convertHitObjects(original.HitObjects)
|
||||
BeatmapInfo = info,
|
||||
HitObjects = original.HitObjects.SelectMany(h => convertHitObject(h, original)).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
private List<TaikoHitObject> convertHitObjects(List<HitObject> hitObjects)
|
||||
{
|
||||
return hitObjects.Select(convertHitObject).ToList();
|
||||
}
|
||||
|
||||
private TaikoHitObject convertHitObject(HitObject original)
|
||||
private IEnumerable<TaikoHitObject> convertHitObject(HitObject obj, Beatmap beatmap)
|
||||
{
|
||||
// Check if this HitObject is already a TaikoHitObject, and return it if so
|
||||
TaikoHitObject originalTaiko = original as TaikoHitObject;
|
||||
var originalTaiko = obj as TaikoHitObject;
|
||||
if (originalTaiko != null)
|
||||
return originalTaiko;
|
||||
yield return originalTaiko;
|
||||
|
||||
IHasDistance distanceData = original as IHasDistance;
|
||||
IHasRepeats repeatsData = original as IHasRepeats;
|
||||
IHasEndTime endTimeData = original as IHasEndTime;
|
||||
var distanceData = obj as IHasDistance;
|
||||
var repeatsData = obj as IHasRepeats;
|
||||
var endTimeData = obj as IHasEndTime;
|
||||
|
||||
// Old osu! used hit sounding to determine various hit type information
|
||||
List<SampleInfo> samples = obj.Samples;
|
||||
|
||||
bool strong = samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
||||
|
||||
if (distanceData != null)
|
||||
{
|
||||
return new DrumRoll
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
int repeats = repeatsData?.RepeatCount ?? 1;
|
||||
|
||||
Distance = distanceData.Distance * (repeatsData?.RepeatCount ?? 1)
|
||||
double speedAdjustment = beatmap.TimingInfo.SpeedMultiplierAt(obj.StartTime);
|
||||
double speedAdjustedBeatLength = beatmap.TimingInfo.BeatLengthAt(obj.StartTime) * speedAdjustment;
|
||||
|
||||
// The true distance, accounting for any repeats. This ends up being the drum roll distance later
|
||||
double distance = distanceData.Distance * repeats * legacy_velocity_multiplier;
|
||||
|
||||
// The velocity of the taiko hit object - calculated as the velocity of a drum roll
|
||||
double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.Difficulty.SliderMultiplier * legacy_velocity_multiplier / speedAdjustedBeatLength;
|
||||
// The duration of the taiko hit object
|
||||
double taikoDuration = distance / taikoVelocity;
|
||||
|
||||
// For some reason, old osu! always uses speedAdjustment to determine the taiko velocity, but
|
||||
// only uses it to determine osu! velocity if beatmap version < 8. Let's account for that here.
|
||||
if (beatmap.BeatmapInfo.BeatmapVersion >= 8)
|
||||
speedAdjustedBeatLength /= speedAdjustment;
|
||||
|
||||
// The velocity of the osu! hit object - calculated as the velocity of a slider
|
||||
double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.Difficulty.SliderMultiplier * legacy_velocity_multiplier / speedAdjustedBeatLength;
|
||||
// The duration of the osu! hit object
|
||||
double osuDuration = distance / osuVelocity;
|
||||
|
||||
// If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat
|
||||
double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.Difficulty.SliderTickRate, taikoDuration / repeats) / 8;
|
||||
|
||||
if (tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength)
|
||||
{
|
||||
for (double j = obj.StartTime; j <= distanceData.EndTime + tickSpacing; j += tickSpacing)
|
||||
{
|
||||
// Todo: This should generate different type of hits (including strongs)
|
||||
// depending on hitobject sound additions (not implemented fully yet)
|
||||
yield return new CentreHit
|
||||
{
|
||||
StartTime = j,
|
||||
Samples = obj.Samples,
|
||||
IsStrong = strong,
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new DrumRoll
|
||||
{
|
||||
StartTime = obj.StartTime,
|
||||
Samples = obj.Samples,
|
||||
IsStrong = strong,
|
||||
Duration = taikoDuration,
|
||||
TickRate = beatmap.BeatmapInfo.Difficulty.SliderTickRate == 3 ? 3 : 4,
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (endTimeData != null)
|
||||
{
|
||||
double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier;
|
||||
|
||||
yield return new Swell
|
||||
{
|
||||
StartTime = obj.StartTime,
|
||||
Samples = obj.Samples,
|
||||
IsStrong = strong,
|
||||
Duration = endTimeData.Duration,
|
||||
RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier),
|
||||
};
|
||||
}
|
||||
|
||||
if (endTimeData != null)
|
||||
else
|
||||
{
|
||||
// We compute the end time manually to add in the Bash convert factor
|
||||
return new Bash
|
||||
bool isRim = samples.Any(s => s.Name == SampleInfo.HIT_CLAP || s.Name == SampleInfo.HIT_WHISTLE);
|
||||
|
||||
if (isRim)
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
|
||||
EndTime = original.StartTime + endTimeData.Duration * bash_convert_factor
|
||||
};
|
||||
yield return new RimHit
|
||||
{
|
||||
StartTime = obj.StartTime,
|
||||
Samples = obj.Samples,
|
||||
IsStrong = strong,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new CentreHit
|
||||
{
|
||||
StartTime = obj.StartTime,
|
||||
Samples = obj.Samples,
|
||||
IsStrong = strong,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return new Hit
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Sample = original.Sample,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,14 @@ namespace osu.Game.Modes.Taiko.Judgements
|
||||
/// <summary>
|
||||
/// Drum roll ticks don't display judgement text.
|
||||
/// </summary>
|
||||
public override string ScoreString => string.Empty;
|
||||
public override string ResultString => string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Drum roll ticks don't display judgement text.
|
||||
/// </summary>
|
||||
public override string MaxScoreString => string.Empty;
|
||||
public override string MaxResultString => string.Empty;
|
||||
|
||||
public override bool AffectsCombo => false;
|
||||
|
||||
protected override int NumericResultForScore(TaikoHitResult result)
|
||||
{
|
||||
|
@ -3,56 +3,57 @@
|
||||
|
||||
using osu.Game.Modes.Judgements;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Judgements
|
||||
{
|
||||
public class TaikoJudgement : Judgement
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum score value.
|
||||
/// The maximum result.
|
||||
/// </summary>
|
||||
public const TaikoHitResult MAX_HIT_RESULT = TaikoHitResult.Great;
|
||||
|
||||
/// <summary>
|
||||
/// The score value.
|
||||
/// The result.
|
||||
/// </summary>
|
||||
public TaikoHitResult TaikoResult;
|
||||
|
||||
/// <summary>
|
||||
/// The score value for the combo portion of the score.
|
||||
/// The result value for the combo portion of the score.
|
||||
/// </summary>
|
||||
public int ScoreValue => NumericResultForScore(TaikoResult);
|
||||
|
||||
/// <summary>
|
||||
/// The score value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int AccuracyScoreValue => NumericResultForAccuracy(TaikoResult);
|
||||
public int ResultValueForScore => Result == HitResult.Miss ? 0 : NumericResultForScore(TaikoResult);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum score value for the combo portion of the score.
|
||||
/// The result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int MaxScoreValue => NumericResultForScore(MAX_HIT_RESULT);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum score value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int MaxAccuracyScoreValue => NumericResultForAccuracy(MAX_HIT_RESULT);
|
||||
|
||||
public override string ScoreString => TaikoResult.GetDescription();
|
||||
|
||||
public override string MaxScoreString => MAX_HIT_RESULT.GetDescription();
|
||||
public int ResultValueForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(TaikoResult);
|
||||
|
||||
/// <summary>
|
||||
/// Whether this Judgement has a secondary hit in the case of finishers.
|
||||
/// The maximum result value for the combo portion of the score.
|
||||
/// </summary>
|
||||
public bool SecondHit;
|
||||
public int MaxResultValueForScore => NumericResultForScore(MAX_HIT_RESULT);
|
||||
|
||||
/// <summary>
|
||||
/// Computes the numeric score value for the combo portion of the score.
|
||||
/// The maximum result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int MaxResultValueForAccuracy => NumericResultForAccuracy(MAX_HIT_RESULT);
|
||||
|
||||
public override string ResultString => TaikoResult.GetDescription();
|
||||
|
||||
public override string MaxResultString => MAX_HIT_RESULT.GetDescription();
|
||||
|
||||
/// <summary>
|
||||
/// Whether this Judgement has a secondary hit in the case of strong hits.
|
||||
/// </summary>
|
||||
public virtual bool SecondHit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Computes the numeric result value for the combo portion of the score.
|
||||
/// For the accuracy portion of the score (including accuracy percentage), see <see cref="NumericResultForAccuracy(TaikoHitResult)"/>.
|
||||
/// </summary>
|
||||
/// <param name="result">The result to compute the score value for.</param>
|
||||
/// <returns>The numeric score value.</returns>
|
||||
/// <param name="result">The result to compute the value for.</param>
|
||||
/// <returns>The numeric result value.</returns>
|
||||
protected virtual int NumericResultForScore(TaikoHitResult result)
|
||||
{
|
||||
switch (result)
|
||||
@ -67,11 +68,11 @@ namespace osu.Game.Modes.Taiko.Judgements
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the numeric score value for the accuracy portion of the score.
|
||||
/// Computes the numeric result value for the accuracy portion of the score.
|
||||
/// For the combo portion of the score, see <see cref="NumericResultForScore(TaikoHitResult)"/>.
|
||||
/// </summary>
|
||||
/// <param name="result">The result to compute the score value for.</param>
|
||||
/// <returns>The numeric score value.</returns>
|
||||
/// <param name="result">The result to compute the value for.</param>
|
||||
/// <returns>The numeric result value.</returns>
|
||||
protected virtual int NumericResultForAccuracy(TaikoHitResult result)
|
||||
{
|
||||
switch (result)
|
||||
|
25
osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs
Normal file
25
osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs
Normal file
@ -0,0 +1,25 @@
|
||||
// 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.Judgements;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Judgements
|
||||
{
|
||||
public class TaikoStrongHitJudgement : TaikoJudgement, IPartialJudgement
|
||||
{
|
||||
public bool Changed { get; set; }
|
||||
|
||||
public override bool SecondHit
|
||||
{
|
||||
get { return base.SecondHit; }
|
||||
set
|
||||
{
|
||||
if (base.SecondHit == value)
|
||||
return;
|
||||
base.SecondHit = value;
|
||||
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,12 @@
|
||||
// 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 osu.Game.Modes.Mods;
|
||||
using osu.Game.Modes.Scoring;
|
||||
using osu.Game.Modes.Taiko.Objects;
|
||||
using osu.Game.Modes.Taiko.Replays;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Mods
|
||||
{
|
||||
@ -61,4 +66,13 @@ namespace osu.Game.Modes.Taiko.Mods
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class TaikoModAutoplay : ModAutoplay<TaikoHitObject>
|
||||
{
|
||||
protected override Score CreateReplayScore(Beatmap<TaikoHitObject> beatmap) => new Score
|
||||
{
|
||||
User = new User { Username = "mekkadosu!" },
|
||||
Replay = new TaikoAutoReplay(beatmap)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +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.Beatmaps.Samples
|
||||
namespace osu.Game.Modes.Taiko.Objects
|
||||
{
|
||||
public class HitSampleInfo : SampleInfo
|
||||
public class BarLine : TaikoHitObject
|
||||
{
|
||||
public SampleType Type { get; set; }
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// 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.Timing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects
|
||||
{
|
||||
public class Bash : TaikoHitObject, IHasEndTime
|
||||
{
|
||||
public double EndTime { get; set; }
|
||||
|
||||
public double Duration => EndTime - StartTime;
|
||||
|
||||
/// <summary>
|
||||
/// The number of hits required to complete the bash successfully.
|
||||
/// </summary>
|
||||
public int RequiredHits { get; protected set; }
|
||||
|
||||
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaults(timing, difficulty);
|
||||
|
||||
double spinnerRotationRatio = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
|
||||
RequiredHits = (int)Math.Max(1, Duration / 1000f * spinnerRotationRatio);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +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.Beatmaps.Samples
|
||||
namespace osu.Game.Modes.Taiko.Objects
|
||||
{
|
||||
public class SampleInfo
|
||||
public class CentreHit : Hit
|
||||
{
|
||||
public SampleBank Bank;
|
||||
public SampleSet Set;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
// 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.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.Judgements;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||
{
|
||||
public abstract class DrawableTaikoHitObject : DrawableHitObject<TaikoHitObject, TaikoJudgement>
|
||||
{
|
||||
protected DrawableTaikoHitObject(TaikoHitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativePositionAxes = Axes.X;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
LifetimeStart = HitObject.StartTime - HitObject.PreEmpt * 2;
|
||||
LifetimeEnd = HitObject.StartTime + HitObject.PreEmpt;
|
||||
|
||||
base.LoadComplete();
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the scroll position of the DrawableHitObject relative to the offset between
|
||||
/// a time value and the HitObject's StartTime.
|
||||
/// </summary>
|
||||
/// <param name="time"></param>
|
||||
protected virtual void UpdateScrollPosition(double time)
|
||||
{
|
||||
MoveToX((float)((HitObject.StartTime - time) / HitObject.PreEmpt));
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
UpdateScrollPosition(Time.Current);
|
||||
}
|
||||
}
|
||||
}
|
80
osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLine.cs
Normal file
80
osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLine.cs
Normal file
@ -0,0 +1,80 @@
|
||||
// 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;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// A line that scrolls alongside hit objects in the playfield and visualises control points.
|
||||
/// </summary>
|
||||
public class DrawableBarLine : Container
|
||||
{
|
||||
/// <summary>
|
||||
/// The width of the line tracker.
|
||||
/// </summary>
|
||||
private const float tracker_width = 2f;
|
||||
|
||||
/// <summary>
|
||||
/// Fade out time calibrated to a pre-empt of 1000ms.
|
||||
/// </summary>
|
||||
private const float base_fadeout_time = 100f;
|
||||
|
||||
/// <summary>
|
||||
/// The visual line tracker.
|
||||
/// </summary>
|
||||
protected Box Tracker;
|
||||
|
||||
/// <summary>
|
||||
/// The bar line.
|
||||
/// </summary>
|
||||
protected readonly BarLine BarLine;
|
||||
|
||||
public DrawableBarLine(BarLine barLine)
|
||||
{
|
||||
BarLine = barLine;
|
||||
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativePositionAxes = Axes.X;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
|
||||
Width = tracker_width;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
Tracker = new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
EdgeSmoothness = new Vector2(0.5f, 0),
|
||||
Alpha = 0.75f
|
||||
}
|
||||
};
|
||||
|
||||
LifetimeStart = BarLine.StartTime - BarLine.ScrollTime * 2;
|
||||
LifetimeEnd = BarLine.StartTime + BarLine.ScrollTime;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Delay(BarLine.StartTime - Time.Current);
|
||||
FadeOut(base_fadeout_time * BarLine.ScrollTime / 1000);
|
||||
}
|
||||
|
||||
private void updateScrollPosition(double time) => MoveToX((float)((BarLine.StartTime - time) / BarLine.ScrollTime));
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
updateScrollPosition(Time.Current);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
// 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;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public class DrawableBarLineMajor : DrawableBarLine
|
||||
{
|
||||
/// <summary>
|
||||
/// The vertical offset of the triangles from the line tracker.
|
||||
/// </summary>
|
||||
private const float triangle_offfset = 10f;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the triangles.
|
||||
/// </summary>
|
||||
private const float triangle_size = 20f;
|
||||
|
||||
public DrawableBarLineMajor(BarLine barLine)
|
||||
: base(barLine)
|
||||
{
|
||||
Add(new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
new EquilateralTriangle
|
||||
{
|
||||
Name = "Top",
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Position = new Vector2(0, -triangle_offfset),
|
||||
Size = new Vector2(-triangle_size),
|
||||
EdgeSmoothness = new Vector2(1),
|
||||
},
|
||||
new EquilateralTriangle
|
||||
{
|
||||
Name = "Bottom",
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Position = new Vector2(0, triangle_offfset),
|
||||
Size = new Vector2(triangle_size),
|
||||
EdgeSmoothness = new Vector2(1),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Tracker.Alpha = 1f;
|
||||
}
|
||||
}
|
||||
}
|
27
osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHit.cs
Normal file
27
osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHit.cs
Normal file
@ -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.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public class DrawableCentreHit : DrawableHit
|
||||
{
|
||||
protected override Key[] HitKeys { get; } = { Key.F, Key.J };
|
||||
|
||||
public DrawableCentreHit(Hit hit)
|
||||
: base(hit)
|
||||
{
|
||||
MainPiece.Add(new CentreHitSymbolPiece());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
MainPiece.AccentColour = colours.PinkDarker;
|
||||
}
|
||||
}
|
||||
}
|
@ -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.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public class DrawableCentreHitStrong : DrawableHitStrong
|
||||
{
|
||||
protected override Key[] HitKeys { get; } = { Key.F, Key.J };
|
||||
|
||||
public DrawableCentreHitStrong(Hit hit)
|
||||
: base(hit)
|
||||
{
|
||||
MainPiece.Add(new CentreHitSymbolPiece());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
MainPiece.AccentColour = colours.PinkDarker;
|
||||
}
|
||||
}
|
||||
}
|
109
osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRoll.cs
Normal file
109
osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRoll.cs
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.Judgements;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public class DrawableDrumRoll : DrawableTaikoHitObject<DrumRoll>
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of rolling hits required to reach the dark/final accent colour.
|
||||
/// </summary>
|
||||
private const int rolling_hits_for_dark_accent = 5;
|
||||
|
||||
private Color4 accentDarkColour;
|
||||
|
||||
/// <summary>
|
||||
/// Rolling number of tick hits. This increases for hits and decreases for misses.
|
||||
/// </summary>
|
||||
private int rollingHits;
|
||||
|
||||
public DrawableDrumRoll(DrumRoll drumRoll)
|
||||
: base(drumRoll)
|
||||
{
|
||||
foreach (var tick in drumRoll.Ticks)
|
||||
{
|
||||
var newTick = new DrawableDrumRollTick(tick)
|
||||
{
|
||||
X = (float)((tick.StartTime - HitObject.StartTime) / HitObject.Duration)
|
||||
};
|
||||
|
||||
newTick.OnJudgement += onTickJudgement;
|
||||
|
||||
AddNested(newTick);
|
||||
MainPiece.Add(newTick);
|
||||
}
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong };
|
||||
|
||||
protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(HitObject.IsStrong)
|
||||
{
|
||||
Length = (float)(HitObject.Duration / HitObject.ScrollTime),
|
||||
PlayfieldLengthReference = () => Parent.DrawSize.X
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
MainPiece.AccentColour = AccentColour = colours.YellowDark;
|
||||
accentDarkColour = colours.YellowDarker;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
// This is naive, however it's based on the reasoning that the hit target
|
||||
// is further than mid point of the play field, so the time taken to scroll in should always
|
||||
// be greater than the time taken to scroll out to the left of the screen.
|
||||
// Thus, using PreEmpt here is enough for the drum roll to completely scroll out.
|
||||
LifetimeEnd = HitObject.EndTime + HitObject.ScrollTime;
|
||||
}
|
||||
|
||||
private void onTickJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> obj)
|
||||
{
|
||||
if (obj.Judgement.Result == HitResult.Hit)
|
||||
rollingHits++;
|
||||
else
|
||||
rollingHits--;
|
||||
|
||||
rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_dark_accent);
|
||||
|
||||
Color4 newAccent = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_dark_accent, AccentColour, accentDarkColour, 0, 1);
|
||||
MainPiece.FadeAccent(newAccent, 100);
|
||||
}
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (userTriggered)
|
||||
return;
|
||||
|
||||
if (Judgement.TimeOffset < 0)
|
||||
return;
|
||||
|
||||
int countHit = NestedHitObjects.Count(o => o.Judgement.Result == HitResult.Hit);
|
||||
|
||||
if (countHit > HitObject.RequiredGoodHits)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = countHit >= HitObject.RequiredGreatHits ? TaikoHitResult.Great : TaikoHitResult.Good;
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -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 System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.Judgements;
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public class DrawableDrumRollTick : DrawableTaikoHitObject<DrumRollTick>
|
||||
{
|
||||
public DrawableDrumRollTick(DrumRollTick tick)
|
||||
: base(tick)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TaikoPiece CreateMainPiece() => new TickPiece
|
||||
{
|
||||
Filled = HitObject.FirstTick
|
||||
};
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoDrumRollTickJudgement { SecondHit = HitObject.IsStrong };
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset > HitObject.HitWindow)
|
||||
Judgement.Result = HitResult.Miss;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.Abs(Judgement.TimeOffset) < HitObject.HitWindow)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = TaikoHitResult.Great;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
Content.ScaleTo(0, 100, EasingTypes.OutQuint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateScrollPosition(double time)
|
||||
{
|
||||
// Ticks don't move
|
||||
}
|
||||
|
||||
protected override bool HandleKeyPress(Key key)
|
||||
{
|
||||
return Judgement.Result == HitResult.None && UpdateJudgement(true);
|
||||
}
|
||||
}
|
||||
}
|
109
osu.Game.Modes.Taiko/Objects/Drawables/DrawableHit.cs
Normal file
109
osu.Game.Modes.Taiko/Objects/Drawables/DrawableHit.cs
Normal file
@ -0,0 +1,109 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.Judgements;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableHit : DrawableTaikoHitObject<Hit>
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of keys which can result in hits for this HitObject.
|
||||
/// </summary>
|
||||
protected abstract Key[] HitKeys { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the last key pressed is a valid hit key.
|
||||
/// </summary>
|
||||
private bool validKeyPressed;
|
||||
|
||||
protected DrawableHit(Hit hit)
|
||||
: base(hit)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset > HitObject.HitWindowGood)
|
||||
Judgement.Result = HitResult.Miss;
|
||||
return;
|
||||
}
|
||||
|
||||
double hitOffset = Math.Abs(Judgement.TimeOffset);
|
||||
|
||||
if (hitOffset > HitObject.HitWindowMiss)
|
||||
return;
|
||||
|
||||
if (!validKeyPressed)
|
||||
Judgement.Result = HitResult.Miss;
|
||||
else if (hitOffset < HitObject.HitWindowGood)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = hitOffset < HitObject.HitWindowGreat ? TaikoHitResult.Great : TaikoHitResult.Good;
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
|
||||
protected override bool HandleKeyPress(Key key)
|
||||
{
|
||||
if (Judgement.Result != HitResult.None)
|
||||
return false;
|
||||
|
||||
validKeyPressed = HitKeys.Contains(key);
|
||||
|
||||
return UpdateJudgement(true);
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
Delay(HitObject.StartTime - Time.Current + Judgement.TimeOffset, true);
|
||||
|
||||
var circlePiece = MainPiece as CirclePiece;
|
||||
|
||||
circlePiece?.FlashBox.Flush();
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case ArmedState.Idle:
|
||||
Delay(HitObject.HitWindowMiss);
|
||||
break;
|
||||
case ArmedState.Miss:
|
||||
FadeOut(100);
|
||||
break;
|
||||
case ArmedState.Hit:
|
||||
FadeOut(600);
|
||||
|
||||
var flash = circlePiece?.FlashBox;
|
||||
if (flash != null)
|
||||
{
|
||||
flash.FadeTo(0.9f);
|
||||
flash.FadeOut(300);
|
||||
}
|
||||
|
||||
|
||||
FadeOut(800);
|
||||
|
||||
const float gravity_time = 300;
|
||||
const float gravity_travel_height = 200;
|
||||
|
||||
Content.ScaleTo(0.8f, gravity_time * 2, EasingTypes.OutQuad);
|
||||
|
||||
MoveToY(-gravity_travel_height, gravity_time, EasingTypes.Out);
|
||||
Delay(gravity_time, true);
|
||||
MoveToY(gravity_travel_height * 2, gravity_time * 2, EasingTypes.In);
|
||||
break;
|
||||
}
|
||||
|
||||
Expire();
|
||||
}
|
||||
}
|
||||
}
|
92
osu.Game.Modes.Taiko/Objects/Drawables/DrawableHitStrong.cs
Normal file
92
osu.Game.Modes.Taiko/Objects/Drawables/DrawableHitStrong.cs
Normal file
@ -0,0 +1,92 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.Judgements;
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableHitStrong : DrawableHit
|
||||
{
|
||||
/// <summary>
|
||||
/// The lenience for the second key press.
|
||||
/// This does not adjust by map difficulty in ScoreV2 yet.
|
||||
/// </summary>
|
||||
private const double second_hit_window = 30;
|
||||
|
||||
private double firstHitTime;
|
||||
private bool firstKeyHeld;
|
||||
private Key firstHitKey;
|
||||
|
||||
protected DrawableHitStrong(Hit hit)
|
||||
: base(hit)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TaikoPiece CreateMainPiece() => new CirclePiece(true);
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoStrongHitJudgement();
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (Judgement.Result == HitResult.None)
|
||||
{
|
||||
base.CheckJudgement(userTriggered);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!userTriggered)
|
||||
return;
|
||||
|
||||
// If we get here, we're assured that the key pressed is the correct secondary key
|
||||
|
||||
if (Math.Abs(firstHitTime - Time.Current) < second_hit_window)
|
||||
Judgement.SecondHit = true;
|
||||
}
|
||||
|
||||
protected override bool HandleKeyPress(Key key)
|
||||
{
|
||||
// Check if we've handled the first key
|
||||
if (Judgement.Result == HitResult.None)
|
||||
{
|
||||
// First key hasn't been handled yet, attempt to handle it
|
||||
bool handled = base.HandleKeyPress(key);
|
||||
|
||||
if (handled)
|
||||
{
|
||||
firstHitTime = Time.Current;
|
||||
firstHitKey = key;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
// If we've already hit the second key, don't handle this object any further
|
||||
if (Judgement.SecondHit)
|
||||
return false;
|
||||
|
||||
// Don't handle represses of the first key
|
||||
if (firstHitKey == key)
|
||||
return false;
|
||||
|
||||
// Don't handle invalid hit key presses
|
||||
if (!HitKeys.Contains(key))
|
||||
return false;
|
||||
|
||||
// Assume the intention was to hit the strong hit with both keys only if the first key is still being held down
|
||||
return firstKeyHeld && UpdateJudgement(true);
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
firstKeyHeld = state.Keyboard.Keys.Contains(firstHitKey);
|
||||
|
||||
return base.OnKeyDown(state, args);
|
||||
}
|
||||
}
|
||||
}
|
27
osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHit.cs
Normal file
27
osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHit.cs
Normal file
@ -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.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public class DrawableRimHit : DrawableHit
|
||||
{
|
||||
protected override Key[] HitKeys { get; } = { Key.D, Key.K };
|
||||
|
||||
public DrawableRimHit(Hit hit)
|
||||
: base(hit)
|
||||
{
|
||||
MainPiece.Add(new RimHitSymbolPiece());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
MainPiece.AccentColour = colours.BlueDarker;
|
||||
}
|
||||
}
|
||||
}
|
@ -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.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public class DrawableRimHitStrong : DrawableHitStrong
|
||||
{
|
||||
protected override Key[] HitKeys { get; } = { Key.D, Key.K };
|
||||
|
||||
public DrawableRimHitStrong(Hit hit)
|
||||
: base(hit)
|
||||
{
|
||||
MainPiece.Add(new RimHitSymbolPiece());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
MainPiece.AccentColour = colours.BlueDarker;
|
||||
}
|
||||
}
|
||||
}
|
243
osu.Game.Modes.Taiko/Objects/Drawables/DrawableSwell.cs
Normal file
243
osu.Game.Modes.Taiko/Objects/Drawables/DrawableSwell.cs
Normal file
@ -0,0 +1,243 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.Judgements;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public class DrawableSwell : DrawableTaikoHitObject<Swell>
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoked when the swell has reached the hit target, i.e. when CurrentTime >= StartTime.
|
||||
/// This is only ever invoked once.
|
||||
/// </summary>
|
||||
public event Action OnStart;
|
||||
|
||||
private const float target_ring_thick_border = 1.4f;
|
||||
private const float target_ring_thin_border = 1f;
|
||||
private const float target_ring_scale = 5f;
|
||||
private const float inner_ring_alpha = 0.65f;
|
||||
|
||||
private readonly Container bodyContainer;
|
||||
private readonly CircularContainer targetRing;
|
||||
private readonly CircularContainer expandingRing;
|
||||
|
||||
private readonly CirclePiece circlePiece;
|
||||
|
||||
private readonly Key[] rimKeys = { Key.D, Key.K };
|
||||
private readonly Key[] centreKeys = { Key.F, Key.J };
|
||||
private Key[] lastKeySet;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of times the user has hit this swell.
|
||||
/// </summary>
|
||||
private int userHits;
|
||||
|
||||
private bool hasStarted;
|
||||
private readonly SwellSymbolPiece symbol;
|
||||
|
||||
public DrawableSwell(Swell swell)
|
||||
: base(swell)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
bodyContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
expandingRing = new CircularContainer
|
||||
{
|
||||
Name = "Expanding ring",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Masking = true,
|
||||
Children = new []
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = inner_ring_alpha,
|
||||
}
|
||||
}
|
||||
},
|
||||
targetRing = new CircularContainer
|
||||
{
|
||||
Name = "Target ring (thick border)",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
||||
Masking = true,
|
||||
BorderThickness = target_ring_thick_border,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Name = "Target ring (thin border)",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
BorderThickness = target_ring_thin_border,
|
||||
BorderColour = Color4.White,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
circlePiece = new CirclePiece
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new []
|
||||
{
|
||||
symbol = new SwellSymbolPiece()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
circlePiece.KiaiMode = HitObject.Kiai;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
circlePiece.AccentColour = colours.YellowDark;
|
||||
expandingRing.Colour = colours.YellowLight;
|
||||
targetRing.BorderColour = colours.YellowDark.Opacity(0.25f);
|
||||
}
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (userTriggered)
|
||||
{
|
||||
userHits++;
|
||||
|
||||
var completion = (float)userHits / HitObject.RequiredHits;
|
||||
|
||||
expandingRing.FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50);
|
||||
expandingRing.Delay(50);
|
||||
expandingRing.FadeTo(completion / 8, 2000, EasingTypes.OutQuint);
|
||||
expandingRing.DelayReset();
|
||||
|
||||
symbol.RotateTo((float)(completion * HitObject.Duration / 8), 4000, EasingTypes.OutQuint);
|
||||
|
||||
expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, EasingTypes.OutQuint);
|
||||
|
||||
if (userHits == HitObject.RequiredHits)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = TaikoHitResult.Great;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Judgement.TimeOffset < 0)
|
||||
return;
|
||||
|
||||
//TODO: THIS IS SHIT AND CAN'T EXIST POST-TAIKO WORLD CUP
|
||||
if (userHits > HitObject.RequiredHits / 2)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = TaikoHitResult.Good;
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
const float preempt = 100;
|
||||
|
||||
Delay(HitObject.StartTime - Time.Current - preempt, true);
|
||||
|
||||
targetRing.ScaleTo(target_ring_scale, preempt * 4, EasingTypes.OutQuint);
|
||||
|
||||
Delay(preempt, true);
|
||||
|
||||
Delay(Judgement.TimeOffset + HitObject.Duration, true);
|
||||
|
||||
const float out_transition_time = 300;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
bodyContainer.ScaleTo(1.4f, out_transition_time);
|
||||
break;
|
||||
}
|
||||
|
||||
FadeOut(out_transition_time, EasingTypes.Out);
|
||||
|
||||
Expire();
|
||||
}
|
||||
|
||||
protected override void UpdateScrollPosition(double time)
|
||||
{
|
||||
// Make the swell stop at the hit target
|
||||
double t = Math.Min(HitObject.StartTime, time);
|
||||
|
||||
if (t == HitObject.StartTime && !hasStarted)
|
||||
{
|
||||
OnStart?.Invoke();
|
||||
hasStarted = true;
|
||||
}
|
||||
|
||||
base.UpdateScrollPosition(t);
|
||||
}
|
||||
|
||||
protected override bool HandleKeyPress(Key key)
|
||||
{
|
||||
if (Judgement.Result != HitResult.None)
|
||||
return false;
|
||||
|
||||
// Don't handle keys before the swell starts
|
||||
if (Time.Current < HitObject.StartTime)
|
||||
return false;
|
||||
|
||||
// Find the keyset which this key corresponds to
|
||||
var keySet = rimKeys.Contains(key) ? rimKeys : centreKeys;
|
||||
|
||||
// Ensure alternating keysets
|
||||
if (keySet == lastKeySet)
|
||||
return false;
|
||||
lastKeySet = keySet;
|
||||
|
||||
UpdateJudgement(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Taiko.Judgements;
|
||||
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableTaikoHitObject<TaikoHitType> : DrawableHitObject<TaikoHitObject, TaikoJudgement>
|
||||
where TaikoHitType : TaikoHitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of keys which this hit object will accept. These are the standard Taiko keys for now.
|
||||
/// These should be moved to bindings later.
|
||||
/// </summary>
|
||||
private readonly List<Key> validKeys = new List<Key>(new[] { Key.D, Key.F, Key.J, Key.K });
|
||||
|
||||
public override Vector2 OriginPosition => new Vector2(DrawHeight / 2);
|
||||
|
||||
protected override Container<Drawable> Content => bodyContainer;
|
||||
|
||||
protected readonly TaikoPiece MainPiece;
|
||||
|
||||
private readonly Container bodyContainer;
|
||||
|
||||
public new TaikoHitType HitObject;
|
||||
|
||||
protected DrawableTaikoHitObject(TaikoHitType hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.Custom;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
RelativePositionAxes = Axes.X;
|
||||
|
||||
AddInternal(bodyContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
MainPiece = CreateMainPiece()
|
||||
}
|
||||
});
|
||||
|
||||
MainPiece.KiaiMode = HitObject.Kiai;
|
||||
|
||||
LifetimeStart = HitObject.StartTime - HitObject.ScrollTime * 2;
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
|
||||
|
||||
protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(HitObject.IsStrong);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the scroll position of the DrawableHitObject relative to the offset between
|
||||
/// a time value and the HitObject's StartTime.
|
||||
/// </summary>
|
||||
/// <param name="time"></param>
|
||||
protected virtual void UpdateScrollPosition(double time) => X = (float)((HitObject.StartTime - time) / HitObject.ScrollTime);
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
UpdateScrollPosition(Time.Current);
|
||||
}
|
||||
|
||||
protected virtual bool HandleKeyPress(Key key) => false;
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
// Make sure we don't handle held-down keys
|
||||
if (args.Repeat)
|
||||
return false;
|
||||
|
||||
// Check if we've pressed a valid taiko key
|
||||
if (!validKeys.Contains(args.Key))
|
||||
return false;
|
||||
|
||||
// Handle it!
|
||||
return HandleKeyPress(args.Key);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
// 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;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol used for centre hit pieces.
|
||||
/// </summary>
|
||||
public class CentreHitSymbolPiece : CircularContainer
|
||||
{
|
||||
public CentreHitSymbolPiece()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Size = new Vector2(CirclePiece.SYMBOL_INNER_SIZE);
|
||||
Masking = true;
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
157
osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CirclePiece.cs
Normal file
157
osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CirclePiece.cs
Normal file
@ -0,0 +1,157 @@
|
||||
// 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.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// A circle piece which is used uniformly through osu!taiko to visualise hitobjects.
|
||||
/// <para>
|
||||
/// Note that this can actually be non-circle if the width is changed. See <see cref="ElongatedCirclePiece"/>
|
||||
/// for a usage example.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public class CirclePiece : TaikoPiece
|
||||
{
|
||||
public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f;
|
||||
public const float SYMBOL_BORDER = 8;
|
||||
public const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER;
|
||||
|
||||
/// <summary>
|
||||
/// The amount to scale up the base circle to show it as a "strong" piece.
|
||||
/// </summary>
|
||||
private const float strong_scale = 1.5f;
|
||||
|
||||
/// <summary>
|
||||
/// The colour of the inner circle and outer glows.
|
||||
/// </summary>
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
|
||||
background.Colour = AccentColour;
|
||||
|
||||
resetEdgeEffects();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether Kiai mode effects are enabled for this circle piece.
|
||||
/// </summary>
|
||||
public override bool KiaiMode
|
||||
{
|
||||
get { return base.KiaiMode; }
|
||||
set
|
||||
{
|
||||
base.KiaiMode = value;
|
||||
|
||||
resetEdgeEffects();
|
||||
}
|
||||
}
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
private readonly Container content;
|
||||
|
||||
private readonly Container background;
|
||||
|
||||
public Box FlashBox;
|
||||
|
||||
public CirclePiece(bool isStrong = false)
|
||||
{
|
||||
AddInternal(new Drawable[]
|
||||
{
|
||||
background = new CircularContainer
|
||||
{
|
||||
Name = "Background",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new Triangles
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ColourLight = Color4.White,
|
||||
ColourDark = Color4.White.Darken(0.1f)
|
||||
}
|
||||
}
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Name = "Ring",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BorderThickness = 8,
|
||||
BorderColour = Color4.White,
|
||||
Masking = true,
|
||||
Children = new[]
|
||||
{
|
||||
FlashBox = new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.White,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
},
|
||||
content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Name = "Content",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
});
|
||||
|
||||
if (isStrong)
|
||||
{
|
||||
Size *= strong_scale;
|
||||
|
||||
//default for symbols etc.
|
||||
Content.Scale *= strong_scale;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
//we want to allow for width of content to remain mapped to the area inside us, regardless of the scale applied above.
|
||||
Content.Width = 1 / Content.Scale.X;
|
||||
}
|
||||
|
||||
private void resetEdgeEffects()
|
||||
{
|
||||
background.EdgeEffect = new EdgeEffect
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = AccentColour,
|
||||
Radius = KiaiMode ? 50 : 8
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
// 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.Graphics.Primitives;
|
||||
using osu.Game.Modes.Taiko.UI;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces
|
||||
{
|
||||
public class ElongatedCirclePiece : CirclePiece
|
||||
{
|
||||
/// <summary>
|
||||
/// As we are being used to define the absolute size of hits, we need to be given a relative reference of our containing <see cref="TaikoPlayfield"/>.
|
||||
/// </summary>
|
||||
public Func<float> PlayfieldLengthReference;
|
||||
|
||||
/// <summary>
|
||||
/// The length of this piece as a multiple of the value returned by <see cref="PlayfieldLengthReference"/>
|
||||
/// </summary>
|
||||
public float Length;
|
||||
|
||||
public ElongatedCirclePiece(bool isStrong = false) : base(isStrong)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
var padding = Content.DrawHeight * Content.Width / 2;
|
||||
|
||||
Content.Padding = new MarginPadding
|
||||
{
|
||||
Left = padding,
|
||||
Right = padding,
|
||||
};
|
||||
|
||||
Width = (PlayfieldLengthReference?.Invoke() ?? 0) * Length + DrawHeight;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
// 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;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol used for rim hit pieces.
|
||||
/// </summary>
|
||||
public class RimHitSymbolPiece : CircularContainer
|
||||
{
|
||||
public RimHitSymbolPiece()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Size = new Vector2(CirclePiece.SYMBOL_SIZE);
|
||||
BorderThickness = CirclePiece.SYMBOL_BORDER;
|
||||
BorderColour = Color4.White;
|
||||
Masking = true;
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user