mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 02:46:43 +08:00
Merge branch 'master' into roompanel
This commit is contained in:
commit
14a6129675
23
appveyor.yml
Normal file
23
appveyor.yml
Normal file
@ -0,0 +1,23 @@
|
||||
clone_depth: 1
|
||||
version: '{branch}-{build}'
|
||||
configuration: Debug
|
||||
cache:
|
||||
- C:\ProgramData\chocolatey\bin -> appveyor.yml
|
||||
- C:\ProgramData\chocolatey\lib -> appveyor.yml
|
||||
- inspectcode -> appveyor.yml
|
||||
- packages -> **\packages.config
|
||||
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
|
||||
before_build:
|
||||
- cmd: CodeFileSanity.exe
|
||||
- cmd: nuget restore
|
||||
build:
|
||||
project: osu.sln
|
||||
parallel: true
|
||||
verbosity: minimal
|
||||
after_build:
|
||||
- cmd: inspectcode /o="inspectcodereport.xml" /caches-home="inspectcode" osu.sln
|
||||
- cmd: NVika parsereport "inspectcodereport.xml"
|
@ -1 +1 @@
|
||||
Subproject commit 5dbb4a5134dacb2e98ab8f2af219039a72bd32e6
|
||||
Subproject commit a50dd75b114da963c75e6a5314099d99140035b8
|
@ -1 +1 @@
|
||||
Subproject commit 51f2b9b37f38cd349a3dd728a78f8fffcb3a54f5
|
||||
Subproject commit 39657fc6066ea3a141ac71cabf67ec9ebf24975c
|
@ -1,4 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
-->
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="StagingFolder" value="Staging" />
|
||||
|
@ -1,8 +1,11 @@
|
||||
using Newtonsoft.Json;
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace osu.Desktop.Deploy
|
||||
{
|
||||
internal class GitHubObject
|
||||
public class GitHubObject
|
||||
{
|
||||
[JsonProperty(@"id")]
|
||||
public int Id;
|
||||
|
@ -1,8 +1,11 @@
|
||||
using Newtonsoft.Json;
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace osu.Desktop.Deploy
|
||||
{
|
||||
internal class GitHubRelease
|
||||
public class GitHubRelease
|
||||
{
|
||||
[JsonProperty(@"id")]
|
||||
public int Id;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.GitHubusercontent.com/ppy/osu-framework/master/LICENCE
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -40,7 +40,7 @@ namespace osu.Desktop.Deploy
|
||||
/// <summary>
|
||||
/// How many previous build deltas we want to keep when publishing.
|
||||
/// </summary>
|
||||
const int keep_delta_count = 3;
|
||||
private const int keep_delta_count = 3;
|
||||
|
||||
private static string codeSigningCmd => string.IsNullOrEmpty(codeSigningPassword) ? "" : $"-n \"/a /f {codeSigningCertPath} /p {codeSigningPassword} /t http://timestamp.comodoca.com/authenticode\"";
|
||||
|
||||
@ -172,10 +172,10 @@ namespace osu.Desktop.Deploy
|
||||
}
|
||||
|
||||
//remove excess deltas
|
||||
var deltas = releaseLines.Where(l => l.Filename.Contains("-delta"));
|
||||
if (deltas.Count() > keep_delta_count)
|
||||
var deltas = releaseLines.Where(l => l.Filename.Contains("-delta")).ToArray();
|
||||
if (deltas.Length > keep_delta_count)
|
||||
{
|
||||
foreach (var l in deltas.Take(deltas.Count() - keep_delta_count))
|
||||
foreach (var l in deltas.Take(deltas.Length - keep_delta_count))
|
||||
{
|
||||
write($"- Removing old delta {l.Filename}", ConsoleColor.Yellow);
|
||||
File.Delete(Path.Combine(ReleasesFolder, l.Filename));
|
||||
@ -342,7 +342,10 @@ namespace osu.Desktop.Deploy
|
||||
};
|
||||
|
||||
Process p = Process.Start(psi);
|
||||
if (p == null) return false;
|
||||
|
||||
string output = p.StandardOutput.ReadToEnd();
|
||||
|
||||
if (p.ExitCode == 0) return true;
|
||||
|
||||
write(output);
|
||||
|
@ -1,4 +1,7 @@
|
||||
using System.Reflection;
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
@ -101,6 +101,9 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\osu.licenseheader">
|
||||
<Link>osu.licenseheader</Link>
|
||||
</None>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
|
@ -1,4 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
-->
|
||||
<packages>
|
||||
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net452" />
|
||||
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net452" />
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
@ -23,7 +23,7 @@ namespace osu.Desktop.VisualTests.Platform
|
||||
platform = new SQLitePlatformWin32();
|
||||
else
|
||||
platform = new SQLitePlatformGeneric();
|
||||
return new SQLiteConnection(platform, $@":memory:");
|
||||
return new SQLiteConnection(platform, @":memory:");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
// 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.Game.Screens.Select.Options;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCaseBeatmapOptionsOverlay : TestCase
|
||||
{
|
||||
public override string Description => @"Beatmap options in song select";
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
var overlay = new BeatmapOptionsOverlay();
|
||||
|
||||
Add(overlay);
|
||||
|
||||
AddButton(@"Toggle", overlay.ToggleVisibility);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,18 +8,17 @@ using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseChatDisplay : TestCase
|
||||
internal class TestCaseChatDisplay : TestCase
|
||||
{
|
||||
private ScheduledDelegate messageRequest;
|
||||
|
||||
public override string Name => @"Chat";
|
||||
public override string Description => @"Testing chat api and overlay";
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
Add(new ChatOverlay()
|
||||
Add(new ChatOverlay
|
||||
{
|
||||
State = Visibility.Visible
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
@ -9,12 +8,11 @@ using osu.Game.Overlays.Dialog;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseDialogOverlay : TestCase
|
||||
internal class TestCaseDialogOverlay : TestCase
|
||||
{
|
||||
public override string Name => @"Dialog Overlay";
|
||||
public override string Description => @"Display dialogs";
|
||||
|
||||
DialogOverlay overlay;
|
||||
private DialogOverlay overlay;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
|
86
osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs
Normal file
86
osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs
Normal file
@ -0,0 +1,86 @@
|
||||
// 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.Screens.Testing;
|
||||
using osu.Game.Screens.Tournament;
|
||||
using osu.Game.Screens.Tournament.Teams;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCaseDrawings : TestCase
|
||||
{
|
||||
public override string Description => "Tournament drawings";
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
Add(new Drawings
|
||||
{
|
||||
TeamList = new TestTeamList(),
|
||||
});
|
||||
}
|
||||
|
||||
private class TestTeamList : ITeamList
|
||||
{
|
||||
public IEnumerable<Team> Teams { get; } = new[]
|
||||
{
|
||||
new Team
|
||||
{
|
||||
FlagName = "GB",
|
||||
FullName = "United Kingdom",
|
||||
Acronym = "UK"
|
||||
},
|
||||
new Team
|
||||
{
|
||||
FlagName = "FR",
|
||||
FullName = "France",
|
||||
Acronym = "FRA"
|
||||
},
|
||||
new Team
|
||||
{
|
||||
FlagName = "CN",
|
||||
FullName = "China",
|
||||
Acronym = "CHN"
|
||||
},
|
||||
new Team
|
||||
{
|
||||
FlagName = "AU",
|
||||
FullName = "Australia",
|
||||
Acronym = "AUS"
|
||||
},
|
||||
new Team
|
||||
{
|
||||
FlagName = "JP",
|
||||
FullName = "Japan",
|
||||
Acronym = "JPN"
|
||||
},
|
||||
new Team
|
||||
{
|
||||
FlagName = "RO",
|
||||
FullName = "Romania",
|
||||
Acronym = "ROM"
|
||||
},
|
||||
new Team
|
||||
{
|
||||
FlagName = "IT",
|
||||
FullName = "Italy",
|
||||
Acronym = "PIZZA"
|
||||
},
|
||||
new Team
|
||||
{
|
||||
FlagName = "VE",
|
||||
FullName = "Venezuela",
|
||||
Acronym = "VNZ"
|
||||
},
|
||||
new Team
|
||||
{
|
||||
FlagName = "US",
|
||||
FullName = "United States of America",
|
||||
Acronym = "USA"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
// 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.Screens.Testing;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Catch.UI;
|
||||
@ -14,14 +14,12 @@ using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Osu.UI;
|
||||
using osu.Game.Modes.Taiko.UI;
|
||||
using OpenTK;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseGamefield : TestCase
|
||||
internal class TestCaseGamefield : TestCase
|
||||
{
|
||||
public override string Name => @"Gamefield";
|
||||
|
||||
public override string Description => @"Showing hitobjects and what not.";
|
||||
|
||||
public override void Reset()
|
||||
@ -33,7 +31,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
int time = 500;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
objects.Add(new HitCircle()
|
||||
objects.Add(new HitCircle
|
||||
{
|
||||
StartTime = time,
|
||||
Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)),
|
||||
@ -57,30 +55,26 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Clock = new FramedClock(),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuHitRenderer
|
||||
new OsuHitRenderer(beatmap)
|
||||
{
|
||||
Beatmap = beatmap,
|
||||
Scale = new Vector2(0.5f),
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft
|
||||
},
|
||||
new TaikoHitRenderer
|
||||
new TaikoHitRenderer(beatmap)
|
||||
{
|
||||
Beatmap = beatmap,
|
||||
Scale = new Vector2(0.5f),
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight
|
||||
},
|
||||
new CatchHitRenderer
|
||||
new CatchHitRenderer(beatmap)
|
||||
{
|
||||
Beatmap = beatmap,
|
||||
Scale = new Vector2(0.5f),
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft
|
||||
},
|
||||
new ManiaHitRenderer
|
||||
new ManiaHitRenderer(beatmap)
|
||||
{
|
||||
Beatmap = beatmap,
|
||||
Scale = new Vector2(0.5f),
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight
|
||||
|
@ -17,25 +17,22 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseHitObjects : TestCase
|
||||
internal class TestCaseHitObjects : TestCase
|
||||
{
|
||||
public override string Name => @"Hit Objects";
|
||||
|
||||
private StopwatchClock rateAdjustClock;
|
||||
private FramedClock framedClock;
|
||||
|
||||
bool auto = false;
|
||||
private bool auto;
|
||||
|
||||
public TestCaseHitObjects()
|
||||
{
|
||||
rateAdjustClock = new StopwatchClock(true);
|
||||
var rateAdjustClock = new StopwatchClock(true);
|
||||
framedClock = new FramedClock(rateAdjustClock);
|
||||
playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; };
|
||||
}
|
||||
|
||||
HitObjectType mode = HitObjectType.Slider;
|
||||
private HitObjectType mode = HitObjectType.Slider;
|
||||
|
||||
BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 };
|
||||
private BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 };
|
||||
private Container playfieldContainer;
|
||||
private Container approachContainer;
|
||||
|
||||
@ -63,7 +60,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
add(new DrawableSlider(new Slider
|
||||
{
|
||||
StartTime = framedClock.CurrentTime + 600,
|
||||
ControlPoints = new List<Vector2>()
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
new Vector2(-200, 0),
|
||||
new Vector2(400, 0),
|
||||
@ -95,7 +92,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
AddButton(@"slider", () => load(HitObjectType.Slider));
|
||||
AddButton(@"spinner", () => load(HitObjectType.Spinner));
|
||||
|
||||
AddToggle(@"auto", (state) => { auto = state; load(mode); });
|
||||
AddToggle(@"auto", state => { auto = state; load(mode); });
|
||||
|
||||
ButtonsContainer.Add(new SpriteText { Text = "Playback Speed" });
|
||||
ButtonsContainer.Add(new BasicSliderBar<double>
|
||||
@ -124,8 +121,9 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
load(mode);
|
||||
}
|
||||
|
||||
int depth;
|
||||
void add(DrawableHitObject h)
|
||||
private int depth;
|
||||
|
||||
private void add(DrawableHitObject h)
|
||||
{
|
||||
h.Anchor = Anchor.Centre;
|
||||
h.Depth = depth++;
|
||||
|
@ -15,10 +15,8 @@ using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseKeyCounter : TestCase
|
||||
internal class TestCaseKeyCounter : TestCase
|
||||
{
|
||||
public override string Name => @"KeyCounter";
|
||||
|
||||
public override string Description => @"Tests key counter";
|
||||
|
||||
public override void Reset()
|
||||
@ -32,10 +30,10 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
IsCounting = true,
|
||||
Children = new KeyCounter[]
|
||||
{
|
||||
new KeyCounterKeyboard(@"Z", Key.Z),
|
||||
new KeyCounterKeyboard(@"X", Key.X),
|
||||
new KeyCounterMouse(@"M1", MouseButton.Left),
|
||||
new KeyCounterMouse(@"M2", MouseButton.Right),
|
||||
new KeyCounterKeyboard(Key.Z),
|
||||
new KeyCounterKeyboard(Key.X),
|
||||
new KeyCounterMouse(MouseButton.Left),
|
||||
new KeyCounterMouse(MouseButton.Right),
|
||||
},
|
||||
};
|
||||
BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 };
|
||||
@ -43,7 +41,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
AddButton("Add Random", () =>
|
||||
{
|
||||
Key key = (Key)((int)Key.A + RNG.Next(26));
|
||||
kc.Add(new KeyCounterKeyboard(key.ToString(), key));
|
||||
kc.Add(new KeyCounterKeyboard(key));
|
||||
});
|
||||
ButtonsContainer.Add(new SpriteText { Text = "FadeTime" });
|
||||
ButtonsContainer.Add(new TestSliderBar<int>
|
||||
|
@ -9,9 +9,8 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseMenuButtonSystem : TestCase
|
||||
internal class TestCaseMenuButtonSystem : TestCase
|
||||
{
|
||||
public override string Name => @"ButtonSystem";
|
||||
public override string Description => @"Main menu button system";
|
||||
|
||||
public override void Reset()
|
||||
|
35
osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs
Normal file
35
osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Game.Modes;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCaseModSelectOverlay : TestCase
|
||||
{
|
||||
public override string Description => @"Tests the mod select overlay";
|
||||
|
||||
private ModSelectOverlay modSelect;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
Add(modSelect = new ModSelectOverlay
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.BottomCentre,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,9 +9,8 @@ using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseMusicController : TestCase
|
||||
internal class TestCaseMusicController : TestCase
|
||||
{
|
||||
public override string Name => @"Music Controller";
|
||||
public override string Description => @"Tests music controller ui.";
|
||||
|
||||
private MusicController mc;
|
||||
@ -31,7 +30,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Anchor = Anchor.Centre
|
||||
};
|
||||
Add(mc);
|
||||
AddToggle(@"Show", (state) => mc.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||
AddToggle(@"Show", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,12 +12,11 @@ using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseNotificationManager : TestCase
|
||||
internal class TestCaseNotificationManager : TestCase
|
||||
{
|
||||
public override string Name => @"Notification Manager";
|
||||
public override string Description => @"I handle notifications";
|
||||
|
||||
NotificationManager manager;
|
||||
private NotificationManager manager;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
@ -31,7 +30,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Origin = Anchor.TopRight,
|
||||
});
|
||||
|
||||
AddToggle(@"show", (state) => manager.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||
AddToggle(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||
|
||||
AddButton(@"simple #1", sendNotification1);
|
||||
AddButton(@"simple #2", sendNotification2);
|
||||
@ -96,7 +95,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
progressingNotifications.Add(n);
|
||||
}
|
||||
|
||||
List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
|
||||
private List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
|
||||
|
||||
private void sendProgress1()
|
||||
{
|
||||
|
@ -6,10 +6,8 @@ using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseOptions : TestCase
|
||||
internal class TestCaseOptions : TestCase
|
||||
{
|
||||
public override string Name => @"Options";
|
||||
|
||||
public override string Description => @"Tests the options overlay";
|
||||
|
||||
private OptionsOverlay options;
|
||||
|
@ -2,15 +2,13 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Overlays.Pause;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCasePauseOverlay : TestCase
|
||||
internal class TestCasePauseOverlay : TestCase
|
||||
{
|
||||
public override string Name => @"PauseOverlay";
|
||||
|
||||
public override string Description => @"Tests the pause overlay";
|
||||
|
||||
private PauseOverlay pauseOverlay;
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Desktop.VisualTests.Platform;
|
||||
using osu.Framework.Screens.Testing;
|
||||
@ -12,13 +11,12 @@ using osu.Game.Screens.Select;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCasePlaySongSelect : TestCase
|
||||
internal class TestCasePlaySongSelect : TestCase
|
||||
{
|
||||
private BeatmapDatabase db, oldDb;
|
||||
private TestStorage storage;
|
||||
private PlaySongSelect songSelect;
|
||||
|
||||
public override string Name => @"Song Select";
|
||||
public override string Description => @"with fake data";
|
||||
|
||||
public override void Reset()
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Screens.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -18,25 +19,30 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCasePlayer : TestCase
|
||||
internal class TestCasePlayer : TestCase
|
||||
{
|
||||
private WorkingBeatmap beatmap;
|
||||
public override string Name => @"Player";
|
||||
protected Player Player;
|
||||
private BeatmapDatabase db;
|
||||
|
||||
|
||||
public override string Description => @"Showing everything to play the game.";
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(BeatmapDatabase db)
|
||||
{
|
||||
var beatmapInfo = db.Query<BeatmapInfo>().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault();
|
||||
if (beatmapInfo != null)
|
||||
beatmap = db.GetWorkingBeatmap(beatmapInfo);
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
WorkingBeatmap beatmap = null;
|
||||
|
||||
var beatmapInfo = db.Query<BeatmapInfo>().FirstOrDefault(b => b.Mode == PlayMode.Osu);
|
||||
if (beatmapInfo != null)
|
||||
beatmap = db.GetWorkingBeatmap(beatmapInfo);
|
||||
|
||||
if (beatmap?.Track == null)
|
||||
{
|
||||
var objects = new List<HitObject>();
|
||||
@ -44,7 +50,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
int time = 1500;
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
objects.Add(new HitCircle()
|
||||
objects.Add(new HitCircle
|
||||
{
|
||||
StartTime = time,
|
||||
Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512,
|
||||
@ -82,17 +88,21 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Colour = Color4.Black,
|
||||
});
|
||||
|
||||
Add(new PlayerLoader(new Player
|
||||
{
|
||||
PreferredPlayMode = PlayMode.Osu,
|
||||
Beatmap = beatmap
|
||||
})
|
||||
Add(new PlayerLoader(Player = CreatePlayer(beatmap))
|
||||
{
|
||||
Beatmap = beatmap
|
||||
});
|
||||
}
|
||||
|
||||
class TestWorkingBeatmap : WorkingBeatmap
|
||||
protected virtual Player CreatePlayer(WorkingBeatmap beatmap)
|
||||
{
|
||||
return new Player
|
||||
{
|
||||
Beatmap = beatmap
|
||||
};
|
||||
}
|
||||
|
||||
private class TestWorkingBeatmap : WorkingBeatmap
|
||||
{
|
||||
public TestWorkingBeatmap(Beatmap beatmap)
|
||||
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
|
||||
|
30
osu.Desktop.VisualTests/Tests/TestCaseReplay.cs
Normal file
30
osu.Desktop.VisualTests/Tests/TestCaseReplay.cs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using osu.Framework.Input.Handlers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
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)
|
||||
{
|
||||
var player = base.CreatePlayer(beatmap);
|
||||
player.ReplayInputHandler = Ruleset.GetRuleset(beatmap.PlayMode).CreateAutoplayScore(beatmap.Beatmap)?.Replay?.GetInputHandler();
|
||||
return player;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +1,19 @@
|
||||
// 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.Screens.Testing;
|
||||
using OpenTK;
|
||||
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.Game.Graphics.UserInterface;
|
||||
using osu.Game.Modes.Catch.UI;
|
||||
using osu.Game.Modes.Mania.UI;
|
||||
using osu.Game.Modes.Osu.UI;
|
||||
using osu.Game.Modes.Taiko.UI;
|
||||
using osu.Game.Modes.UI;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseScoreCounter : TestCase
|
||||
internal class TestCaseScoreCounter : TestCase
|
||||
{
|
||||
public override string Name => @"ScoreCounter";
|
||||
|
||||
public override string Description => @"Tests multiple counters";
|
||||
|
||||
public override void Reset()
|
||||
@ -37,58 +29,26 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
TextSize = 40,
|
||||
Count = 0,
|
||||
Margin = new MarginPadding(20),
|
||||
};
|
||||
Add(score);
|
||||
|
||||
ComboCounter standardCombo = new OsuComboCounter
|
||||
ComboCounter comboCounter = new StandardComboCounter
|
||||
{
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Margin = new MarginPadding(10),
|
||||
Count = 0,
|
||||
TextSize = 40,
|
||||
};
|
||||
Add(standardCombo);
|
||||
Add(comboCounter);
|
||||
|
||||
CatchComboCounter catchCombo = new CatchComboCounter
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Count = 0,
|
||||
TextSize = 40,
|
||||
};
|
||||
Add(catchCombo);
|
||||
|
||||
ComboCounter taikoCombo = new TaikoComboCounter
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(0, -160),
|
||||
Count = 0,
|
||||
TextSize = 40,
|
||||
};
|
||||
Add(taikoCombo);
|
||||
|
||||
ManiaComboCounter maniaCombo = new ManiaComboCounter
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Position = new Vector2(0, -80),
|
||||
Count = 0,
|
||||
TextSize = 40,
|
||||
};
|
||||
Add(maniaCombo);
|
||||
|
||||
|
||||
PercentageCounter accuracyCombo = new PercentageCounter
|
||||
PercentageCounter accuracyCounter = new PercentageCounter
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
Position = new Vector2(-20, 60),
|
||||
};
|
||||
Add(accuracyCombo);
|
||||
Add(accuracyCounter);
|
||||
|
||||
StarCounter stars = new StarCounter
|
||||
{
|
||||
@ -110,50 +70,27 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
|
||||
AddButton(@"Reset all", delegate
|
||||
{
|
||||
score.Count = 0;
|
||||
standardCombo.Count = 0;
|
||||
taikoCombo.Count = 0;
|
||||
maniaCombo.Count = 0;
|
||||
catchCombo.Count = 0;
|
||||
score.Current.Value = 0;
|
||||
comboCounter.Current.Value = 0;
|
||||
numerator = denominator = 0;
|
||||
accuracyCombo.SetFraction(0, 0);
|
||||
accuracyCounter.SetFraction(0, 0);
|
||||
stars.Count = 0;
|
||||
starsLabel.Text = stars.Count.ToString("0.00");
|
||||
});
|
||||
|
||||
AddButton(@"Hit! :D", delegate
|
||||
{
|
||||
score.Count += 300 + (ulong)(300.0 * (standardCombo.Count > 0 ? standardCombo.Count - 1 : 0) / 25.0);
|
||||
standardCombo.Count++;
|
||||
taikoCombo.Count++;
|
||||
maniaCombo.Count++;
|
||||
catchCombo.CatchFruit(new Color4(
|
||||
Math.Max(0.5f, RNG.NextSingle()),
|
||||
Math.Max(0.5f, RNG.NextSingle()),
|
||||
Math.Max(0.5f, RNG.NextSingle()),
|
||||
1)
|
||||
);
|
||||
score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
|
||||
comboCounter.Increment();
|
||||
numerator++; denominator++;
|
||||
accuracyCombo.SetFraction(numerator, denominator);
|
||||
accuracyCounter.SetFraction(numerator, denominator);
|
||||
});
|
||||
|
||||
AddButton(@"miss...", delegate
|
||||
{
|
||||
standardCombo.Roll();
|
||||
taikoCombo.Roll();
|
||||
maniaCombo.Roll();
|
||||
catchCombo.Roll();
|
||||
comboCounter.Current.Value = 0;
|
||||
denominator++;
|
||||
accuracyCombo.SetFraction(numerator, denominator);
|
||||
});
|
||||
|
||||
AddButton(@"mania hold", delegate
|
||||
{
|
||||
if (!maniaHold)
|
||||
maniaCombo.HoldStart();
|
||||
else
|
||||
maniaCombo.HoldEnd();
|
||||
maniaHold = !maniaHold;
|
||||
accuracyCounter.SetFraction(numerator, denominator);
|
||||
});
|
||||
|
||||
AddButton(@"Alter stars", delegate
|
||||
@ -165,11 +102,8 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
AddButton(@"Stop counters", delegate
|
||||
{
|
||||
score.StopRolling();
|
||||
standardCombo.StopRolling();
|
||||
catchCombo.StopRolling();
|
||||
taikoCombo.StopRolling();
|
||||
maniaCombo.StopRolling();
|
||||
accuracyCombo.StopRolling();
|
||||
comboCounter.StopRolling();
|
||||
accuracyCounter.StopRolling();
|
||||
stars.StopAnimation();
|
||||
});
|
||||
}
|
||||
|
@ -12,10 +12,8 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseTextAwesome : TestCase
|
||||
internal class TestCaseTextAwesome : TestCase
|
||||
{
|
||||
public override string Name => @"TextAwesome";
|
||||
|
||||
public override string Description => @"Tests display of icons";
|
||||
|
||||
public override void Reset()
|
||||
@ -24,7 +22,7 @@ namespace osu.Desktop.VisualTests.Tests
|
||||
|
||||
FillFlowContainer flow;
|
||||
|
||||
Add(flow = new FillFlowContainer()
|
||||
Add(flow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.5f),
|
||||
|
@ -7,9 +7,8 @@ using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
class TestCaseTwoLayerButton : TestCase
|
||||
internal class TestCaseTwoLayerButton : TestCase
|
||||
{
|
||||
public override string Name => @"TwoLayerButton";
|
||||
public override string Description => @"Back and skip and what not";
|
||||
|
||||
public override void Reset()
|
||||
|
@ -7,13 +7,13 @@ using osu.Game.Screens.Backgrounds;
|
||||
|
||||
namespace osu.Desktop.VisualTests
|
||||
{
|
||||
class VisualTestGame : OsuGameBase
|
||||
internal class VisualTestGame : OsuGameBase
|
||||
{
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
(new BackgroundScreenDefault() { Depth = 10 }).LoadAsync(this, AddInternal);
|
||||
new BackgroundScreenDefault { Depth = 10 }.LoadAsync(this, AddInternal);
|
||||
|
||||
// Have to construct this here, rather than in the constructor, because
|
||||
// we depend on some dependencies to be loaded within OsuGameBase.load().
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
@ -86,6 +86,10 @@
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1340\lib\net45\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SharpCompress, Version=0.15.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpCompress.0.15.1\lib\net45\SharpCompress.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>$(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
|
||||
@ -179,6 +183,7 @@
|
||||
<Compile Include="Benchmark.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Tests\TestCaseChatDisplay.cs" />
|
||||
<Compile Include="Tests\TestCaseDrawings.cs" />
|
||||
<Compile Include="Tests\TestCaseGamefield.cs" />
|
||||
<Compile Include="Tests\TestCaseMusicController.cs" />
|
||||
<Compile Include="Tests\TestCaseNotificationManager.cs" />
|
||||
@ -186,6 +191,7 @@
|
||||
<Compile Include="Tests\TestCaseHitObjects.cs" />
|
||||
<Compile Include="Tests\TestCaseKeyCounter.cs" />
|
||||
<Compile Include="Tests\TestCaseMenuButtonSystem.cs" />
|
||||
<Compile Include="Tests\TestCaseReplay.cs" />
|
||||
<Compile Include="Tests\TestCaseScoreCounter.cs" />
|
||||
<Compile Include="Tests\TestCaseTextAwesome.cs" />
|
||||
<Compile Include="Tests\TestCasePlaySongSelect.cs" />
|
||||
@ -194,7 +200,9 @@
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup />
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
@ -6,6 +7,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
|
||||
<package id="ppy.OpenTK" version="2.0.50727.1340" targetFramework="net45" />
|
||||
<package id="SharpCompress" version="0.15.1" targetFramework="net45" />
|
||||
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
||||
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
||||
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
|
||||
|
@ -17,16 +17,16 @@ namespace osu.Desktop.Beatmaps.IO
|
||||
{
|
||||
public static void Register() => AddReader<LegacyFilesystemReader>((storage, path) => Directory.Exists(path));
|
||||
|
||||
private string basePath { get; set; }
|
||||
private Beatmap firstMap { get; set; }
|
||||
private string basePath { get; }
|
||||
private Beatmap firstMap { get; }
|
||||
|
||||
public LegacyFilesystemReader(string path)
|
||||
{
|
||||
basePath = path;
|
||||
BeatmapFilenames = Directory.GetFiles(basePath, @"*.osu").Select(f => Path.GetFileName(f)).ToArray();
|
||||
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(f => Path.GetFileName(f)).FirstOrDefault();
|
||||
StoryboardFilename = Directory.GetFiles(basePath, @"*.osb").Select(Path.GetFileName).FirstOrDefault();
|
||||
using (var stream = new StreamReader(GetStream(BeatmapFilenames[0])))
|
||||
{
|
||||
var decoder = BeatmapDecoder.GetDecoder(stream);
|
||||
|
@ -9,16 +9,16 @@ using osu.Framework.Desktop.Platform;
|
||||
using osu.Desktop.Overlays;
|
||||
using System.Reflection;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Game.Screens.Menu;
|
||||
|
||||
namespace osu.Desktop
|
||||
{
|
||||
class OsuGameDesktop : OsuGame
|
||||
internal class OsuGameDesktop : OsuGame
|
||||
{
|
||||
private VersionManager versionManager;
|
||||
|
||||
public override bool IsDeployedBuild => versionManager.IsDeployedBuild;
|
||||
|
||||
public OsuGameDesktop(string[] args = null)
|
||||
: base(args)
|
||||
{
|
||||
@ -44,7 +44,7 @@ namespace osu.Desktop
|
||||
if (desktopWindow != null)
|
||||
{
|
||||
desktopWindow.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
|
||||
desktopWindow.Title = @"osu!lazer";
|
||||
desktopWindow.Title = Name;
|
||||
|
||||
desktopWindow.DragEnter += dragEnter;
|
||||
desktopWindow.DragDrop += dragDrop;
|
||||
@ -54,22 +54,29 @@ namespace osu.Desktop
|
||||
private void dragDrop(DragEventArgs e)
|
||||
{
|
||||
// this method will only be executed if e.Effect in dragEnter gets set to something other that None.
|
||||
var dropData = e.Data.GetData(DataFormats.FileDrop) as object[];
|
||||
var dropData = (object[])e.Data.GetData(DataFormats.FileDrop);
|
||||
var filePaths = dropData.Select(f => f.ToString()).ToArray();
|
||||
ImportBeatmapsAsync(filePaths);
|
||||
|
||||
if (filePaths.All(f => Path.GetExtension(f) == @".osz"))
|
||||
Task.Run(() => BeatmapDatabase.Import(filePaths));
|
||||
else if (filePaths.All(f => Path.GetExtension(f) == @".osr"))
|
||||
Task.Run(() =>
|
||||
{
|
||||
var score = ScoreDatabase.ReadReplayFile(filePaths.First());
|
||||
Schedule(() => LoadScore(score));
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly string[] allowed_extensions = { @".osz", @".osr" };
|
||||
|
||||
private void dragEnter(DragEventArgs e)
|
||||
{
|
||||
// dragDrop will only be executed if e.Effect gets set to something other that None in this method.
|
||||
bool isFile = e.Data.GetDataPresent(DataFormats.FileDrop);
|
||||
if (isFile)
|
||||
{
|
||||
var paths = (e.Data.GetData(DataFormats.FileDrop) as object[]).Select(f => f.ToString()).ToArray();
|
||||
if (paths.Any(p => !p.EndsWith(".osz")))
|
||||
e.Effect = DragDropEffects.None;
|
||||
else
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
var paths = ((object[])e.Data.GetData(DataFormats.FileDrop)).Select(f => f.ToString()).ToArray();
|
||||
e.Effect = allowed_extensions.Any(ext => paths.All(p => p.EndsWith(ext))) ? DragDropEffects.Copy : DragDropEffects.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
@ -11,13 +10,14 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using Squirrel;
|
||||
using System.Reflection;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using System.Net.Http;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game;
|
||||
|
||||
namespace osu.Desktop.Overlays
|
||||
{
|
||||
@ -26,16 +26,12 @@ namespace osu.Desktop.Overlays
|
||||
private UpdateManager updateManager;
|
||||
private NotificationManager notificationManager;
|
||||
|
||||
AssemblyName assembly = Assembly.GetEntryAssembly().GetName();
|
||||
|
||||
public bool IsDeployedBuild => assembly.Version.Major > 0;
|
||||
|
||||
protected override bool HideOnEscape => false;
|
||||
|
||||
public override bool HandleInput => false;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(NotificationManager notification, OsuColour colours, TextureStore textures)
|
||||
private void load(NotificationManager notification, OsuColour colours, TextureStore textures, OsuGameBase game)
|
||||
{
|
||||
notificationManager = notification;
|
||||
|
||||
@ -44,29 +40,18 @@ namespace osu.Desktop.Overlays
|
||||
Origin = Anchor.BottomCentre;
|
||||
Alpha = 0;
|
||||
|
||||
bool isDebug = false;
|
||||
Debug.Assert(isDebug = true);
|
||||
|
||||
string version;
|
||||
if (!IsDeployedBuild)
|
||||
{
|
||||
version = @"local " + (isDebug ? @"debug" : @"release");
|
||||
}
|
||||
else
|
||||
version = $@"{assembly.Version.Major}.{assembly.Version.Minor}.{assembly.Version.Build}";
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Down,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Right,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
@ -75,12 +60,12 @@ namespace osu.Desktop.Overlays
|
||||
new OsuSpriteText
|
||||
{
|
||||
Font = @"Exo2.0-Bold",
|
||||
Text = $@"osu!lazer"
|
||||
Text = game.Name
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Colour = isDebug ? colours.Red : Color4.White,
|
||||
Text = version
|
||||
Colour = game.IsDebug ? colours.Red : Color4.White,
|
||||
Text = game.Version
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -91,7 +76,7 @@ namespace osu.Desktop.Overlays
|
||||
TextSize = 12,
|
||||
Colour = colours.Yellow,
|
||||
Font = @"Venera",
|
||||
Text = $@"Development Build"
|
||||
Text = @"Development Build"
|
||||
},
|
||||
new Sprite
|
||||
{
|
||||
@ -103,7 +88,7 @@ namespace osu.Desktop.Overlays
|
||||
}
|
||||
};
|
||||
|
||||
if (IsDeployedBuild)
|
||||
if (game.IsDeployedBuild)
|
||||
checkForUpdateAsync();
|
||||
}
|
||||
|
||||
@ -159,15 +144,21 @@ namespace osu.Desktop.Overlays
|
||||
|
||||
Schedule(() => notification.State = ProgressNotificationState.Completed);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
if (useDeltaPatching)
|
||||
{
|
||||
Logger.Error(e, @"delta patching failed!");
|
||||
|
||||
//could fail if deltas are unavailable for full update path (https://github.com/Squirrel/Squirrel.Windows/issues/959)
|
||||
//try again without deltas.
|
||||
checkForUpdateAsync(false, notification);
|
||||
scheduleRetry = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error(e, @"update failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpRequestException)
|
||||
@ -196,9 +187,9 @@ namespace osu.Desktop.Overlays
|
||||
{
|
||||
}
|
||||
|
||||
class UpdateProgressNotification : ProgressNotification
|
||||
private class UpdateProgressNotification : ProgressNotification
|
||||
{
|
||||
protected override Notification CreateCompletionNotification() => new ProgressCompletionNotification(this)
|
||||
protected override Notification CreateCompletionNotification() => new ProgressCompletionNotification()
|
||||
{
|
||||
Text = @"Update ready to install. Click to restart!",
|
||||
Activated = () =>
|
||||
@ -221,6 +212,7 @@ namespace osu.Desktop.Overlays
|
||||
new TextAwesome
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Icon = FontAwesome.fa_upload,
|
||||
Colour = Color4.White,
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ namespace osu.Desktop
|
||||
{
|
||||
if (!host.IsPrimaryInstance)
|
||||
{
|
||||
var importer = new BeatmapImporter(host);
|
||||
var importer = new BeatmapIPCChannel(host);
|
||||
// Restore the cwd so relative paths given at the command line work correctly
|
||||
Directory.SetCurrentDirectory(cwd);
|
||||
foreach (var file in args)
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
@ -101,8 +101,8 @@
|
||||
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
|
@ -17,7 +17,8 @@
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="*.exe" target="lib\net45\" exclude="**vshost**"/>
|
||||
<file src="*.dll" target="lib\net45\"/>
|
||||
<file src="*.dll" target="lib\net45\"/>
|
||||
<file src="*.config" target="lib\net45\"/>
|
||||
<file src="x86\*.dll" target="lib\net45\x86\"/>
|
||||
<file src="x64\*.dll" target="lib\net45\x64\"/>
|
||||
</files>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
@ -7,6 +8,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="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
||||
<package id="squirrel.windows" version="1.5.2" targetFramework="net45" />
|
||||
</packages>
|
21
osu.Game.Modes.Catch/Beatmaps/CatchBeatmapConverter.cs
Normal file
21
osu.Game.Modes.Catch/Beatmaps/CatchBeatmapConverter.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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.Catch.Objects;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Catch.Beatmaps
|
||||
{
|
||||
internal class CatchBeatmapConverter : IBeatmapConverter<CatchBaseHit>
|
||||
{
|
||||
public Beatmap<CatchBaseHit> Convert(Beatmap original)
|
||||
{
|
||||
return new Beatmap<CatchBaseHit>(original)
|
||||
{
|
||||
HitObjects = new List<CatchBaseHit>() // Todo: Convert HitObjects
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -2,26 +2,23 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Catch.Beatmaps;
|
||||
using osu.Game.Modes.Catch.Objects;
|
||||
using osu.Game.Modes.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Catch
|
||||
{
|
||||
public class CatchDifficultyCalculator : DifficultyCalculator<CatchBaseHit>
|
||||
{
|
||||
protected override PlayMode PlayMode => PlayMode.Catch;
|
||||
|
||||
public CatchDifficultyCalculator(Beatmap beatmap) : base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HitObjectConverter<CatchBaseHit> Converter => new CatchConverter();
|
||||
|
||||
protected override double CalculateInternal(Dictionary<String, String> categoryDifficulty)
|
||||
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected override IBeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter();
|
||||
}
|
||||
}
|
62
osu.Game.Modes.Catch/CatchMod.cs
Normal file
62
osu.Game.Modes.Catch/CatchMod.cs
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Modes.Catch
|
||||
{
|
||||
public class CatchModNoFail : ModNoFail
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class CatchModEasy : ModEasy
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class CatchModHidden : ModHidden
|
||||
{
|
||||
public override string Description => @"Play with no approach circles and fading notes for a slight score advantage.";
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
}
|
||||
|
||||
public class CatchModHardRock : ModHardRock
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
public override bool Ranked => true;
|
||||
}
|
||||
|
||||
public class CatchModSuddenDeath : ModSuddenDeath
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class CatchModDoubleTime : ModDoubleTime
|
||||
{
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
}
|
||||
|
||||
public class CatchModRelax : ModRelax
|
||||
{
|
||||
public override string Description => @"Use the mouse to control the catcher.";
|
||||
}
|
||||
|
||||
public class CatchModHalfTime : ModHalfTime
|
||||
{
|
||||
public override double ScoreMultiplier => 0.5;
|
||||
}
|
||||
|
||||
public class CatchModNightcore : ModNightcore
|
||||
{
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
}
|
||||
|
||||
public class CatchModFlashlight : ModFlashlight
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
|
||||
public class CatchModPerfect : ModPerfect
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,26 +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 OpenTK.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Catch.UI;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.UI;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Catch
|
||||
{
|
||||
public class CatchRuleset : Ruleset
|
||||
{
|
||||
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
|
||||
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new CatchHitRenderer(beatmap);
|
||||
|
||||
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new CatchHitRenderer { Beatmap = beatmap };
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ModType.DifficultyReduction:
|
||||
return new Mod[]
|
||||
{
|
||||
new CatchModEasy(),
|
||||
new CatchModNoFail(),
|
||||
new CatchModHalfTime(),
|
||||
};
|
||||
|
||||
case ModType.DifficultyIncrease:
|
||||
return new Mod[]
|
||||
{
|
||||
new CatchModHardRock(),
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new CatchModSuddenDeath(),
|
||||
new CatchModPerfect(),
|
||||
},
|
||||
},
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new CatchModDoubleTime(),
|
||||
new CatchModNightcore(),
|
||||
},
|
||||
},
|
||||
new CatchModHidden(),
|
||||
new CatchModFlashlight(),
|
||||
};
|
||||
|
||||
case ModType.Special:
|
||||
return new Mod[]
|
||||
{
|
||||
new CatchModRelax(),
|
||||
null,
|
||||
null,
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ModAutoplay(),
|
||||
new ModCinema(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
default:
|
||||
return new Mod[] { };
|
||||
}
|
||||
}
|
||||
|
||||
protected override PlayMode PlayMode => PlayMode.Catch;
|
||||
|
||||
public override string Description => "osu!catch";
|
||||
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_fruits_o;
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null;
|
||||
public override IEnumerable<KeyCounter> CreateGameplayKeys() => new KeyCounter[]
|
||||
{
|
||||
new KeyCounterKeyboard(Key.ShiftLeft),
|
||||
new KeyCounterMouse(MouseButton.Left),
|
||||
new KeyCounterMouse(MouseButton.Right)
|
||||
};
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount = 0) => null;
|
||||
|
||||
public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser();
|
||||
|
||||
|
@ -8,7 +8,7 @@ using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Modes.Catch.Objects
|
||||
{
|
||||
class CatchConverter : HitObjectConverter<CatchBaseHit>
|
||||
internal class CatchConverter : HitObjectConverter<CatchBaseHit>
|
||||
{
|
||||
public override List<CatchBaseHit> Convert(Beatmap beatmap)
|
||||
{
|
||||
|
@ -10,7 +10,7 @@ using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Catch.Objects.Drawable
|
||||
{
|
||||
class DrawableFruit : Sprite
|
||||
internal class DrawableFruit : Sprite
|
||||
{
|
||||
private CatchBaseHit h;
|
||||
|
||||
|
@ -1,65 +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.Game.Modes.Osu.UI;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Catch.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Similar to Standard, but without the 'x' and has tinted pop-ups. Used in osu!catch.
|
||||
/// </summary>
|
||||
public class CatchComboCounter : OsuComboCounter
|
||||
{
|
||||
protected override bool CanPopOutWhileRolling => true;
|
||||
|
||||
protected virtual double FadeOutDelay => 1000;
|
||||
protected override double FadeOutDuration => 300;
|
||||
|
||||
protected override string FormatCount(ulong count)
|
||||
{
|
||||
return $@"{count:#,0}";
|
||||
}
|
||||
|
||||
private void animateFade()
|
||||
{
|
||||
Show();
|
||||
Delay(FadeOutDelay);
|
||||
FadeOut(FadeOutDuration);
|
||||
DelayReset();
|
||||
}
|
||||
|
||||
protected override void OnCountChange(ulong currentValue, ulong newValue)
|
||||
{
|
||||
if (newValue != 0)
|
||||
animateFade();
|
||||
base.OnCountChange(currentValue, newValue);
|
||||
}
|
||||
|
||||
protected override void OnCountRolling(ulong currentValue, ulong newValue)
|
||||
{
|
||||
if (!IsRolling)
|
||||
{
|
||||
PopOutCount.Colour = DisplayedCountSpriteText.Colour;
|
||||
FadeOut(FadeOutDuration);
|
||||
}
|
||||
base.OnCountRolling(currentValue, newValue);
|
||||
}
|
||||
|
||||
protected override void OnCountIncrement(ulong currentValue, ulong newValue)
|
||||
{
|
||||
animateFade();
|
||||
base.OnCountIncrement(currentValue, newValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increaces counter and tints pop-out before animation.
|
||||
/// </summary>
|
||||
/// <param name="colour">Last grabbed fruit colour.</param>
|
||||
public void CatchFruit(Color4 colour)
|
||||
{
|
||||
PopOutCount.Colour = colour;
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +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
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Catch.Beatmaps;
|
||||
using osu.Game.Modes.Catch.Objects;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.UI;
|
||||
|
||||
@ -10,10 +11,15 @@ namespace osu.Game.Modes.Catch.UI
|
||||
{
|
||||
public class CatchHitRenderer : HitRenderer<CatchBaseHit>
|
||||
{
|
||||
protected override HitObjectConverter<CatchBaseHit> Converter => new CatchConverter();
|
||||
public CatchHitRenderer(Beatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Playfield CreatePlayfield() => new CatchPlayfield();
|
||||
protected override IBeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter();
|
||||
|
||||
protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) => null;// new DrawableFruit(h);
|
||||
protected override Playfield<CatchBaseHit> CreatePlayfield() => new CatchPlayfield();
|
||||
|
||||
protected override DrawableHitObject<CatchBaseHit> GetVisualRepresentation(CatchBaseHit h) => null;// new DrawableFruit(h);
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,13 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Modes.Catch.Objects;
|
||||
using osu.Game.Modes.UI;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Catch.UI
|
||||
{
|
||||
public class CatchPlayfield : Playfield
|
||||
public class CatchPlayfield : Playfield<CatchBaseHit>
|
||||
{
|
||||
public CatchPlayfield()
|
||||
{
|
||||
|
@ -47,6 +47,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Beatmaps\CatchBeatmapConverter.cs" />
|
||||
<Compile Include="CatchDifficultyCalculator.cs" />
|
||||
<Compile Include="Objects\CatchBaseHit.cs" />
|
||||
<Compile Include="Objects\CatchConverter.cs" />
|
||||
@ -54,10 +55,10 @@
|
||||
<Compile Include="Objects\Droplet.cs" />
|
||||
<Compile Include="Objects\Fruit.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UI\CatchComboCounter.cs" />
|
||||
<Compile Include="UI\CatchHitRenderer.cs" />
|
||||
<Compile Include="UI\CatchPlayfield.cs" />
|
||||
<Compile Include="CatchRuleset.cs" />
|
||||
<Compile Include="CatchMod.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\osu.licenseheader">
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
21
osu.Game.Modes.Mania/Beatmaps/ManiaBeatmapConverter.cs
Normal file
21
osu.Game.Modes.Mania/Beatmaps/ManiaBeatmapConverter.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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.Mania.Objects;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Mania.Beatmaps
|
||||
{
|
||||
internal class ManiaBeatmapConverter : IBeatmapConverter<ManiaBaseHit>
|
||||
{
|
||||
public Beatmap<ManiaBaseHit> Convert(Beatmap original)
|
||||
{
|
||||
return new Beatmap<ManiaBaseHit>(original)
|
||||
{
|
||||
HitObjects = new List<ManiaBaseHit>() // Todo: Implement
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -2,29 +2,24 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Mania.Beatmaps;
|
||||
using osu.Game.Modes.Mania.Objects;
|
||||
using osu.Game.Modes.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Mania
|
||||
{
|
||||
public class ManiaDifficultyCalculator : DifficultyCalculator<ManiaBaseHit>
|
||||
{
|
||||
protected override PlayMode PlayMode => PlayMode.Mania;
|
||||
|
||||
private int columns;
|
||||
|
||||
public ManiaDifficultyCalculator(Beatmap beatmap, int columns = 5) : base(beatmap)
|
||||
public ManiaDifficultyCalculator(Beatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
protected override HitObjectConverter<ManiaBaseHit> Converter => new ManiaConverter(columns);
|
||||
|
||||
protected override double CalculateInternal(Dictionary<String, String> categoryDifficulty)
|
||||
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected override IBeatmapConverter<ManiaBaseHit> CreateBeatmapConverter() => new ManiaBeatmapConverter();
|
||||
}
|
||||
}
|
146
osu.Game.Modes.Mania/ManiaMod.cs
Normal file
146
osu.Game.Modes.Mania/ManiaMod.cs
Normal file
@ -0,0 +1,146 @@
|
||||
// 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.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Mania
|
||||
{
|
||||
public class ManiaModNoFail : ModNoFail
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ManiaModEasy : ModEasy
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ManiaModHidden : ModHidden
|
||||
{
|
||||
public override string Description => @"The notes fade out before you hit them!";
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
|
||||
}
|
||||
|
||||
public class ManiaModHardRock : ModHardRock
|
||||
{
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
}
|
||||
|
||||
public class ManiaModSuddenDeath : ModSuddenDeath
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ManiaModDoubleTime : ModDoubleTime
|
||||
{
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
}
|
||||
|
||||
public class ManiaModHalfTime : ModHalfTime
|
||||
{
|
||||
public override double ScoreMultiplier => 0.3;
|
||||
}
|
||||
|
||||
public class ManiaModNightcore : ModNightcore
|
||||
{
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
}
|
||||
|
||||
public class ManiaModFlashlight : ModFlashlight
|
||||
{
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModHidden) };
|
||||
}
|
||||
|
||||
public class ManiaModPerfect : ModPerfect
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ManiaModFadeIn : Mod
|
||||
{
|
||||
public override string Name => "FadeIn";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => true;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
|
||||
}
|
||||
|
||||
public class ManiaModRandom : Mod
|
||||
{
|
||||
public override string Name => "Random";
|
||||
public override string Description => @"Shuffle around the notes!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
}
|
||||
|
||||
public abstract class ManiaKeyMod : Mod
|
||||
{
|
||||
public abstract int KeyCount { get; }
|
||||
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier
|
||||
public override bool Ranked => true;
|
||||
}
|
||||
|
||||
public class ManiaModKey1 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 1;
|
||||
public override string Name => "1K";
|
||||
}
|
||||
|
||||
public class ManiaModKey2 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 2;
|
||||
public override string Name => "2K";
|
||||
}
|
||||
|
||||
public class ManiaModKey3 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 3;
|
||||
public override string Name => "3K";
|
||||
}
|
||||
|
||||
public class ManiaModKey4 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 4;
|
||||
public override string Name => "4K";
|
||||
}
|
||||
|
||||
public class ManiaModKey5 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 5;
|
||||
public override string Name => "5K";
|
||||
}
|
||||
|
||||
public class ManiaModKey6 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 6;
|
||||
public override string Name => "6K";
|
||||
}
|
||||
|
||||
public class ManiaModKey7 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 7;
|
||||
public override string Name => "7K";
|
||||
}
|
||||
|
||||
public class ManiaModKey8 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 8;
|
||||
public override string Name => "8K";
|
||||
}
|
||||
|
||||
public class ManiaModKey9 : ManiaKeyMod
|
||||
{
|
||||
public override int KeyCount => 9;
|
||||
public override string Name => "9K";
|
||||
}
|
||||
|
||||
public class ManiaModKeyCoop : Mod
|
||||
{
|
||||
public override string Name => "KeyCoop";
|
||||
public override string Description => @"Double the key amount, double the fun!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => true;
|
||||
}
|
||||
}
|
@ -1,26 +1,107 @@
|
||||
// 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.Graphics;
|
||||
using osu.Game.Modes.Mania.UI;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.UI;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Mania
|
||||
{
|
||||
public class ManiaRuleset : Ruleset
|
||||
{
|
||||
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
|
||||
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new ManiaHitRenderer(beatmap);
|
||||
|
||||
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new ManiaHitRenderer { Beatmap = beatmap };
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ModType.DifficultyReduction:
|
||||
return new Mod[]
|
||||
{
|
||||
new ManiaModEasy(),
|
||||
new ManiaModNoFail(),
|
||||
new ManiaModHalfTime(),
|
||||
};
|
||||
|
||||
case ModType.DifficultyIncrease:
|
||||
return new Mod[]
|
||||
{
|
||||
new ManiaModHardRock(),
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ManiaModSuddenDeath(),
|
||||
new ManiaModPerfect(),
|
||||
},
|
||||
},
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ManiaModDoubleTime(),
|
||||
new ManiaModNightcore(),
|
||||
},
|
||||
},
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ManiaModFadeIn(),
|
||||
new ManiaModHidden(),
|
||||
}
|
||||
},
|
||||
new ManiaModFlashlight(),
|
||||
};
|
||||
|
||||
case ModType.Special:
|
||||
return new Mod[]
|
||||
{
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ManiaModKey4(),
|
||||
new ManiaModKey5(),
|
||||
new ManiaModKey6(),
|
||||
new ManiaModKey7(),
|
||||
new ManiaModKey8(),
|
||||
new ManiaModKey9(),
|
||||
new ManiaModKey1(),
|
||||
new ManiaModKey2(),
|
||||
new ManiaModKey3(),
|
||||
},
|
||||
},
|
||||
new ManiaModRandom(),
|
||||
new ManiaModKeyCoop(),
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ModAutoplay(),
|
||||
new ModCinema(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
default:
|
||||
return new Mod[] { };
|
||||
}
|
||||
}
|
||||
|
||||
protected override PlayMode PlayMode => PlayMode.Mania;
|
||||
|
||||
public override string Description => "osu!mania";
|
||||
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mania_o;
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null;
|
||||
public override IEnumerable<KeyCounter> CreateGameplayKeys() => new KeyCounter[] { /* Todo: Should be keymod specific */ };
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount = 0) => null;
|
||||
|
||||
public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser();
|
||||
|
||||
|
@ -26,8 +26,8 @@ namespace osu.Game.Modes.Mania.Objects.Drawable
|
||||
{
|
||||
Texture = textures.Get(@"Menu/logo");
|
||||
|
||||
Transforms.Add(new TransformPositionY() { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f });
|
||||
Transforms.Add(new TransformAlpha() { StartTime = note.StartTime + note.Duration + 200, EndTime = note.StartTime + note.Duration + 400, StartValue = 1, EndValue = 0 });
|
||||
Transforms.Add(new TransformPositionY { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f });
|
||||
Transforms.Add(new TransformAlpha { StartTime = note.StartTime + note.Duration + 200, EndTime = note.StartTime + note.Duration + 400, StartValue = 1, EndValue = 0 });
|
||||
Expire(true);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Modes.Mania.Objects
|
||||
{
|
||||
class ManiaConverter : HitObjectConverter<ManiaBaseHit>
|
||||
internal class ManiaConverter : HitObjectConverter<ManiaBaseHit>
|
||||
{
|
||||
private readonly int columns;
|
||||
|
||||
|
@ -1,78 +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.Framework.Graphics.Transforms;
|
||||
using osu.Game.Modes.Taiko.UI;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Mania.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Similar to osu!taiko, with a pop-out animation when failing (rolling). Used in osu!mania.
|
||||
/// </summary>
|
||||
public class ManiaComboCounter : TaikoComboCounter
|
||||
{
|
||||
protected ushort KeysHeld = 0;
|
||||
|
||||
protected Color4 OriginalColour;
|
||||
|
||||
protected Color4 TintColour => Color4.Orange;
|
||||
protected EasingTypes TintEasing => EasingTypes.None;
|
||||
protected int TintDuration => 500;
|
||||
|
||||
protected Color4 PopOutColor => Color4.Red;
|
||||
protected override float PopOutInitialAlpha => 1.0f;
|
||||
protected override double PopOutDuration => 300;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
PopOutCount.Anchor = Anchor.BottomCentre;
|
||||
PopOutCount.Origin = Anchor.Centre;
|
||||
PopOutCount.FadeColour(PopOutColor, 0);
|
||||
OriginalColour = DisplayedCountSpriteText.Colour;
|
||||
}
|
||||
|
||||
protected override void OnCountRolling(ulong currentValue, ulong newValue)
|
||||
{
|
||||
if (!IsRolling && newValue < currentValue)
|
||||
{
|
||||
PopOutCount.Text = FormatCount(currentValue);
|
||||
|
||||
PopOutCount.FadeTo(PopOutInitialAlpha);
|
||||
PopOutCount.ScaleTo(1.0f);
|
||||
|
||||
PopOutCount.FadeOut(PopOutDuration, PopOutEasing);
|
||||
PopOutCount.ScaleTo(PopOutScale, PopOutDuration, PopOutEasing);
|
||||
}
|
||||
|
||||
base.OnCountRolling(currentValue, newValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tints text while holding a key.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Does not alter combo. This has to be done depending of the scoring system.
|
||||
/// (i.e. v1 = each period of time; v2 = when starting and ending a key hold)
|
||||
/// </remarks>
|
||||
public void HoldStart()
|
||||
{
|
||||
if (KeysHeld == 0)
|
||||
DisplayedCountSpriteText.FadeColour(TintColour, TintDuration, TintEasing);
|
||||
KeysHeld++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ends tinting.
|
||||
/// </summary>
|
||||
public void HoldEnd()
|
||||
{
|
||||
KeysHeld--;
|
||||
if (KeysHeld == 0)
|
||||
DisplayedCountSpriteText.FadeColour(OriginalColour, TintDuration, TintEasing);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +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
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Mania.Beatmaps;
|
||||
using osu.Game.Modes.Mania.Objects;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.UI;
|
||||
|
||||
@ -12,16 +13,17 @@ namespace osu.Game.Modes.Mania.UI
|
||||
{
|
||||
private readonly int columns;
|
||||
|
||||
public ManiaHitRenderer(int columns = 5)
|
||||
public ManiaHitRenderer(Beatmap beatmap, int columns = 5)
|
||||
: base(beatmap)
|
||||
{
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
protected override HitObjectConverter<ManiaBaseHit> Converter => new ManiaConverter(columns);
|
||||
protected override IBeatmapConverter<ManiaBaseHit> CreateBeatmapConverter() => new ManiaBeatmapConverter();
|
||||
|
||||
protected override Playfield CreatePlayfield() => new ManiaPlayfield(columns);
|
||||
protected override Playfield<ManiaBaseHit> CreatePlayfield() => new ManiaPlayfield(columns);
|
||||
|
||||
protected override DrawableHitObject GetVisualRepresentation(ManiaBaseHit h)
|
||||
protected override DrawableHitObject<ManiaBaseHit> GetVisualRepresentation(ManiaBaseHit h)
|
||||
{
|
||||
return null;
|
||||
//return new DrawableNote(h)
|
||||
|
@ -3,19 +3,17 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Modes.Mania.Objects;
|
||||
using osu.Game.Modes.UI;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Mania.UI
|
||||
{
|
||||
public class ManiaPlayfield : Playfield
|
||||
public class ManiaPlayfield : Playfield<ManiaBaseHit>
|
||||
{
|
||||
private readonly int columns;
|
||||
|
||||
public ManiaPlayfield(int columns)
|
||||
{
|
||||
this.columns = columns;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Size = new Vector2(columns / 20f, 1f);
|
||||
Anchor = Anchor.BottomCentre;
|
||||
@ -24,7 +22,7 @@ namespace osu.Game.Modes.Mania.UI
|
||||
Add(new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.5f });
|
||||
|
||||
for (int i = 0; i < columns; i++)
|
||||
Add(new Box()
|
||||
Add(new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Size = new Vector2(2, 1),
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
@ -47,6 +47,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Beatmaps\ManiaBeatmapConverter.cs" />
|
||||
<Compile Include="ManiaDifficultyCalculator.cs" />
|
||||
<Compile Include="Objects\Drawable\DrawableNote.cs" />
|
||||
<Compile Include="Objects\HoldNote.cs" />
|
||||
@ -54,10 +55,10 @@
|
||||
<Compile Include="Objects\ManiaConverter.cs" />
|
||||
<Compile Include="Objects\Note.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UI\ManiaComboCounter.cs" />
|
||||
<Compile Include="UI\ManiaHitRenderer.cs" />
|
||||
<Compile Include="UI\ManiaPlayfield.cs" />
|
||||
<Compile Include="ManiaRuleset.cs" />
|
||||
<Compile Include="ManiaMod.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||
@ -85,6 +86,7 @@
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
@ -1,35 +1,45 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Beatmaps
|
||||
{
|
||||
public class OsuHitObjectConverter : HitObjectConverter<OsuHitObject>
|
||||
internal class OsuBeatmapConverter : IBeatmapConverter<OsuHitObject>
|
||||
{
|
||||
public override List<OsuHitObject> Convert(Beatmap beatmap)
|
||||
public Beatmap<OsuHitObject> Convert(Beatmap original)
|
||||
{
|
||||
List<OsuHitObject> output = new List<OsuHitObject>();
|
||||
return new Beatmap<OsuHitObject>(original)
|
||||
{
|
||||
HitObjects = convertHitObject(original.HitObjects, original.BeatmapInfo?.StackLeniency ?? 0.7f)
|
||||
};
|
||||
}
|
||||
|
||||
private List<OsuHitObject> convertHitObject(List<HitObject> hitObjects, float stackLeniency)
|
||||
{
|
||||
List<OsuHitObject> converted = new List<OsuHitObject>();
|
||||
|
||||
int combo = 0;
|
||||
foreach (HitObject h in beatmap.HitObjects)
|
||||
foreach (HitObject h in hitObjects)
|
||||
{
|
||||
if (h.NewCombo) combo = 0;
|
||||
|
||||
h.ComboIndex = combo++;
|
||||
output.Add(h as OsuHitObject);
|
||||
converted.Add(h as OsuHitObject);
|
||||
}
|
||||
|
||||
UpdateStacking(output, beatmap.BeatmapInfo?.StackLeniency ?? 0.7f);
|
||||
updateStacking(converted, stackLeniency);
|
||||
|
||||
return output;
|
||||
return converted;
|
||||
}
|
||||
|
||||
public static void UpdateStacking(List<OsuHitObject> hitObjects, float stackLeniency, int startIndex = 0, int endIndex = -1)
|
||||
private void updateStacking(List<OsuHitObject> hitObjects, float stackLeniency, int startIndex = 0, int endIndex = -1)
|
||||
{
|
||||
if (endIndex == -1)
|
||||
endIndex = hitObjects.Count - 1;
|
||||
@ -59,7 +69,7 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
break;
|
||||
|
||||
if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stackDistance ||
|
||||
(stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stackDistance))
|
||||
stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stackDistance)
|
||||
{
|
||||
stackBaseIndex = n;
|
||||
|
||||
@ -171,6 +181,5 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -79,12 +79,9 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
// We select the amount of points for the approximation by requiring the discrete curvature
|
||||
// to be smaller than the provided tolerance. The exact angle required to meet the tolerance
|
||||
// is: 2 * Math.Acos(1 - TOLERANCE / r)
|
||||
if (2 * r <= tolerance)
|
||||
// This special case is required for extremely short sliders where the radius is smaller than
|
||||
// the tolerance. This is a pathological rather than a realistic case.
|
||||
amountPoints = 2;
|
||||
else
|
||||
amountPoints = Math.Max(2, (int)Math.Ceiling(thetaRange / (2 * Math.Acos(1 - tolerance / r))));
|
||||
// The special case is required for extremely short sliders where the radius is smaller than
|
||||
// the tolerance. This is a pathological rather than a realistic case.
|
||||
amountPoints = 2 * r <= tolerance ? 2 : Math.Max(2, (int)Math.Ceiling(thetaRange / (2 * Math.Acos(1 - tolerance / r))));
|
||||
|
||||
List<Vector2> output = new List<Vector2>(amountPoints);
|
||||
|
||||
|
@ -3,11 +3,11 @@
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
|
||||
{
|
||||
@ -17,7 +17,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
|
||||
public double EndTime;
|
||||
public Vector2 EndPosition;
|
||||
|
||||
const float width = 8;
|
||||
private const float width = 8;
|
||||
|
||||
public FollowPoint()
|
||||
{
|
||||
|
@ -1,12 +1,11 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables.Connections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
|
||||
{
|
||||
public class FollowPointRenderer : ConnectionRenderer<OsuHitObject>
|
||||
{
|
||||
@ -74,13 +73,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance)
|
||||
{
|
||||
float fraction = ((float)d / distance);
|
||||
float fraction = (float)d / distance;
|
||||
Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector;
|
||||
Vector2 pointEndPosition = startPosition + fraction * distanceVector;
|
||||
double fadeOutTime = startTime + fraction * duration;
|
||||
double fadeInTime = fadeOutTime - PreEmpt;
|
||||
|
||||
Add(new FollowPoint()
|
||||
Add(new FollowPoint
|
||||
{
|
||||
StartTime = fadeInTime,
|
||||
EndTime = fadeOutTime,
|
||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
return true;
|
||||
},
|
||||
},
|
||||
number = new NumberPiece()
|
||||
number = new NumberPiece
|
||||
{
|
||||
Text = h is Spinner ? "S" : (HitObject.ComboIndex + 1).ToString(),
|
||||
},
|
||||
@ -59,7 +59,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
{
|
||||
Colour = osuObject.Colour,
|
||||
},
|
||||
ApproachCircle = new ApproachCircle()
|
||||
ApproachCircle = new ApproachCircle
|
||||
{
|
||||
Colour = osuObject.Colour,
|
||||
}
|
||||
@ -69,33 +69,23 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
Size = circle.DrawSize;
|
||||
}
|
||||
|
||||
double hit50 = 150;
|
||||
double hit100 = 80;
|
||||
double hit300 = 30;
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset > hit50)
|
||||
if (Judgement.TimeOffset > HitObject.HitWindowFor(OsuScoreResult.Hit50))
|
||||
Judgement.Result = HitResult.Miss;
|
||||
return;
|
||||
}
|
||||
|
||||
double hitOffset = Math.Abs(Judgement.TimeOffset);
|
||||
|
||||
OsuJudgementInfo osuJudgement = Judgement as OsuJudgementInfo;
|
||||
OsuJudgementInfo osuJudgement = (OsuJudgementInfo)Judgement;
|
||||
|
||||
if (hitOffset < hit50)
|
||||
if (hitOffset < HitObject.HitWindowFor(OsuScoreResult.Hit50))
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
|
||||
if (hitOffset < hit300)
|
||||
osuJudgement.Score = OsuScoreResult.Hit300;
|
||||
else if (hitOffset < hit100)
|
||||
osuJudgement.Score = OsuScoreResult.Hit100;
|
||||
else if (hitOffset < hit50)
|
||||
osuJudgement.Score = OsuScoreResult.Hit50;
|
||||
osuJudgement.Score = HitObject.ScoreResultForOffset(hitOffset);
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
|
@ -2,12 +2,11 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableOsuHitObject : DrawableHitObject
|
||||
public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject>
|
||||
{
|
||||
public const float TIME_PREEMPT = 600;
|
||||
public const float TIME_FADEIN = 400;
|
||||
@ -18,7 +17,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
{
|
||||
}
|
||||
|
||||
public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.Hit300 };
|
||||
protected override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.Hit300 };
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
|
@ -21,13 +21,14 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
private Container<DrawableSliderTick> ticks;
|
||||
|
||||
SliderBody body;
|
||||
SliderBall ball;
|
||||
private SliderBody body;
|
||||
private SliderBall ball;
|
||||
|
||||
SliderBouncer bouncer1, bouncer2;
|
||||
private SliderBouncer bouncer2;
|
||||
|
||||
public DrawableSlider(Slider s) : base(s)
|
||||
{
|
||||
SliderBouncer bouncer1;
|
||||
slider = s;
|
||||
|
||||
Children = new Drawable[]
|
||||
@ -94,7 +95,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
// pass all input through.
|
||||
public override bool Contains(Vector2 screenSpacePos) => true;
|
||||
|
||||
int currentRepeat;
|
||||
private int currentRepeat;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
@ -102,8 +103,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
|
||||
|
||||
int repeat = (int)(progress * slider.RepeatCount);
|
||||
progress = (progress * slider.RepeatCount) % 1;
|
||||
int repeat = slider.RepeatAt(progress);
|
||||
progress = slider.CurveProgressAt(progress);
|
||||
|
||||
if (repeat > currentRepeat)
|
||||
{
|
||||
@ -112,9 +113,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
currentRepeat = repeat;
|
||||
}
|
||||
|
||||
if (repeat % 2 == 1)
|
||||
progress = 1 - progress;
|
||||
|
||||
bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0);
|
||||
|
||||
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
|
||||
@ -127,8 +125,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
var j = Judgement as OsuJudgementInfo;
|
||||
var sc = initialCircle.Judgement as OsuJudgementInfo;
|
||||
var j = (OsuJudgementInfo)Judgement;
|
||||
var sc = (OsuJudgementInfo)initialCircle.Judgement;
|
||||
|
||||
if (!userTriggered && Time.Current >= HitObject.EndTime)
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
public override bool RemoveWhenNotAlive => false;
|
||||
|
||||
public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.SliderTick };
|
||||
protected override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.SliderTick };
|
||||
|
||||
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
|
||||
{
|
||||
@ -71,7 +71,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
var j = Judgement as OsuJudgementInfo;
|
||||
var j = (OsuJudgementInfo)Judgement;
|
||||
|
||||
if (Judgement.TimeOffset >= 0)
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
{
|
||||
if (Time.Current < HitObject.StartTime) return;
|
||||
|
||||
var j = Judgement as OsuJudgementInfo;
|
||||
var j = (OsuJudgementInfo)Judgement;
|
||||
|
||||
disc.ScaleTo(Interpolation.ValueAt(Math.Sqrt(Progress), scaleToCircle, Vector2.One, 0, 1), 100);
|
||||
|
||||
@ -108,9 +108,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 scaleToCircle => (circle.Scale * circle.DrawWidth / DrawWidth) * 0.95f;
|
||||
private Vector2 scaleToCircle => circle.Scale * circle.DrawWidth / DrawWidth * 0.95f;
|
||||
|
||||
private float spinsPerMinuteNeeded = 100 + (5 * 15); //TODO: read per-map OD and place it on the 5
|
||||
private float spinsPerMinuteNeeded = 100 + 5 * 15; //TODO: read per-map OD and place it on the 5
|
||||
|
||||
private float rotationsNeeded => (float)(spinsPerMinuteNeeded * (spinner.EndTime - spinner.StartTime) / 60000f);
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Direction = FillDirection.Down;
|
||||
Direction = FillDirection.Vertical;
|
||||
Spacing = new Vector2(0, 2);
|
||||
Position = (h?.StackedEndPosition ?? Vector2.Zero) + judgement.PositionOffset;
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
|
||||
public CirclePiece()
|
||||
{
|
||||
Size = new Vector2(128);
|
||||
Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2);
|
||||
Masking = true;
|
||||
CornerRadius = Size.X / 2;
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
// 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;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
private readonly Slider slider;
|
||||
private Box follow;
|
||||
|
||||
const float width = 128;
|
||||
private const float width = 128;
|
||||
|
||||
public SliderBall(Slider slider)
|
||||
{
|
||||
@ -81,7 +81,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
return base.OnMouseMove(state);
|
||||
}
|
||||
|
||||
bool tracking;
|
||||
private bool tracking;
|
||||
public bool Tracking
|
||||
{
|
||||
get { return tracking; }
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -28,7 +29,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
set { Disc.Colour = value; }
|
||||
}
|
||||
|
||||
Color4 completeColour;
|
||||
private Color4 completeColour;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
@ -36,7 +37,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
completeColour = colours.YellowLight.Opacity(0.8f);
|
||||
}
|
||||
|
||||
class SpinnerBorder : Container
|
||||
private class SpinnerBorder : Container
|
||||
{
|
||||
public SpinnerBorder()
|
||||
{
|
||||
@ -115,7 +116,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
};
|
||||
}
|
||||
|
||||
bool tracking;
|
||||
private bool tracking;
|
||||
public bool Tracking
|
||||
{
|
||||
get { return tracking; }
|
||||
@ -129,7 +130,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
|
||||
bool complete;
|
||||
private bool complete;
|
||||
public bool Complete
|
||||
{
|
||||
get { return complete; }
|
||||
|
@ -5,11 +5,19 @@ using System;
|
||||
using osu.Game.Modes.Objects;
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
public abstract class OsuHitObject : HitObject
|
||||
{
|
||||
public const double OBJECT_RADIUS = 64;
|
||||
|
||||
private const double hittable_range = 300;
|
||||
private const double hit_window_50 = 150;
|
||||
private const double hit_window_100 = 80;
|
||||
private const double hit_window_300 = 30;
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public Vector2 StackedPosition => Position + StackOffset;
|
||||
@ -22,10 +30,38 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
|
||||
public Vector2 StackOffset => new Vector2(StackHeight * Scale * -6.4f);
|
||||
|
||||
public double Radius => OBJECT_RADIUS * Scale;
|
||||
|
||||
public float Scale { get; set; } = 1;
|
||||
|
||||
public abstract HitObjectType Type { get; }
|
||||
|
||||
public double HitWindowFor(OsuScoreResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 300;
|
||||
case OsuScoreResult.Hit50:
|
||||
return 150;
|
||||
case OsuScoreResult.Hit100:
|
||||
return 80;
|
||||
case OsuScoreResult.Hit300:
|
||||
return 30;
|
||||
}
|
||||
}
|
||||
|
||||
public OsuScoreResult ScoreResultForOffset(double offset)
|
||||
{
|
||||
if (offset < HitWindowFor(OsuScoreResult.Hit300))
|
||||
return OsuScoreResult.Hit300;
|
||||
if (offset < HitWindowFor(OsuScoreResult.Hit100))
|
||||
return OsuScoreResult.Hit100;
|
||||
if (offset < HitWindowFor(OsuScoreResult.Hit50))
|
||||
return OsuScoreResult.Hit50;
|
||||
return OsuScoreResult.Miss;
|
||||
}
|
||||
|
||||
public override void SetDefaultsFromBeatmap(Beatmap beatmap)
|
||||
{
|
||||
base.SetDefaultsFromBeatmap(beatmap);
|
||||
|
@ -8,7 +8,7 @@ using System.Linq;
|
||||
|
||||
namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
class OsuHitObjectDifficulty
|
||||
internal class OsuHitObjectDifficulty
|
||||
{
|
||||
/// <summary>
|
||||
/// Factor by how much speed / aim strain decays per second.
|
||||
@ -63,7 +63,7 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
MaxCombo += slider.Ticks.Count();
|
||||
|
||||
// We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
|
||||
scalingFactor = (52.0f / circleRadius);
|
||||
scalingFactor = 52.0f / circleRadius;
|
||||
if (circleRadius < 30)
|
||||
{
|
||||
float smallCircleBonus = Math.Min(30.0f - circleRadius, 5.0f) / 50.0f;
|
||||
@ -130,7 +130,7 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
else if (distance > almost_diameter)
|
||||
return 1.2 + 0.4 * (distance - almost_diameter) / (stream_spacing_threshold - almost_diameter);
|
||||
else if (distance > almost_diameter / 2)
|
||||
return 0.95 + 0.25 * (distance - (almost_diameter / 2)) / (almost_diameter / 2);
|
||||
return 0.95 + 0.25 * (distance - almost_diameter / 2) / (almost_diameter / 2);
|
||||
else
|
||||
return 0.95;
|
||||
|
||||
|
@ -30,18 +30,15 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
break;
|
||||
case HitObjectType.Slider:
|
||||
CurveTypes curveType = CurveTypes.Catmull;
|
||||
int repeatCount;
|
||||
double length = 0;
|
||||
List<Vector2> points = new List<Vector2>();
|
||||
|
||||
points.Add(new Vector2(int.Parse(split[0]), int.Parse(split[1])));
|
||||
List<Vector2> points = new List<Vector2> { new Vector2(int.Parse(split[0]), int.Parse(split[1])) };
|
||||
|
||||
string[] pointsplit = split[5].Split('|');
|
||||
for (int i = 0; i < pointsplit.Length; i++)
|
||||
foreach (string t in pointsplit)
|
||||
{
|
||||
if (pointsplit[i].Length == 1)
|
||||
if (t.Length == 1)
|
||||
{
|
||||
switch (pointsplit[i])
|
||||
switch (t)
|
||||
{
|
||||
case @"C":
|
||||
curveType = CurveTypes.Catmull;
|
||||
@ -59,7 +56,7 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] temp = pointsplit[i].Split(':');
|
||||
string[] temp = t.Split(':');
|
||||
Vector2 v = new Vector2(
|
||||
(int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture),
|
||||
(int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture)
|
||||
@ -67,12 +64,10 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
points.Add(v);
|
||||
}
|
||||
|
||||
repeatCount = Convert.ToInt32(split[6], CultureInfo.InvariantCulture);
|
||||
int repeatCount = Convert.ToInt32(split[6], CultureInfo.InvariantCulture);
|
||||
|
||||
if (repeatCount > 9000)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("wacky man");
|
||||
}
|
||||
throw new ArgumentOutOfRangeException(nameof(repeatCount), @"Repeat count is way too high");
|
||||
|
||||
if (split.Length > 7)
|
||||
length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture);
|
||||
|
@ -14,7 +14,32 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
{
|
||||
public override double EndTime => StartTime + RepeatCount * Curve.Length / Velocity;
|
||||
|
||||
public override Vector2 EndPosition => RepeatCount % 2 == 0 ? Position : Curve.PositionAt(1);
|
||||
public override Vector2 EndPosition => PositionAt(1);
|
||||
|
||||
/// <summary>
|
||||
/// Computes the position on the slider at a given progress that ranges from 0 (beginning of the slider)
|
||||
/// to 1 (end of the slider). This includes repeat logic.
|
||||
/// </summary>
|
||||
/// <param name="progress">Ranges from 0 (beginning of the slider) to 1 (end of the slider).</param>
|
||||
/// <returns></returns>
|
||||
public Vector2 PositionAt(double progress) => Curve.PositionAt(CurveProgressAt(progress));
|
||||
|
||||
/// <summary>
|
||||
/// Find the current progress along the curve, accounting for repeat logic.
|
||||
/// </summary>
|
||||
public double CurveProgressAt(double progress)
|
||||
{
|
||||
var p = progress * RepeatCount % 1;
|
||||
if (RepeatAt(progress) % 2 == 1)
|
||||
p = 1 - p;
|
||||
return p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine which repeat of the slider we are on at a given progress.
|
||||
/// Range is 0..RepeatCount where 0 is the first run.
|
||||
/// </summary>
|
||||
public int RepeatAt(double progress) => (int)(progress * RepeatCount);
|
||||
|
||||
private int stackHeight;
|
||||
public override int StackHeight
|
||||
|
@ -59,10 +59,9 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
if (i == ControlPoints.Count - 1 || ControlPoints[i] == ControlPoints[i + 1])
|
||||
{
|
||||
List<Vector2> subpath = calculateSubpath(subControlPoints);
|
||||
for (int j = 0; j < subpath.Count; ++j)
|
||||
// Only add those vertices that add a new segment to the path.
|
||||
if (calculatedPath.Count == 0 || calculatedPath.Last() != subpath[j])
|
||||
calculatedPath.Add(subpath[j]);
|
||||
foreach (Vector2 t in subpath)
|
||||
if (calculatedPath.Count == 0 || calculatedPath.Last() != t)
|
||||
calculatedPath.Add(t);
|
||||
|
||||
subControlPoints.Clear();
|
||||
}
|
||||
@ -175,7 +174,7 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
path.Clear();
|
||||
|
||||
int i = 0;
|
||||
for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i) ;
|
||||
for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i) { }
|
||||
|
||||
path.Add(interpolateVertices(i, d0) + Offset);
|
||||
|
||||
@ -186,10 +185,10 @@ namespace osu.Game.Modes.Osu.Objects
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the position on the slider at a given progress that ranges from 0 (beginning of the slider)
|
||||
/// to 1 (end of the slider).
|
||||
/// Computes the position on the slider at a given progress that ranges from 0 (beginning of the curve)
|
||||
/// to 1 (end of the curve).
|
||||
/// </summary>
|
||||
/// <param name="progress">Ranges from 0 (beginning of the slider) to 1 (end of the slider).</param>
|
||||
/// <param name="progress">Ranges from 0 (beginning of the curve) to 1 (end of the curve).</param>
|
||||
/// <returns></returns>
|
||||
public Vector2 PositionAt(double progress)
|
||||
{
|
||||
|
299
osu.Game.Modes.Osu/OsuAutoReplay.cs
Normal file
299
osu.Game.Modes.Osu/OsuAutoReplay.cs
Normal file
@ -0,0 +1,299 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using OpenTK;
|
||||
using System;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using osu.Framework.MathUtils;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
public class OsuAutoReplay : LegacyReplay
|
||||
{
|
||||
private static readonly Vector2 spinner_centre = new Vector2(256, 192);
|
||||
|
||||
private const float spin_radius = 50;
|
||||
|
||||
private Beatmap beatmap;
|
||||
|
||||
public OsuAutoReplay(Beatmap beatmap)
|
||||
{
|
||||
this.beatmap = beatmap;
|
||||
|
||||
createAutoReplay();
|
||||
}
|
||||
|
||||
internal class LegacyReplayFrameComparer : IComparer<LegacyReplayFrame>
|
||||
{
|
||||
public int Compare(LegacyReplayFrame f1, LegacyReplayFrame f2)
|
||||
{
|
||||
return f1.Time.CompareTo(f2.Time);
|
||||
}
|
||||
}
|
||||
|
||||
private static IComparer<LegacyReplayFrame> replayFrameComparer = new LegacyReplayFrameComparer();
|
||||
|
||||
private int findInsertionIndex(LegacyReplayFrame frame)
|
||||
{
|
||||
int index = Frames.BinarySearch(frame, replayFrameComparer);
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
index = ~index;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Go to the first index which is actually bigger
|
||||
while (index < Frames.Count && frame.Time == Frames[index].Time)
|
||||
{
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
private void addFrameToReplay(LegacyReplayFrame 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));
|
||||
|
||||
private double applyModsToTime(double v) => v;
|
||||
private double applyModsToRate(double v) => v;
|
||||
|
||||
public bool DelayedMovements; // ModManager.CheckActive(Mods.Relax2);
|
||||
|
||||
private void createAutoReplay()
|
||||
{
|
||||
int buttonIndex = 0;
|
||||
|
||||
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));
|
||||
|
||||
// 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);
|
||||
|
||||
// Already superhuman, but still somewhat realistic
|
||||
int reactionTime = (int)applyModsToRate(100);
|
||||
|
||||
|
||||
for (int i = 0; i < beatmap.HitObjects.Count; i++)
|
||||
{
|
||||
OsuHitObject h = (OsuHitObject)beatmap.HitObjects[i];
|
||||
|
||||
//if (h.EndTime < InputManager.ReplayStartTime)
|
||||
//{
|
||||
// h.IsHit = true;
|
||||
// continue;
|
||||
//}
|
||||
|
||||
int endDelay = h is Spinner ? 1 : 0;
|
||||
|
||||
if (DelayedMovements && i > 0)
|
||||
{
|
||||
OsuHitObject last = (OsuHitObject)beatmap.HitObjects[i - 1];
|
||||
|
||||
//Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
|
||||
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > last.EndTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - last.EndTime < 1000) addFrameToReplay(new LegacyReplayFrame(last.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));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > last.EndTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - last.EndTime < 1000) addFrameToReplay(new LegacyReplayFrame(last.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));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > last.EndTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
|
||||
{
|
||||
if (!(last is Spinner) && h.StartTime - last.EndTime < 1000) addFrameToReplay(new LegacyReplayFrame(last.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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector2 targetPosition = h.Position;
|
||||
EasingTypes easing = preferredEasing;
|
||||
float spinnerDirection = -1;
|
||||
|
||||
if (h is Spinner)
|
||||
{
|
||||
targetPosition.X = Frames[Frames.Count - 1].MouseX;
|
||||
targetPosition.Y = Frames[Frames.Count - 1].MouseY;
|
||||
|
||||
Vector2 difference = spinner_centre - targetPosition;
|
||||
|
||||
float differenceLength = difference.Length;
|
||||
float newLength = (float)Math.Sqrt(differenceLength * differenceLength - spin_radius * spin_radius);
|
||||
|
||||
if (differenceLength > spin_radius)
|
||||
{
|
||||
float angle = (float)Math.Asin(spin_radius / differenceLength);
|
||||
|
||||
if (angle > 0)
|
||||
{
|
||||
spinnerDirection = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
spinnerDirection = 1;
|
||||
}
|
||||
|
||||
difference.X = difference.X * (float)Math.Cos(angle) - difference.Y * (float)Math.Sin(angle);
|
||||
difference.Y = difference.X * (float)Math.Sin(angle) + difference.Y * (float)Math.Cos(angle);
|
||||
|
||||
difference.Normalize();
|
||||
difference *= newLength;
|
||||
|
||||
targetPosition += difference;
|
||||
|
||||
easing = EasingTypes.In;
|
||||
}
|
||||
else if (difference.Length > 0)
|
||||
{
|
||||
targetPosition = spinner_centre - difference * (spin_radius / difference.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPosition = spinner_centre + new Vector2(0, -spin_radius);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do some nice easing for cursor movements
|
||||
if (Frames.Count > 0)
|
||||
{
|
||||
LegacyReplayFrame 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);
|
||||
addFrameToReplay(lastFrame);
|
||||
}
|
||||
|
||||
Vector2 lastPosition = new Vector2(lastFrame.MouseX, lastFrame.MouseY);
|
||||
|
||||
double timeDifference = applyModsToTime(h.StartTime - lastFrame.Time);
|
||||
|
||||
// Only "snap" to hitcircles if they are far enough apart. As the time between hitcircles gets shorter the snapping threshold goes up.
|
||||
if (timeDifference > 0 && // Sanity checks
|
||||
((lastPosition - targetPosition).Length > h.Radius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough
|
||||
timeDifference >= 266)) // ... or the beats are slow enough to tap anyway.
|
||||
{
|
||||
// Perform eased movement
|
||||
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));
|
||||
}
|
||||
|
||||
buttonIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
LegacyButtonState button = buttonIndex % 2 == 0 ? LegacyButtonState.Left1 : LegacyButtonState.Right1;
|
||||
|
||||
LegacyReplayFrame newFrame = new LegacyReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button);
|
||||
LegacyReplayFrame endFrame = new LegacyReplayFrame(h.EndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, LegacyButtonState.None);
|
||||
|
||||
// Decrement because we want the previous frame, not the next one
|
||||
int index = findInsertionIndex(newFrame) - 1;
|
||||
|
||||
// Do we have a previous frame? No need to check for < replay.Count since we decremented!
|
||||
if (index >= 0)
|
||||
{
|
||||
LegacyReplayFrame previousFrame = Frames[index];
|
||||
var previousButton = previousFrame.ButtonState;
|
||||
|
||||
// If a button is already held, then we simply alternate
|
||||
if (previousButton != LegacyButtonState.None)
|
||||
{
|
||||
Debug.Assert(previousButton != (LegacyButtonState.Left1 | LegacyButtonState.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);
|
||||
}
|
||||
|
||||
// We always follow the most recent slider / spinner, so remove any other frames that occur while it exists.
|
||||
int endIndex = findInsertionIndex(endFrame);
|
||||
|
||||
if (index < Frames.Count - 1)
|
||||
Frames.RemoveRange(index + 1, Math.Max(0, endIndex - (index + 1)));
|
||||
|
||||
// After alternating we need to keep holding the other button in the future rather than the previous one.
|
||||
for (int j = index + 1; j < Frames.Count; ++j)
|
||||
{
|
||||
// Don't affect frames which stop pressing a button!
|
||||
if (j < Frames.Count - 1 || Frames[j].ButtonState == previousButton)
|
||||
Frames[j].SetButtonStates(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addFrameToReplay(newFrame);
|
||||
|
||||
// We add intermediate frames for spinning / following a slider here.
|
||||
if (h is Spinner)
|
||||
{
|
||||
Vector2 difference = targetPosition - spinner_centre;
|
||||
|
||||
float radius = difference.Length;
|
||||
float angle = radius == 0 ? 0 : (float)Math.Atan2(difference.Y, difference.X);
|
||||
|
||||
double t;
|
||||
|
||||
for (double j = h.StartTime + frameDelay; j < h.EndTime; j += frameDelay)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
t = applyModsToTime(h.EndTime - h.StartTime) * spinnerDirection;
|
||||
Vector2 endPosition = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
|
||||
|
||||
addFrameToReplay(new LegacyReplayFrame(h.EndTime, endPosition.X, endPosition.Y, button));
|
||||
|
||||
endFrame.MouseX = endPosition.X;
|
||||
endFrame.MouseY = endPosition.Y;
|
||||
}
|
||||
else if (h is Slider)
|
||||
{
|
||||
Slider s = h as Slider;
|
||||
|
||||
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 LegacyReplayFrame(h.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!
|
||||
if (Frames[Frames.Count - 1].Time <= endFrame.Time)
|
||||
addFrameToReplay(endFrame);
|
||||
}
|
||||
|
||||
//Player.currentScore.Replay = InputManager.ReplayScore.Replay;
|
||||
//Player.currentScore.PlayerName = "osu!";
|
||||
}
|
||||
}
|
||||
}
|
@ -2,10 +2,10 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Modes.Objects;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
@ -14,8 +14,6 @@ namespace osu.Game.Modes.Osu
|
||||
private const double star_scaling_factor = 0.0675;
|
||||
private const double extreme_scaling_factor = 0.5;
|
||||
|
||||
protected override PlayMode PlayMode => PlayMode.Osu;
|
||||
|
||||
/// <summary>
|
||||
/// HitObjects are stored as a member variable.
|
||||
/// </summary>
|
||||
@ -25,8 +23,6 @@ namespace osu.Game.Modes.Osu
|
||||
{
|
||||
}
|
||||
|
||||
protected override HitObjectConverter<OsuHitObject> Converter => new OsuHitObjectConverter();
|
||||
|
||||
protected override void PreprocessHitObjects()
|
||||
{
|
||||
foreach (var h in Objects)
|
||||
@ -34,7 +30,7 @@ namespace osu.Game.Modes.Osu
|
||||
((Slider)h).Curve.Calculate();
|
||||
}
|
||||
|
||||
protected override double CalculateInternal(Dictionary<String, String> categoryDifficulty)
|
||||
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
|
||||
{
|
||||
// Fill our custom DifficultyHitObject class, that carries additional information
|
||||
DifficultyHitObjects.Clear();
|
||||
@ -100,22 +96,23 @@ namespace osu.Game.Modes.Osu
|
||||
protected bool CalculateStrainValues()
|
||||
{
|
||||
// Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment.
|
||||
List<OsuHitObjectDifficulty>.Enumerator hitObjectsEnumerator = DifficultyHitObjects.GetEnumerator();
|
||||
|
||||
if (!hitObjectsEnumerator.MoveNext()) return false;
|
||||
|
||||
OsuHitObjectDifficulty currentHitObject = hitObjectsEnumerator.Current;
|
||||
OsuHitObjectDifficulty nextHitObject;
|
||||
|
||||
// First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject.
|
||||
while (hitObjectsEnumerator.MoveNext())
|
||||
using (List<OsuHitObjectDifficulty>.Enumerator hitObjectsEnumerator = DifficultyHitObjects.GetEnumerator())
|
||||
{
|
||||
nextHitObject = hitObjectsEnumerator.Current;
|
||||
nextHitObject.CalculateStrains(currentHitObject, TimeRate);
|
||||
currentHitObject = nextHitObject;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!hitObjectsEnumerator.MoveNext()) return false;
|
||||
|
||||
OsuHitObjectDifficulty current = hitObjectsEnumerator.Current;
|
||||
|
||||
// First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject.
|
||||
while (hitObjectsEnumerator.MoveNext())
|
||||
{
|
||||
var next = hitObjectsEnumerator.Current;
|
||||
next?.CalculateStrains(current, TimeRate);
|
||||
current = next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -183,8 +180,10 @@ namespace osu.Game.Modes.Osu
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
protected override IBeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter();
|
||||
|
||||
// Those values are used as array indices. Be careful when changing them!
|
||||
public enum DifficultyType : int
|
||||
public enum DifficultyType
|
||||
{
|
||||
Speed = 0,
|
||||
Aim,
|
||||
|
100
osu.Game.Modes.Osu/OsuMod.cs
Normal file
100
osu.Game.Modes.Osu/OsuMod.cs
Normal file
@ -0,0 +1,100 @@
|
||||
// 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.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
public class OsuModNoFail : ModNoFail
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
|
||||
public class OsuModEasy : ModEasy
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class OsuModHidden : ModHidden
|
||||
{
|
||||
public override string Description => @"Play with no approach circles and fading notes for a slight score advantage.";
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
}
|
||||
|
||||
public class OsuModHardRock : ModHardRock
|
||||
{
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
public override bool Ranked => true;
|
||||
}
|
||||
|
||||
public class OsuModSuddenDeath : ModSuddenDeath
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
|
||||
public class OsuModDoubleTime : ModDoubleTime
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
|
||||
public class OsuModRelax : ModRelax
|
||||
{
|
||||
public override string Description => "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things.";
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
|
||||
public class OsuModHalfTime : ModHalfTime
|
||||
{
|
||||
public override double ScoreMultiplier => 0.5;
|
||||
}
|
||||
|
||||
public class OsuModNightcore : ModNightcore
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
|
||||
public class OsuModFlashlight : ModFlashlight
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
}
|
||||
|
||||
public class OsuModPerfect : ModPerfect
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class OsuModSpunOut : Mod
|
||||
{
|
||||
public override string Name => "Spun Out";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
|
||||
public override string Description => @"Spinners will be automatically completed";
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
public override bool Ranked => true;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) };
|
||||
}
|
||||
|
||||
public class OsuModAutopilot : Mod
|
||||
{
|
||||
public override string Name => "Autopilot";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
|
||||
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
||||
public override double ScoreMultiplier => 0;
|
||||
public override bool Ranked => false;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) };
|
||||
}
|
||||
|
||||
public class OsuModAutoplay : ModAutoplay
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
|
||||
}
|
||||
|
||||
public class OsuModTarget : Mod
|
||||
{
|
||||
public override string Name => "Target";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
|
||||
public override string Description => @"";
|
||||
public override double ScoreMultiplier => 1;
|
||||
}
|
||||
}
|
@ -1,22 +1,22 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Osu.UI;
|
||||
using osu.Game.Modes.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
public class OsuRuleset : Ruleset
|
||||
{
|
||||
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
|
||||
|
||||
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new OsuHitRenderer { Beatmap = beatmap };
|
||||
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new OsuHitRenderer(beatmap);
|
||||
|
||||
public override IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new[]
|
||||
{
|
||||
@ -34,14 +34,89 @@ namespace osu.Game.Modes.Osu
|
||||
}
|
||||
};
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ModType.DifficultyReduction:
|
||||
return new Mod[]
|
||||
{
|
||||
new OsuModEasy(),
|
||||
new OsuModNoFail(),
|
||||
new OsuModHalfTime(),
|
||||
};
|
||||
|
||||
case ModType.DifficultyIncrease:
|
||||
return new Mod[]
|
||||
{
|
||||
new OsuModHardRock(),
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new OsuModSuddenDeath(),
|
||||
new OsuModPerfect(),
|
||||
},
|
||||
},
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new OsuModDoubleTime(),
|
||||
new OsuModNightcore(),
|
||||
},
|
||||
},
|
||||
new OsuModHidden(),
|
||||
new OsuModFlashlight(),
|
||||
};
|
||||
|
||||
case ModType.Special:
|
||||
return new Mod[]
|
||||
{
|
||||
new OsuModRelax(),
|
||||
new OsuModAutopilot(),
|
||||
new OsuModSpunOut(),
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new OsuModAutoplay(),
|
||||
new ModCinema(),
|
||||
},
|
||||
},
|
||||
new OsuModTarget(),
|
||||
};
|
||||
|
||||
default:
|
||||
return new Mod[] { };
|
||||
}
|
||||
}
|
||||
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_osu_o;
|
||||
|
||||
public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => new OsuScoreProcessor(hitObjectCount);
|
||||
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount = 0) => new OsuScoreProcessor(hitObjectCount);
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new OsuDifficultyCalculator(beatmap);
|
||||
|
||||
public override Score CreateAutoplayScore(Beatmap beatmap)
|
||||
{
|
||||
var score = CreateScoreProcessor().GetScore();
|
||||
score.Replay = new OsuAutoReplay(beatmap);
|
||||
return score;
|
||||
}
|
||||
|
||||
protected override PlayMode PlayMode => PlayMode.Osu;
|
||||
|
||||
public override string Description => "osu!";
|
||||
|
||||
public override IEnumerable<KeyCounter> CreateGameplayKeys() => new KeyCounter[]
|
||||
{
|
||||
new KeyCounterKeyboard(Key.Z),
|
||||
new KeyCounterKeyboard(Key.X),
|
||||
new KeyCounterMouse(MouseButton.Left),
|
||||
new KeyCounterMouse(MouseButton.Right)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
class OsuScore : Score
|
||||
internal class OsuScore : Score
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,13 @@ using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Modes.Osu
|
||||
{
|
||||
class OsuScoreProcessor : ScoreProcessor
|
||||
internal class OsuScoreProcessor : ScoreProcessor
|
||||
{
|
||||
public OsuScoreProcessor(int hitObjectCount)
|
||||
public OsuScoreProcessor(int hitObjectCount = 0)
|
||||
: base(hitObjectCount)
|
||||
{
|
||||
Health.Value = 1;
|
||||
Accuracy.Value = 1;
|
||||
}
|
||||
|
||||
protected override void UpdateCalculations(JudgementInfo judgement)
|
||||
@ -34,8 +35,9 @@ namespace osu.Game.Modes.Osu
|
||||
int score = 0;
|
||||
int maxScore = 0;
|
||||
|
||||
foreach (OsuJudgementInfo j in Judgements)
|
||||
foreach (var judgementInfo in Judgements)
|
||||
{
|
||||
var j = (OsuJudgementInfo)judgementInfo;
|
||||
score += j.ScoreValue;
|
||||
maxScore += j.MaxScoreValue;
|
||||
}
|
||||
|
@ -1,8 +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
|
||||
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Beatmaps;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using osu.Game.Modes.UI;
|
||||
@ -11,18 +12,28 @@ namespace osu.Game.Modes.Osu.UI
|
||||
{
|
||||
public class OsuHitRenderer : HitRenderer<OsuHitObject>
|
||||
{
|
||||
protected override HitObjectConverter<OsuHitObject> Converter => new OsuHitObjectConverter();
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuPlayfield();
|
||||
|
||||
protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h)
|
||||
public OsuHitRenderer(Beatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
if (h is HitCircle)
|
||||
return new DrawableHitCircle(h as HitCircle);
|
||||
if (h is Slider)
|
||||
return new DrawableSlider(h as Slider);
|
||||
if (h is Spinner)
|
||||
return new DrawableSpinner(h as Spinner);
|
||||
}
|
||||
|
||||
protected override IBeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter();
|
||||
|
||||
protected override Playfield<OsuHitObject> CreatePlayfield() => new OsuPlayfield();
|
||||
|
||||
protected override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h)
|
||||
{
|
||||
var circle = h as HitCircle;
|
||||
if (circle != null)
|
||||
return new DrawableHitCircle(circle);
|
||||
|
||||
var slider = h as Slider;
|
||||
if (slider != null)
|
||||
return new DrawableSlider(slider);
|
||||
|
||||
var spinner = h as Spinner;
|
||||
if (spinner != null)
|
||||
return new DrawableSpinner(spinner);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,12 @@ using osu.Game.Modes.Osu.Objects.Drawables;
|
||||
using osu.Game.Modes.Osu.Objects.Drawables.Connections;
|
||||
using osu.Game.Modes.UI;
|
||||
using System.Linq;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Osu.UI
|
||||
{
|
||||
public class OsuPlayfield : Playfield
|
||||
public class OsuPlayfield : Playfield<OsuHitObject>
|
||||
{
|
||||
private Container approachCircles;
|
||||
private Container judgementLayer;
|
||||
@ -30,7 +32,7 @@ namespace osu.Game.Modes.Osu.UI
|
||||
}
|
||||
}
|
||||
|
||||
public OsuPlayfield()
|
||||
public OsuPlayfield() : base(512)
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
@ -53,11 +55,17 @@ namespace osu.Game.Modes.Osu.UI
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = -1,
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public override void Add(DrawableHitObject h)
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
AddInternal(new OsuCursorContainer { Colour = Color4.LightYellow });
|
||||
}
|
||||
|
||||
public override void Add(DrawableHitObject<OsuHitObject> h)
|
||||
{
|
||||
h.Depth = (float)h.HitObject.StartTime;
|
||||
IDrawableHitObjectWithProxiedApproach c = h as IDrawableHitObjectWithProxiedApproach;
|
||||
@ -74,13 +82,13 @@ namespace osu.Game.Modes.Osu.UI
|
||||
public override void PostProcess()
|
||||
{
|
||||
connectionLayer.HitObjects = HitObjects.Children
|
||||
.Select(d => (OsuHitObject)d.HitObject)
|
||||
.Select(d => d.HitObject)
|
||||
.OrderBy(h => h.StartTime);
|
||||
}
|
||||
|
||||
private void judgement(DrawableHitObject h, JudgementInfo j)
|
||||
private void judgement(DrawableHitObject<OsuHitObject> h, JudgementInfo j)
|
||||
{
|
||||
HitExplosion explosion = new HitExplosion((OsuJudgementInfo)j, (OsuHitObject)h.HitObject);
|
||||
HitExplosion explosion = new HitExplosion((OsuJudgementInfo)j, h.HitObject);
|
||||
|
||||
judgementLayer.Add(explosion);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
@ -43,6 +43,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Beatmaps\OsuBeatmapConverter.cs" />
|
||||
<Compile Include="Objects\BezierApproximator.cs" />
|
||||
<Compile Include="Objects\CircularArcApproximator.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableOsuHitObject.cs" />
|
||||
@ -70,21 +71,20 @@
|
||||
<Compile Include="Objects\OsuHitObjectParser.cs" />
|
||||
<Compile Include="Objects\SliderCurve.cs" />
|
||||
<Compile Include="Objects\SliderTick.cs" />
|
||||
<Compile Include="OsuAutoReplay.cs" />
|
||||
<Compile Include="OsuDifficultyCalculator.cs" />
|
||||
<Compile Include="OsuScore.cs" />
|
||||
<Compile Include="OsuScoreProcessor.cs" />
|
||||
<Compile Include="UI\OsuComboCounter.cs" />
|
||||
<Compile Include="UI\OsuHitRenderer.cs" />
|
||||
<Compile Include="UI\OsuPlayfield.cs" />
|
||||
<Compile Include="OsuRuleset.cs" />
|
||||
<Compile Include="Objects\HitCircle.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableHitCircle.cs" />
|
||||
<Compile Include="Objects\OsuHitObject.cs" />
|
||||
<Compile Include="Objects\OsuHitObjectConverter.cs" />
|
||||
<Compile Include="Objects\Slider.cs" />
|
||||
<Compile Include="Objects\Spinner.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UI\OsuScoreOverlay.cs" />
|
||||
<Compile Include="OsuMod.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
20
osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs
Normal file
20
osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.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.Game.Beatmaps;
|
||||
using osu.Game.Modes.Taiko.Objects;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Beatmaps
|
||||
{
|
||||
internal class TaikoBeatmapConverter : IBeatmapConverter<TaikoBaseHit>
|
||||
{
|
||||
public Beatmap<TaikoBaseHit> Convert(Beatmap original)
|
||||
{
|
||||
return new Beatmap<TaikoBaseHit>(original)
|
||||
{
|
||||
HitObjects = new List<TaikoBaseHit>() // Todo: Implement
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||
{
|
||||
class DrawableTaikoHit : Sprite
|
||||
internal class DrawableTaikoHit : Sprite
|
||||
{
|
||||
private TaikoBaseHit h;
|
||||
|
||||
|
@ -8,7 +8,7 @@ using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Modes.Taiko.Objects
|
||||
{
|
||||
class TaikoConverter : HitObjectConverter<TaikoBaseHit>
|
||||
internal class TaikoConverter : HitObjectConverter<TaikoBaseHit>
|
||||
{
|
||||
public override List<TaikoBaseHit> Convert(Beatmap beatmap)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user