mirror of
https://github.com/osukey/osukey.git
synced 2025-08-06 08:03:52 +09:00
Merge remote-tracking branch 'origin/master' into taiko-drawable-generation
Conflicts: osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj
This commit is contained in:
Submodule osu-framework updated: fee17db537...1c08c1fec4
Submodule osu-resources updated: e674531595...12bbab717d
@ -13,10 +13,10 @@ using osu.Game.Modes.Taiko;
|
|||||||
namespace osu.Desktop.Tests
|
namespace osu.Desktop.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class BenchmarkTest
|
public class VisualTests
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void TestBenchmark()
|
public void TestVisualTests()
|
||||||
{
|
{
|
||||||
using (var host = new HeadlessGameHost())
|
using (var host = new HeadlessGameHost())
|
||||||
{
|
{
|
||||||
@ -25,7 +25,7 @@ namespace osu.Desktop.Tests
|
|||||||
Ruleset.Register(new ManiaRuleset());
|
Ruleset.Register(new ManiaRuleset());
|
||||||
Ruleset.Register(new CatchRuleset());
|
Ruleset.Register(new CatchRuleset());
|
||||||
|
|
||||||
host.Run(new Benchmark());
|
host.Run(new AutomatedVisualTestGame());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -56,7 +56,7 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BenchmarkTest.cs" />
|
<Compile Include="VisualTests.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu-framework\osu.Framework.Desktop\osu.Framework.Desktop.csproj">
|
<ProjectReference Include="..\osu-framework\osu.Framework.Desktop\osu.Framework.Desktop.csproj">
|
||||||
|
20
osu.Desktop.VisualTests/AutomatedVisualTestGame.cs
Normal file
20
osu.Desktop.VisualTests/AutomatedVisualTestGame.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game;
|
||||||
|
|
||||||
|
namespace osu.Desktop.VisualTests
|
||||||
|
{
|
||||||
|
public class AutomatedVisualTestGame : OsuGameBase
|
||||||
|
{
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
// Have to construct this here, rather than in the constructor, because
|
||||||
|
// we depend on some dependencies to be loaded within OsuGameBase.load().
|
||||||
|
Add(new TestRunner(new TestBrowser()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game;
|
|
||||||
|
|
||||||
namespace osu.Desktop.VisualTests
|
|
||||||
{
|
|
||||||
public class Benchmark : OsuGameBase
|
|
||||||
{
|
|
||||||
private const double time_per_test = 200;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
Host.MaximumDrawHz = int.MaxValue;
|
|
||||||
Host.MaximumUpdateHz = int.MaxValue;
|
|
||||||
Host.MaximumInactiveHz = int.MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
TestBrowser f = new TestBrowser();
|
|
||||||
Add(f);
|
|
||||||
|
|
||||||
Console.WriteLine($@"{Time}: Running {f.TestCount} tests for {time_per_test}ms each...");
|
|
||||||
|
|
||||||
for (int i = 1; i < f.TestCount; i++)
|
|
||||||
{
|
|
||||||
int loadableCase = i;
|
|
||||||
Scheduler.AddDelayed(delegate
|
|
||||||
{
|
|
||||||
f.LoadTest(loadableCase);
|
|
||||||
Console.WriteLine($@"{Time}: Switching to test #{loadableCase}");
|
|
||||||
}, loadableCase * time_per_test);
|
|
||||||
}
|
|
||||||
|
|
||||||
Scheduler.AddDelayed(Host.Exit, f.TestCount * time_per_test);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,7 +27,7 @@ namespace osu.Desktop.VisualTests
|
|||||||
Ruleset.Register(new CatchRuleset());
|
Ruleset.Register(new CatchRuleset());
|
||||||
|
|
||||||
if (benchmark)
|
if (benchmark)
|
||||||
host.Run(new Benchmark());
|
host.Run(new AutomatedVisualTestGame());
|
||||||
else
|
else
|
||||||
host.Run(new VisualTestGame());
|
host.Run(new VisualTestGame());
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
|
|
||||||
Add(overlay);
|
Add(overlay);
|
||||||
|
|
||||||
AddButton(@"Toggle", overlay.ToggleVisibility);
|
AddStep(@"Toggle", overlay.ToggleVisibility);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
|
|
||||||
Add(overlay = new DialogOverlay());
|
Add(overlay = new DialogOverlay());
|
||||||
|
|
||||||
AddButton("dialog #1", () => overlay.Push(new PopupDialog
|
AddStep("dialog #1", () => overlay.Push(new PopupDialog
|
||||||
{
|
{
|
||||||
Icon = FontAwesome.fa_trash_o,
|
Icon = FontAwesome.fa_trash_o,
|
||||||
HeaderText = @"Confirm deletion of",
|
HeaderText = @"Confirm deletion of",
|
||||||
@ -40,7 +40,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
AddButton("dialog #2", () => overlay.Push(new PopupDialog
|
AddStep("dialog #2", () => overlay.Push(new PopupDialog
|
||||||
{
|
{
|
||||||
Icon = FontAwesome.fa_gear,
|
Icon = FontAwesome.fa_gear,
|
||||||
HeaderText = @"What do you want to do with",
|
HeaderText = @"What do you want to do with",
|
||||||
|
@ -93,19 +93,28 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
|
|
||||||
playbackSpeed.TriggerChange();
|
playbackSpeed.TriggerChange();
|
||||||
|
|
||||||
AddButton(@"circles", () => load(HitObjectType.Circle));
|
AddStep(@"circles", () => load(HitObjectType.Circle));
|
||||||
AddButton(@"slider", () => load(HitObjectType.Slider));
|
AddStep(@"slider", () => load(HitObjectType.Slider));
|
||||||
AddButton(@"spinner", () => load(HitObjectType.Spinner));
|
AddStep(@"spinner", () => load(HitObjectType.Spinner));
|
||||||
|
|
||||||
AddToggle(@"auto", state => { auto = state; load(mode); });
|
AddToggleStep(@"auto", state => { auto = state; load(mode); });
|
||||||
|
|
||||||
ButtonsContainer.Add(new SpriteText { Text = "Playback Speed" });
|
Add(new Container
|
||||||
ButtonsContainer.Add(new BasicSliderBar<double>
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new SpriteText { Text = "Playback Speed" },
|
||||||
|
new BasicSliderBar<double>
|
||||||
{
|
{
|
||||||
Width = 150,
|
Width = 150,
|
||||||
Height = 10,
|
Height = 10,
|
||||||
SelectionColor = Color4.Orange,
|
SelectionColor = Color4.Orange,
|
||||||
Bindable = playbackSpeed
|
Bindable = playbackSpeed
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
framedClock.ProcessFrame();
|
framedClock.ProcessFrame();
|
||||||
|
@ -6,6 +6,7 @@ using osu.Framework.Graphics;
|
|||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.MathUtils;
|
using osu.Framework.MathUtils;
|
||||||
@ -37,19 +38,30 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
};
|
};
|
||||||
BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 };
|
BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 };
|
||||||
bindable.ValueChanged += delegate { kc.FadeTime = bindable.Value; };
|
bindable.ValueChanged += delegate { kc.FadeTime = bindable.Value; };
|
||||||
AddButton("Add Random", () =>
|
AddStep("Add Random", () =>
|
||||||
{
|
{
|
||||||
Key key = (Key)((int)Key.A + RNG.Next(26));
|
Key key = (Key)((int)Key.A + RNG.Next(26));
|
||||||
kc.Add(new KeyCounterKeyboard(key));
|
kc.Add(new KeyCounterKeyboard(key));
|
||||||
});
|
});
|
||||||
ButtonsContainer.Add(new SpriteText { Text = "FadeTime" });
|
|
||||||
ButtonsContainer.Add(new TestSliderBar<int>
|
Add(new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new SpriteText { Text = "FadeTime" },
|
||||||
|
new TestSliderBar<int>
|
||||||
{
|
{
|
||||||
Width = 150,
|
Width = 150,
|
||||||
Height = 10,
|
Height = 10,
|
||||||
SelectionColor = Color4.Orange,
|
SelectionColor = Color4.Orange,
|
||||||
Bindable = bindable
|
Bindable = bindable
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(kc);
|
Add(kc);
|
||||||
}
|
}
|
||||||
private class TestSliderBar<T> : SliderBar<T> where T : struct
|
private class TestSliderBar<T> : SliderBar<T> where T : struct
|
||||||
|
@ -218,7 +218,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
Size = new Vector2(550f, 450f),
|
Size = new Vector2(550f, 450f),
|
||||||
});
|
});
|
||||||
|
|
||||||
AddButton(@"New Scores", newScores);
|
AddStep(@"New Scores", newScores);
|
||||||
newScores();
|
newScores();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,11 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
Anchor = Anchor.BottomCentre,
|
Anchor = Anchor.BottomCentre,
|
||||||
});
|
});
|
||||||
|
|
||||||
AddButton("Toggle", modSelect.ToggleVisibility);
|
AddStep("Toggle", modSelect.ToggleVisibility);
|
||||||
AddButton("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu);
|
AddStep("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu);
|
||||||
AddButton("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko);
|
AddStep("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko);
|
||||||
AddButton("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch);
|
AddStep("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch);
|
||||||
AddButton("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania);
|
AddStep("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
Anchor = Anchor.Centre
|
Anchor = Anchor.Centre
|
||||||
};
|
};
|
||||||
Add(mc);
|
Add(mc);
|
||||||
AddToggle(@"Show", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
|
AddToggleStep(@"Show", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,13 +30,13 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
});
|
});
|
||||||
|
|
||||||
AddToggle(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
|
AddToggleStep(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
|
||||||
|
|
||||||
AddButton(@"simple #1", sendNotification1);
|
AddStep(@"simple #1", sendNotification1);
|
||||||
AddButton(@"simple #2", sendNotification2);
|
AddStep(@"simple #2", sendNotification2);
|
||||||
AddButton(@"progress #1", sendProgress1);
|
AddStep(@"progress #1", sendProgress1);
|
||||||
AddButton(@"progress #2", sendProgress2);
|
AddStep(@"progress #2", sendProgress2);
|
||||||
AddButton(@"barrage", () => sendBarrage());
|
AddStep(@"barrage", () => sendBarrage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendBarrage(int remaining = 100)
|
private void sendBarrage(int remaining = 100)
|
||||||
|
@ -25,8 +25,8 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
OnRetry = () => Logger.Log(@"Retry"),
|
OnRetry = () => Logger.Log(@"Retry"),
|
||||||
OnQuit = () => Logger.Log(@"Quit")
|
OnQuit = () => Logger.Log(@"Quit")
|
||||||
});
|
});
|
||||||
AddButton("Pause", pauseOverlay.Show);
|
AddStep("Pause", pauseOverlay.Show);
|
||||||
AddButton("Add Retry", delegate
|
AddStep("Add Retry", delegate
|
||||||
{
|
{
|
||||||
retryCount++;
|
retryCount++;
|
||||||
pauseOverlay.Retries = retryCount;
|
pauseOverlay.Retries = retryCount;
|
||||||
|
@ -23,12 +23,10 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
public override void Reset()
|
public override void Reset()
|
||||||
{
|
{
|
||||||
base.Reset();
|
base.Reset();
|
||||||
oldDb = Dependencies.Get<BeatmapDatabase>();
|
|
||||||
if (db == null)
|
if (db == null)
|
||||||
{
|
{
|
||||||
storage = new TestStorage(@"TestCasePlaySongSelect");
|
storage = new TestStorage(@"TestCasePlaySongSelect");
|
||||||
db = new BeatmapDatabase(storage);
|
db = new BeatmapDatabase(storage);
|
||||||
Dependencies.Cache(db, true);
|
|
||||||
|
|
||||||
var sets = new List<BeatmapSetInfo>();
|
var sets = new List<BeatmapSetInfo>();
|
||||||
|
|
||||||
@ -40,19 +38,16 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
|
|
||||||
Add(songSelect = new PlaySongSelect());
|
Add(songSelect = new PlaySongSelect());
|
||||||
|
|
||||||
AddButton(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
|
AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
|
||||||
AddButton(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
|
AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
|
||||||
AddButton(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
|
AddStep(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
|
||||||
AddButton(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
|
AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
if (oldDb != null)
|
if (oldDb != null)
|
||||||
{
|
|
||||||
Dependencies.Cache(oldDb, true);
|
|
||||||
db = null;
|
db = null;
|
||||||
}
|
|
||||||
|
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
};
|
};
|
||||||
Add(starsLabel);
|
Add(starsLabel);
|
||||||
|
|
||||||
AddButton(@"Reset all", delegate
|
AddStep(@"Reset all", delegate
|
||||||
{
|
{
|
||||||
score.Current.Value = 0;
|
score.Current.Value = 0;
|
||||||
comboCounter.Current.Value = 0;
|
comboCounter.Current.Value = 0;
|
||||||
@ -78,7 +78,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
starsLabel.Text = stars.Count.ToString("0.00");
|
starsLabel.Text = stars.Count.ToString("0.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
AddButton(@"Hit! :D", delegate
|
AddStep(@"Hit! :D", delegate
|
||||||
{
|
{
|
||||||
score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
|
score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
|
||||||
comboCounter.Increment();
|
comboCounter.Increment();
|
||||||
@ -86,20 +86,20 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
accuracyCounter.SetFraction(numerator, denominator);
|
accuracyCounter.SetFraction(numerator, denominator);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddButton(@"miss...", delegate
|
AddStep(@"miss...", delegate
|
||||||
{
|
{
|
||||||
comboCounter.Current.Value = 0;
|
comboCounter.Current.Value = 0;
|
||||||
denominator++;
|
denominator++;
|
||||||
accuracyCounter.SetFraction(numerator, denominator);
|
accuracyCounter.SetFraction(numerator, denominator);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddButton(@"Alter stars", delegate
|
AddStep(@"Alter stars", delegate
|
||||||
{
|
{
|
||||||
stars.Count = RNG.NextSingle() * (stars.StarCount + 1);
|
stars.Count = RNG.NextSingle() * (stars.StarCount + 1);
|
||||||
starsLabel.Text = stars.Count.ToString("0.00");
|
starsLabel.Text = stars.Count.ToString("0.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
AddButton(@"Stop counters", delegate
|
AddStep(@"Stop counters", delegate
|
||||||
{
|
{
|
||||||
score.StopRolling();
|
score.StopRolling();
|
||||||
comboCounter.StopRolling();
|
comboCounter.StopRolling();
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using osu.Framework.Allocation;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
||||||
|
|
||||||
namespace osu.Desktop.VisualTests.Tests
|
namespace osu.Desktop.VisualTests.Tests
|
||||||
@ -21,99 +20,93 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
{
|
{
|
||||||
base.Reset();
|
base.Reset();
|
||||||
|
|
||||||
AddToggle("Kiai", b =>
|
AddToggleStep("Kiai", b =>
|
||||||
{
|
{
|
||||||
kiai = !kiai;
|
kiai = !kiai;
|
||||||
Reset();
|
updateKiaiState();
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(new CentreHitCirclePiece(new CirclePiece
|
Add(new CirclePiece
|
||||||
{
|
{
|
||||||
KiaiMode = kiai
|
Position = new Vector2(100, 100),
|
||||||
})
|
Width = 0,
|
||||||
|
AccentColour = Color4.DarkRed,
|
||||||
|
KiaiMode = kiai,
|
||||||
|
Children = new[]
|
||||||
{
|
{
|
||||||
Position = new Vector2(100, 100)
|
new CentreHitSymbolPiece()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(new CentreHitCirclePiece(new StrongCirclePiece
|
Add(new StrongCirclePiece
|
||||||
{
|
{
|
||||||
KiaiMode = kiai
|
Position = new Vector2(350, 100),
|
||||||
})
|
Width = 0,
|
||||||
|
AccentColour = Color4.DarkRed,
|
||||||
|
KiaiMode = kiai,
|
||||||
|
Children = new[]
|
||||||
{
|
{
|
||||||
Position = new Vector2(350, 100)
|
new CentreHitSymbolPiece()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(new RimHitCirclePiece(new CirclePiece
|
Add(new CirclePiece
|
||||||
{
|
{
|
||||||
KiaiMode = kiai
|
Position = new Vector2(100, 300),
|
||||||
})
|
Width = 0,
|
||||||
|
AccentColour = Color4.DarkBlue,
|
||||||
|
KiaiMode = kiai,
|
||||||
|
Children = new[]
|
||||||
{
|
{
|
||||||
Position = new Vector2(100, 300)
|
new RimHitSymbolPiece()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(new RimHitCirclePiece(new StrongCirclePiece
|
Add(new StrongCirclePiece
|
||||||
{
|
{
|
||||||
KiaiMode = kiai
|
Position = new Vector2(350, 300),
|
||||||
})
|
Width = 0,
|
||||||
|
AccentColour = Color4.DarkBlue,
|
||||||
|
KiaiMode = kiai,
|
||||||
|
Children = new[]
|
||||||
{
|
{
|
||||||
Position = new Vector2(350, 300)
|
new RimHitSymbolPiece()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(new SwellCirclePiece(new CirclePiece
|
Add(new CirclePiece
|
||||||
{
|
{
|
||||||
KiaiMode = kiai
|
Position = new Vector2(100, 500),
|
||||||
})
|
Width = 0,
|
||||||
|
AccentColour = Color4.Orange,
|
||||||
|
KiaiMode = kiai,
|
||||||
|
Children = new[]
|
||||||
{
|
{
|
||||||
Position = new Vector2(100, 500)
|
new SwellSymbolPiece()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(new SwellCirclePiece(new StrongCirclePiece
|
Add(new CirclePiece
|
||||||
{
|
|
||||||
KiaiMode = kiai
|
|
||||||
})
|
|
||||||
{
|
|
||||||
Position = new Vector2(350, 500)
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new DrumRollCirclePiece(new CirclePiece
|
|
||||||
{
|
|
||||||
KiaiMode = kiai
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
|
Position = new Vector2(575, 100),
|
||||||
Width = 0.25f,
|
Width = 0.25f,
|
||||||
Position = new Vector2(575, 100)
|
AccentColour = Color4.Orange,
|
||||||
|
KiaiMode = kiai,
|
||||||
});
|
});
|
||||||
|
|
||||||
Add(new DrumRollCirclePiece(new StrongCirclePiece
|
Add(new StrongCirclePiece
|
||||||
{
|
|
||||||
KiaiMode = kiai
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
|
Position = new Vector2(575, 300),
|
||||||
Width = 0.25f,
|
Width = 0.25f,
|
||||||
Position = new Vector2(575, 300)
|
AccentColour = Color4.Orange,
|
||||||
|
KiaiMode = kiai
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SwellCircle : BaseCircle
|
private void updateKiaiState()
|
||||||
{
|
{
|
||||||
public SwellCircle(CirclePiece piece)
|
foreach (var c in Children.OfType<CirclePiece>())
|
||||||
: base(piece)
|
c.KiaiMode = kiai;
|
||||||
{
|
|
||||||
Piece.Add(new TextAwesome
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
TextSize = CirclePiece.SYMBOL_INNER_SIZE,
|
|
||||||
Icon = FontAwesome.fa_asterisk,
|
|
||||||
Shadow = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
Piece.AccentColour = colours.YellowDark;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class BaseCircle : Container
|
private abstract class BaseCircle : Container
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Primitives;
|
|
||||||
using osu.Framework.MathUtils;
|
using osu.Framework.MathUtils;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Modes.Objects.Drawables;
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
@ -24,21 +23,20 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
{
|
{
|
||||||
base.Reset();
|
base.Reset();
|
||||||
|
|
||||||
AddButton("Hit!", addHitJudgement);
|
AddStep("Hit!", addHitJudgement);
|
||||||
AddButton("Miss :(", addMissJudgement);
|
AddStep("Miss :(", addMissJudgement);
|
||||||
AddButton("DrumRoll", () => addDrumRoll(false));
|
AddStep("DrumRoll", () => addDrumRoll(false));
|
||||||
AddButton("Strong DrumRoll", () => addDrumRoll(true));
|
AddStep("Strong DrumRoll", () => addDrumRoll(true));
|
||||||
AddButton("Swell", addSwell);
|
AddStep("Swell", addSwell);
|
||||||
AddButton("Centre", () => addCentreHit(false));
|
AddStep("Centre", () => addCentreHit(false));
|
||||||
AddButton("Strong Centre", () => addCentreHit(true));
|
AddStep("Strong Centre", () => addCentreHit(true));
|
||||||
AddButton("Rim", () => addRimHit(false));
|
AddStep("Rim", () => addRimHit(false));
|
||||||
AddButton("Strong Rim", () => addRimHit(true));
|
AddStep("Strong Rim", () => addRimHit(true));
|
||||||
|
|
||||||
Add(new Container
|
Add(new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Y = 200,
|
Y = 200,
|
||||||
Padding = new MarginPadding { Left = 200 },
|
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
playfield = new TaikoPlayfield()
|
playfield = new TaikoPlayfield()
|
||||||
@ -58,7 +56,6 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
Result = HitResult.Hit,
|
Result = HitResult.Hit,
|
||||||
TaikoResult = hitResult,
|
TaikoResult = hitResult,
|
||||||
TimeOffset = 0,
|
TimeOffset = 0,
|
||||||
ComboAtHit = 1,
|
|
||||||
SecondHit = RNG.Next(10) == 0
|
SecondHit = RNG.Next(10) == 0
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -71,8 +68,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
Judgement = new TaikoJudgement
|
Judgement = new TaikoJudgement
|
||||||
{
|
{
|
||||||
Result = HitResult.Miss,
|
Result = HitResult.Miss,
|
||||||
TimeOffset = 0,
|
TimeOffset = 0
|
||||||
ComboAtHit = 0
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -92,7 +88,7 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
var d = new DrumRoll
|
var d = new DrumRoll
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + 1000,
|
StartTime = Time.Current + 1000,
|
||||||
Distance = 2000,
|
Distance = 20000,
|
||||||
PreEmpt = 1000,
|
PreEmpt = 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ namespace osu.Desktop.VisualTests
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
new BackgroundScreenDefault { Depth = 10 }.LoadAsync(this, AddInternal);
|
LoadComponentAsync(new BackgroundScreenDefault { Depth = 10 }, AddInternal);
|
||||||
|
|
||||||
// Have to construct this here, rather than in the constructor, because
|
// Have to construct this here, rather than in the constructor, because
|
||||||
// we depend on some dependencies to be loaded within OsuGameBase.load().
|
// we depend on some dependencies to be loaded within OsuGameBase.load().
|
||||||
@ -24,6 +24,11 @@ namespace osu.Desktop.VisualTests
|
|||||||
public override void SetHost(GameHost host)
|
public override void SetHost(GameHost host)
|
||||||
{
|
{
|
||||||
base.SetHost(host);
|
base.SetHost(host);
|
||||||
|
|
||||||
|
host.UpdateThread.InactiveHz = host.UpdateThread.ActiveHz;
|
||||||
|
host.DrawThread.InactiveHz = host.DrawThread.ActiveHz;
|
||||||
|
host.InputThread.InactiveHz = host.InputThread.ActiveHz;
|
||||||
|
|
||||||
host.Window.CursorState = CursorState.Hidden;
|
host.Window.CursorState = CursorState.Hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@
|
|||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Benchmark.cs" />
|
<Compile Include="AutomatedVisualTestGame.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Tests\TestCaseChatDisplay.cs" />
|
<Compile Include="Tests\TestCaseChatDisplay.cs" />
|
||||||
<Compile Include="Tests\TestCaseDrawings.cs" />
|
<Compile Include="Tests\TestCaseDrawings.cs" />
|
||||||
|
29
osu.Desktop/OpenTK.dll.config
Normal file
29
osu.Desktop/OpenTK.dll.config
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
-->
|
||||||
|
<configuration>
|
||||||
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||||
|
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||||
|
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||||
|
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||||
|
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||||
|
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||||
|
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||||
|
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||||
|
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||||
|
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||||
|
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||||
|
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||||
|
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||||
|
</configuration>
|
@ -29,7 +29,7 @@ namespace osu.Desktop
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
versionManager.LoadAsync(this);
|
LoadComponentAsync(versionManager);
|
||||||
ScreenChanged += s =>
|
ScreenChanged += s =>
|
||||||
{
|
{
|
||||||
if (!versionManager.IsAlive && s is Intro)
|
if (!versionManager.IsAlive && s is Intro)
|
||||||
|
@ -123,7 +123,10 @@
|
|||||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4" />
|
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||||
|
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1340\lib\net45\OpenTK.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
@ -150,6 +153,7 @@
|
|||||||
<None Include="..\osu.licenseheader">
|
<None Include="..\osu.licenseheader">
|
||||||
<Link>osu.licenseheader</Link>
|
<Link>osu.licenseheader</Link>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="OpenTK.dll.config" />
|
||||||
<None Include="osu!.res" />
|
<None Include="osu!.res" />
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
<None Include="Properties\app.manifest" />
|
<None Include="Properties\app.manifest" />
|
||||||
|
@ -7,6 +7,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
|||||||
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" />
|
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" />
|
||||||
<package id="Microsoft.Net.Http" version="2.2.29" 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="Mono.Cecil" version="0.9.6.4" targetFramework="net45" />
|
||||||
|
<package id="ppy.OpenTK" version="2.0.50727.1340" targetFramework="net45" />
|
||||||
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
||||||
<package id="squirrel.windows" version="1.5.2" targetFramework="net45" />
|
<package id="squirrel.windows" version="1.5.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -19,7 +19,7 @@ namespace osu.Game.Modes.Catch.Scoring
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewJugement(CatchJudgement judgement)
|
protected override void OnNewJudgement(CatchJudgement judgement)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Modes.Mania.Scoring
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewJugement(ManiaJudgement judgement)
|
protected override void OnNewJudgement(ManiaJudgement judgement)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
|
|||||||
Colour = AccentColour,
|
Colour = AccentColour,
|
||||||
Hit = () =>
|
Hit = () =>
|
||||||
{
|
{
|
||||||
if (Judgement.Result.HasValue) return false;
|
if (Judgement.Result != HitResult.None) return false;
|
||||||
|
|
||||||
Judgement.PositionOffset = Vector2.Zero; //todo: set to correct value
|
Judgement.PositionOffset = Vector2.Zero; //todo: set to correct value
|
||||||
UpdateJudgement(true);
|
UpdateJudgement(true);
|
||||||
|
@ -11,10 +11,11 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Modes.Objects.Types;
|
using osu.Game.Modes.Objects.Types;
|
||||||
|
using osu.Game.Modes.Replays;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Osu
|
namespace osu.Game.Modes.Osu
|
||||||
{
|
{
|
||||||
public class OsuAutoReplay : LegacyReplay
|
public class OsuAutoReplay : Replay
|
||||||
{
|
{
|
||||||
private static readonly Vector2 spinner_centre = new Vector2(256, 192);
|
private static readonly Vector2 spinner_centre = new Vector2(256, 192);
|
||||||
|
|
||||||
@ -29,17 +30,20 @@ namespace osu.Game.Modes.Osu
|
|||||||
createAutoReplay();
|
createAutoReplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LegacyReplayFrameComparer : IComparer<LegacyReplayFrame>
|
private class ReplayFrameComparer : IComparer<ReplayFrame>
|
||||||
{
|
{
|
||||||
public int Compare(LegacyReplayFrame f1, LegacyReplayFrame f2)
|
public int Compare(ReplayFrame f1, ReplayFrame f2)
|
||||||
{
|
{
|
||||||
|
if (f1 == null) throw new NullReferenceException($@"{nameof(f1)} cannot be null");
|
||||||
|
if (f2 == null) throw new NullReferenceException($@"{nameof(f2)} cannot be null");
|
||||||
|
|
||||||
return f1.Time.CompareTo(f2.Time);
|
return f1.Time.CompareTo(f2.Time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly IComparer<LegacyReplayFrame> replay_frame_comparer = new LegacyReplayFrameComparer();
|
private static readonly IComparer<ReplayFrame> replay_frame_comparer = new ReplayFrameComparer();
|
||||||
|
|
||||||
private int findInsertionIndex(LegacyReplayFrame frame)
|
private int findInsertionIndex(ReplayFrame frame)
|
||||||
{
|
{
|
||||||
int index = Frames.BinarySearch(frame, replay_frame_comparer);
|
int index = Frames.BinarySearch(frame, replay_frame_comparer);
|
||||||
|
|
||||||
@ -59,7 +63,7 @@ namespace osu.Game.Modes.Osu
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFrameToReplay(LegacyReplayFrame frame) => Frames.Insert(findInsertionIndex(frame), frame);
|
private void addFrameToReplay(ReplayFrame frame) => Frames.Insert(findInsertionIndex(frame), frame);
|
||||||
|
|
||||||
private static Vector2 circlePosition(double t, double radius) => new Vector2((float)(Math.Cos(t) * radius), (float)(Math.Sin(t) * radius));
|
private static Vector2 circlePosition(double t, double radius) => new Vector2((float)(Math.Cos(t) * radius), (float)(Math.Sin(t) * radius));
|
||||||
|
|
||||||
@ -74,9 +78,9 @@ namespace osu.Game.Modes.Osu
|
|||||||
|
|
||||||
EasingTypes preferredEasing = DelayedMovements ? EasingTypes.InOutCubic : EasingTypes.Out;
|
EasingTypes preferredEasing = DelayedMovements ? EasingTypes.InOutCubic : EasingTypes.Out;
|
||||||
|
|
||||||
addFrameToReplay(new LegacyReplayFrame(-100000, 256, 500, LegacyButtonState.None));
|
addFrameToReplay(new ReplayFrame(-100000, 256, 500, ReplayButtonState.None));
|
||||||
addFrameToReplay(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1500, 256, 500, LegacyButtonState.None));
|
addFrameToReplay(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1500, 256, 500, ReplayButtonState.None));
|
||||||
addFrameToReplay(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 256, 192, LegacyButtonState.None));
|
addFrameToReplay(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 256, 192, ReplayButtonState.None));
|
||||||
|
|
||||||
// We are using ApplyModsToRate and not ApplyModsToTime to counteract the speed up / slow down from HalfTime / DoubleTime so that we remain at a constant framerate of 60 fps.
|
// 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);
|
float frameDelay = (float)applyModsToRate(1000.0 / 60.0);
|
||||||
@ -106,18 +110,18 @@ namespace osu.Game.Modes.Osu
|
|||||||
//Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
|
//Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
|
||||||
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||||
{
|
{
|
||||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None));
|
||||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, ReplayButtonState.None));
|
||||||
}
|
}
|
||||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||||
{
|
{
|
||||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None));
|
||||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, ReplayButtonState.None));
|
||||||
}
|
}
|
||||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
|
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
|
||||||
{
|
{
|
||||||
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
|
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None));
|
||||||
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, LegacyButtonState.None));
|
if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, ReplayButtonState.None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,13 +177,13 @@ namespace osu.Game.Modes.Osu
|
|||||||
// Do some nice easing for cursor movements
|
// Do some nice easing for cursor movements
|
||||||
if (Frames.Count > 0)
|
if (Frames.Count > 0)
|
||||||
{
|
{
|
||||||
LegacyReplayFrame lastFrame = Frames[Frames.Count - 1];
|
ReplayFrame lastFrame = Frames[Frames.Count - 1];
|
||||||
|
|
||||||
// Wait until Auto could "see and react" to the next note.
|
// Wait until Auto could "see and react" to the next note.
|
||||||
double waitTime = h.StartTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime);
|
double waitTime = h.StartTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime);
|
||||||
if (waitTime > lastFrame.Time)
|
if (waitTime > lastFrame.Time)
|
||||||
{
|
{
|
||||||
lastFrame = new LegacyReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState);
|
lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState);
|
||||||
addFrameToReplay(lastFrame);
|
addFrameToReplay(lastFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +200,7 @@ namespace osu.Game.Modes.Osu
|
|||||||
for (double time = lastFrame.Time + frameDelay; time < h.StartTime; time += frameDelay)
|
for (double time = lastFrame.Time + frameDelay; time < h.StartTime; time += frameDelay)
|
||||||
{
|
{
|
||||||
Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPosition, lastFrame.Time, h.StartTime, easing);
|
Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPosition, lastFrame.Time, h.StartTime, easing);
|
||||||
addFrameToReplay(new LegacyReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState));
|
addFrameToReplay(new ReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState));
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonIndex = 0;
|
buttonIndex = 0;
|
||||||
@ -207,12 +211,12 @@ namespace osu.Game.Modes.Osu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LegacyButtonState button = buttonIndex % 2 == 0 ? LegacyButtonState.Left1 : LegacyButtonState.Right1;
|
ReplayButtonState button = buttonIndex % 2 == 0 ? ReplayButtonState.Left1 : ReplayButtonState.Right1;
|
||||||
|
|
||||||
double hEndTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
|
double hEndTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
|
||||||
|
|
||||||
LegacyReplayFrame newFrame = new LegacyReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button);
|
ReplayFrame newFrame = new ReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button);
|
||||||
LegacyReplayFrame endFrame = new LegacyReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, LegacyButtonState.None);
|
ReplayFrame endFrame = new ReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, ReplayButtonState.None);
|
||||||
|
|
||||||
// Decrement because we want the previous frame, not the next one
|
// Decrement because we want the previous frame, not the next one
|
||||||
int index = findInsertionIndex(newFrame) - 1;
|
int index = findInsertionIndex(newFrame) - 1;
|
||||||
@ -220,19 +224,19 @@ namespace osu.Game.Modes.Osu
|
|||||||
// Do we have a previous frame? No need to check for < replay.Count since we decremented!
|
// Do we have a previous frame? No need to check for < replay.Count since we decremented!
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
LegacyReplayFrame previousFrame = Frames[index];
|
ReplayFrame previousFrame = Frames[index];
|
||||||
var previousButton = previousFrame.ButtonState;
|
var previousButton = previousFrame.ButtonState;
|
||||||
|
|
||||||
// If a button is already held, then we simply alternate
|
// If a button is already held, then we simply alternate
|
||||||
if (previousButton != LegacyButtonState.None)
|
if (previousButton != ReplayButtonState.None)
|
||||||
{
|
{
|
||||||
Debug.Assert(previousButton != (LegacyButtonState.Left1 | LegacyButtonState.Right1));
|
Debug.Assert(previousButton != (ReplayButtonState.Left1 | ReplayButtonState.Right1));
|
||||||
|
|
||||||
// Force alternation if we have the same button. Otherwise we can just keep the naturally to us assigned button.
|
// Force alternation if we have the same button. Otherwise we can just keep the naturally to us assigned button.
|
||||||
if (previousButton == button)
|
if (previousButton == button)
|
||||||
{
|
{
|
||||||
button = (LegacyButtonState.Left1 | LegacyButtonState.Right1) & ~button;
|
button = (ReplayButtonState.Left1 | ReplayButtonState.Right1) & ~button;
|
||||||
newFrame.SetButtonStates(button);
|
newFrame.ButtonState = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We always follow the most recent slider / spinner, so remove any other frames that occur while it exists.
|
// We always follow the most recent slider / spinner, so remove any other frames that occur while it exists.
|
||||||
@ -246,7 +250,7 @@ namespace osu.Game.Modes.Osu
|
|||||||
{
|
{
|
||||||
// Don't affect frames which stop pressing a button!
|
// Don't affect frames which stop pressing a button!
|
||||||
if (j < Frames.Count - 1 || Frames[j].ButtonState == previousButton)
|
if (j < Frames.Count - 1 || Frames[j].ButtonState == previousButton)
|
||||||
Frames[j].SetButtonStates(button);
|
Frames[j].ButtonState = button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,13 +274,13 @@ namespace osu.Game.Modes.Osu
|
|||||||
t = applyModsToTime(j - h.StartTime) * spinnerDirection;
|
t = applyModsToTime(j - h.StartTime) * spinnerDirection;
|
||||||
|
|
||||||
Vector2 pos = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
|
Vector2 pos = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
|
||||||
addFrameToReplay(new LegacyReplayFrame((int)j, pos.X, pos.Y, button));
|
addFrameToReplay(new ReplayFrame((int)j, pos.X, pos.Y, button));
|
||||||
}
|
}
|
||||||
|
|
||||||
t = applyModsToTime(s.EndTime - h.StartTime) * spinnerDirection;
|
t = applyModsToTime(s.EndTime - h.StartTime) * spinnerDirection;
|
||||||
Vector2 endPosition = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
|
Vector2 endPosition = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
|
||||||
|
|
||||||
addFrameToReplay(new LegacyReplayFrame(s.EndTime, endPosition.X, endPosition.Y, button));
|
addFrameToReplay(new ReplayFrame(s.EndTime, endPosition.X, endPosition.Y, button));
|
||||||
|
|
||||||
endFrame.MouseX = endPosition.X;
|
endFrame.MouseX = endPosition.X;
|
||||||
endFrame.MouseY = endPosition.Y;
|
endFrame.MouseY = endPosition.Y;
|
||||||
@ -288,10 +292,10 @@ namespace osu.Game.Modes.Osu
|
|||||||
for (double j = frameDelay; j < s.Duration; j += frameDelay)
|
for (double j = frameDelay; j < s.Duration; j += frameDelay)
|
||||||
{
|
{
|
||||||
Vector2 pos = s.PositionAt(j / s.Duration);
|
Vector2 pos = s.PositionAt(j / s.Duration);
|
||||||
addFrameToReplay(new LegacyReplayFrame(h.StartTime + j, pos.X, pos.Y, button));
|
addFrameToReplay(new ReplayFrame(h.StartTime + j, pos.X, pos.Y, button));
|
||||||
}
|
}
|
||||||
|
|
||||||
addFrameToReplay(new LegacyReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button));
|
addFrameToReplay(new ReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed!
|
// 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!
|
||||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Modes.Osu.Scoring
|
|||||||
Accuracy.Value = 1;
|
Accuracy.Value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewJugement(OsuJudgement judgement)
|
protected override void OnNewJudgement(OsuJudgement judgement)
|
||||||
{
|
{
|
||||||
if (judgement != null)
|
if (judgement != null)
|
||||||
{
|
{
|
||||||
|
@ -74,14 +74,23 @@ namespace osu.Game.Modes.Taiko.Beatmaps
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
HitType type = (sample & ~(SampleType.Finish | SampleType.Normal)) == 0 ? HitType.Centre : HitType.Rim;
|
bool isCentre = (sample & ~(SampleType.Finish | SampleType.Normal)) == 0;
|
||||||
|
|
||||||
return new Hit
|
if (isCentre)
|
||||||
|
{
|
||||||
|
return new CentreHit
|
||||||
|
{
|
||||||
|
StartTime = original.StartTime,
|
||||||
|
Sample = original.Sample,
|
||||||
|
IsStrong = strong
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RimHit
|
||||||
{
|
{
|
||||||
StartTime = original.StartTime,
|
StartTime = original.StartTime,
|
||||||
Sample = original.Sample,
|
Sample = original.Sample,
|
||||||
IsStrong = strong,
|
IsStrong = strong,
|
||||||
Type = type
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ namespace osu.Game.Modes.Taiko.Judgements
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this Judgement has a secondary hit in the case of finishers.
|
/// Whether this Judgement has a secondary hit in the case of finishers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool SecondHit;
|
public virtual bool SecondHit { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the numeric result value for the combo portion of the score.
|
/// Computes the numeric result value for the combo portion of the score.
|
||||||
|
25
osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs
Normal file
25
osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Game.Modes.Judgements;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.Judgements
|
||||||
|
{
|
||||||
|
public class TaikoStrongHitJudgement : TaikoJudgement, IPartialJudgement
|
||||||
|
{
|
||||||
|
public bool Changed { get; set; }
|
||||||
|
|
||||||
|
public override bool SecondHit
|
||||||
|
{
|
||||||
|
get { return base.SecondHit; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (base.SecondHit == value)
|
||||||
|
return;
|
||||||
|
base.SecondHit = value;
|
||||||
|
|
||||||
|
Changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using osu.Framework.Input;
|
|
||||||
using osu.Game.Input.Handlers;
|
|
||||||
using OpenTK.Input;
|
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko
|
|
||||||
{
|
|
||||||
public class LegacyTaikoReplay : LegacyReplay
|
|
||||||
{
|
|
||||||
protected LegacyTaikoReplay()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public LegacyTaikoReplay(StreamReader reader)
|
|
||||||
: base(reader)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ReplayInputHandler CreateInputHandler() => new LegacyTaikoReplayInputHandler(Frames);
|
|
||||||
|
|
||||||
private class LegacyTaikoReplayInputHandler : LegacyReplayInputHandler
|
|
||||||
{
|
|
||||||
public LegacyTaikoReplayInputHandler(List<LegacyReplayFrame> replayContent)
|
|
||||||
: base(replayContent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override List<InputState> GetPendingStates() => new List<InputState>
|
|
||||||
{
|
|
||||||
new InputState
|
|
||||||
{
|
|
||||||
Keyboard = new ReplayKeyboardState(new List<Key>(new[]
|
|
||||||
{
|
|
||||||
CurrentFrame?.MouseRight1 == true ? Key.F : Key.Unknown,
|
|
||||||
CurrentFrame?.MouseRight2 == true ? Key.J : Key.Unknown,
|
|
||||||
CurrentFrame?.MouseLeft1 == true ? Key.D : Key.Unknown,
|
|
||||||
CurrentFrame?.MouseLeft2 == true ? Key.K : Key.Unknown
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,6 +5,8 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Modes.Mods;
|
using osu.Game.Modes.Mods;
|
||||||
using osu.Game.Modes.Scoring;
|
using osu.Game.Modes.Scoring;
|
||||||
using osu.Game.Modes.Taiko.Objects;
|
using osu.Game.Modes.Taiko.Objects;
|
||||||
|
using osu.Game.Modes.Taiko.Replays;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Mods
|
namespace osu.Game.Modes.Taiko.Mods
|
||||||
{
|
{
|
||||||
@ -69,6 +71,7 @@ namespace osu.Game.Modes.Taiko.Mods
|
|||||||
{
|
{
|
||||||
protected override Score CreateReplayScore(Beatmap<TaikoHitObject> beatmap) => new Score
|
protected override Score CreateReplayScore(Beatmap<TaikoHitObject> beatmap) => new Score
|
||||||
{
|
{
|
||||||
|
User = new User { Username = "mekkadosu!" },
|
||||||
Replay = new TaikoAutoReplay(beatmap)
|
Replay = new TaikoAutoReplay(beatmap)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,7 @@
|
|||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects
|
namespace osu.Game.Modes.Taiko.Objects
|
||||||
{
|
{
|
||||||
/// <summary>
|
public class CentreHit : Hit
|
||||||
/// Describes whether a hit is a centre-hit or a rim-hit.
|
|
||||||
/// </summary>
|
|
||||||
public enum HitType
|
|
||||||
{
|
{
|
||||||
Centre,
|
|
||||||
Rim
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,20 +1,35 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||||
{
|
{
|
||||||
public class DrawableCentreHit : DrawableHit
|
public class DrawableCentreHit : DrawableHit
|
||||||
{
|
{
|
||||||
protected override List<Key> HitKeys { get; } = new List<Key>(new[] { Key.F, Key.J });
|
protected override Key[] HitKeys { get; } = { Key.F, Key.J };
|
||||||
|
|
||||||
|
private readonly CirclePiece circlePiece;
|
||||||
|
|
||||||
public DrawableCentreHit(Hit hit)
|
public DrawableCentreHit(Hit hit)
|
||||||
: base(hit)
|
: base(hit)
|
||||||
{
|
{
|
||||||
Add(new CentreHitCirclePiece(new CirclePiece()));
|
Add(circlePiece = new CirclePiece
|
||||||
|
{
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new CentreHitSymbolPiece()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
circlePiece.AccentColour = colours.PinkDarker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Modes.Objects.Drawables;
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
using osu.Game.Modes.Taiko.Judgements;
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
||||||
@ -11,9 +16,21 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
{
|
{
|
||||||
public class DrawableDrumRoll : DrawableTaikoHitObject
|
public class DrawableDrumRoll : DrawableTaikoHitObject
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Number of rolling hits required to reach the dark/final accent colour.
|
||||||
|
/// </summary>
|
||||||
|
private const int rolling_hits_for_dark_accent = 5;
|
||||||
|
|
||||||
private readonly DrumRoll drumRoll;
|
private readonly DrumRoll drumRoll;
|
||||||
|
|
||||||
private readonly DrumRollCirclePiece circle;
|
private readonly CirclePiece circle;
|
||||||
|
|
||||||
|
private Color4 accentDarkColour;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rolling number of tick hits. This increases for hits and decreases for misses.
|
||||||
|
/// </summary>
|
||||||
|
private int rollingHits;
|
||||||
|
|
||||||
public DrawableDrumRoll(DrumRoll drumRoll)
|
public DrawableDrumRoll(DrumRoll drumRoll)
|
||||||
: base(drumRoll)
|
: base(drumRoll)
|
||||||
@ -23,7 +40,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Width = (float)(drumRoll.Duration / drumRoll.PreEmpt);
|
Width = (float)(drumRoll.Duration / drumRoll.PreEmpt);
|
||||||
|
|
||||||
Add(circle = new DrumRollCirclePiece(CreateCirclePiece()));
|
Add(circle = CreateCirclePiece());
|
||||||
|
|
||||||
foreach (var tick in drumRoll.Ticks)
|
foreach (var tick in drumRoll.Ticks)
|
||||||
{
|
{
|
||||||
@ -39,10 +56,11 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onTickJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> obj)
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
int countHit = NestedHitObjects.Count(o => o.Judgement.Result == HitResult.Hit);
|
circle.AccentColour = AccentColour = colours.YellowDark;
|
||||||
circle.Completion = (float)countHit / NestedHitObjects.Count();
|
accentDarkColour = colours.YellowDarker;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -56,6 +74,19 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
LifetimeEnd = drumRoll.EndTime + drumRoll.PreEmpt;
|
LifetimeEnd = drumRoll.EndTime + drumRoll.PreEmpt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onTickJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> obj)
|
||||||
|
{
|
||||||
|
if (obj.Judgement.Result == HitResult.Hit)
|
||||||
|
rollingHits++;
|
||||||
|
else
|
||||||
|
rollingHits--;
|
||||||
|
|
||||||
|
rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_dark_accent);
|
||||||
|
|
||||||
|
Color4 newAccent = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_dark_accent, AccentColour, accentDarkColour, 0, 1);
|
||||||
|
circle.FadeAccent(newAccent, 100);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void CheckJudgement(bool userTriggered)
|
protected override void CheckJudgement(bool userTriggered)
|
||||||
{
|
{
|
||||||
if (userTriggered)
|
if (userTriggered)
|
||||||
|
@ -99,7 +99,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
|
|
||||||
protected override bool HandleKeyPress(Key key)
|
protected override bool HandleKeyPress(Key key)
|
||||||
{
|
{
|
||||||
return !Judgement.Result.HasValue && UpdateJudgement(true);
|
return Judgement.Result == HitResult.None && UpdateJudgement(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Game.Modes.Objects.Drawables;
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
using osu.Game.Modes.Taiko.Judgements;
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Linq;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||||
{
|
{
|
||||||
@ -16,7 +16,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of keys which can result in hits for this HitObject.
|
/// A list of keys which can result in hits for this HitObject.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract List<Key> HitKeys { get; }
|
protected abstract Key[] HitKeys { get; }
|
||||||
|
|
||||||
protected override Container<Framework.Graphics.Drawable> Content => bodyContainer;
|
protected override Container<Framework.Graphics.Drawable> Content => bodyContainer;
|
||||||
|
|
||||||
@ -36,8 +36,8 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
|
|
||||||
AddInternal(bodyContainer = new Container
|
AddInternal(bodyContainer = new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.Centre,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
|
|
||||||
protected override bool HandleKeyPress(Key key)
|
protected override bool HandleKeyPress(Key key)
|
||||||
{
|
{
|
||||||
if (Judgement.Result.HasValue)
|
if (Judgement.Result != HitResult.None)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
validKeyPressed = HitKeys.Contains(key);
|
validKeyPressed = HitKeys.Contains(key);
|
||||||
@ -78,13 +78,15 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
|
|
||||||
protected override void UpdateState(ArmedState state)
|
protected override void UpdateState(ArmedState state)
|
||||||
{
|
{
|
||||||
|
Delay(HitObject.StartTime - Time.Current + Judgement.TimeOffset, true);
|
||||||
|
|
||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
case ArmedState.Idle:
|
case ArmedState.Idle:
|
||||||
|
Delay(hit.HitWindowMiss);
|
||||||
break;
|
break;
|
||||||
case ArmedState.Miss:
|
case ArmedState.Miss:
|
||||||
FadeOut(100);
|
FadeOut(100);
|
||||||
Expire();
|
|
||||||
break;
|
break;
|
||||||
case ArmedState.Hit:
|
case ArmedState.Hit:
|
||||||
bodyContainer.ScaleTo(0.8f, 400, EasingTypes.OutQuad);
|
bodyContainer.ScaleTo(0.8f, 400, EasingTypes.OutQuad);
|
||||||
@ -93,9 +95,10 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
bodyContainer.MoveToY(0, 500, EasingTypes.In);
|
bodyContainer.MoveToY(0, 500, EasingTypes.In);
|
||||||
|
|
||||||
FadeOut(600);
|
FadeOut(600);
|
||||||
Expire();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Graphics;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
||||||
|
|
||||||
@ -9,12 +10,26 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
{
|
{
|
||||||
public class DrawableRimHit : DrawableHit
|
public class DrawableRimHit : DrawableHit
|
||||||
{
|
{
|
||||||
protected override List<Key> HitKeys { get; } = new List<Key>(new[] { Key.D, Key.K });
|
protected override Key[] HitKeys { get; } = { Key.D, Key.K };
|
||||||
|
|
||||||
|
private readonly CirclePiece circlePiece;
|
||||||
|
|
||||||
public DrawableRimHit(Hit hit)
|
public DrawableRimHit(Hit hit)
|
||||||
: base(hit)
|
: base(hit)
|
||||||
{
|
{
|
||||||
Add(new RimHitCirclePiece(new CirclePiece()));
|
Add(circlePiece = new CirclePiece
|
||||||
|
{
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new RimHitSymbolPiece()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
circlePiece.AccentColour = colours.BlueDarker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,35 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||||
{
|
{
|
||||||
public class DrawableStrongCentreHit : DrawableStrongHit
|
public class DrawableStrongCentreHit : DrawableStrongHit
|
||||||
{
|
{
|
||||||
protected override List<Key> HitKeys { get; } = new List<Key>(new[] { Key.F, Key.J });
|
protected override Key[] HitKeys { get; } = { Key.F, Key.J };
|
||||||
|
|
||||||
|
private readonly CirclePiece circlePiece;
|
||||||
|
|
||||||
public DrawableStrongCentreHit(Hit hit)
|
public DrawableStrongCentreHit(Hit hit)
|
||||||
: base(hit)
|
: base(hit)
|
||||||
{
|
{
|
||||||
Add(new CentreHitCirclePiece(new StrongCirclePiece()));
|
Add(circlePiece = new StrongCirclePiece
|
||||||
|
{
|
||||||
|
Children = new []
|
||||||
|
{
|
||||||
|
new CentreHitSymbolPiece()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
circlePiece.AccentColour = colours.PinkDarker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ using OpenTK.Input;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||||
{
|
{
|
||||||
@ -25,9 +27,11 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override TaikoJudgement CreateJudgement() => new TaikoStrongHitJudgement();
|
||||||
|
|
||||||
protected override void CheckJudgement(bool userTriggered)
|
protected override void CheckJudgement(bool userTriggered)
|
||||||
{
|
{
|
||||||
if (!Judgement.Result.HasValue)
|
if (Judgement.Result == HitResult.None)
|
||||||
{
|
{
|
||||||
base.CheckJudgement(userTriggered);
|
base.CheckJudgement(userTriggered);
|
||||||
return;
|
return;
|
||||||
@ -45,7 +49,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
protected override bool HandleKeyPress(Key key)
|
protected override bool HandleKeyPress(Key key)
|
||||||
{
|
{
|
||||||
// Check if we've handled the first key
|
// Check if we've handled the first key
|
||||||
if (!Judgement.Result.HasValue)
|
if (Judgement.Result == HitResult.None)
|
||||||
{
|
{
|
||||||
// First key hasn't been handled yet, attempt to handle it
|
// First key hasn't been handled yet, attempt to handle it
|
||||||
bool handled = base.HandleKeyPress(key);
|
bool handled = base.HandleKeyPress(key);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Graphics;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
||||||
|
|
||||||
@ -9,12 +10,26 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
{
|
{
|
||||||
public class DrawableStrongRimHit : DrawableStrongHit
|
public class DrawableStrongRimHit : DrawableStrongHit
|
||||||
{
|
{
|
||||||
protected override List<Key> HitKeys { get; } = new List<Key>(new[] { Key.D, Key.K });
|
protected override Key[] HitKeys { get; } = { Key.D, Key.K };
|
||||||
|
|
||||||
|
private readonly CirclePiece circlePiece;
|
||||||
|
|
||||||
public DrawableStrongRimHit(Hit hit)
|
public DrawableStrongRimHit(Hit hit)
|
||||||
: base(hit)
|
: base(hit)
|
||||||
{
|
{
|
||||||
Add(new RimHitCirclePiece(new StrongCirclePiece()));
|
Add(circlePiece = new StrongCirclePiece
|
||||||
|
{
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new RimHitSymbolPiece()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
circlePiece.AccentColour = colours.BlueDarker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ using osu.Game.Modes.Objects.Drawables;
|
|||||||
using osu.Game.Modes.Taiko.Judgements;
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
namespace osu.Game.Modes.Taiko.Objects.Drawable
|
||||||
{
|
{
|
||||||
@ -25,23 +26,30 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action OnStart;
|
public event Action OnStart;
|
||||||
|
|
||||||
private const float target_ring_thick_border = 4f;
|
private const float target_ring_thick_border = 1.4f;
|
||||||
private const float target_ring_thin_border = 1f;
|
private const float target_ring_thin_border = 1f;
|
||||||
private const float target_ring_scale = 5f;
|
private const float target_ring_scale = 5f;
|
||||||
private const float inner_ring_alpha = 0.35f;
|
private const float inner_ring_alpha = 0.65f;
|
||||||
|
|
||||||
|
private readonly Swell swell;
|
||||||
|
|
||||||
|
private readonly Container bodyContainer;
|
||||||
|
private readonly CircularContainer targetRing;
|
||||||
|
private readonly CircularContainer expandingRing;
|
||||||
|
|
||||||
|
private readonly CirclePiece circlePiece;
|
||||||
|
|
||||||
|
private readonly Key[] rimKeys = { Key.D, Key.K };
|
||||||
|
private readonly Key[] centreKeys = { Key.F, Key.J };
|
||||||
|
private Key[] lastKeySet;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of times the user has hit this swell.
|
/// The amount of times the user has hit this swell.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int userHits;
|
private int userHits;
|
||||||
|
|
||||||
private readonly Swell swell;
|
|
||||||
|
|
||||||
private readonly Container bodyContainer;
|
|
||||||
private readonly CircularContainer targetRing;
|
|
||||||
private readonly CircularContainer innerRing;
|
|
||||||
|
|
||||||
private bool hasStarted;
|
private bool hasStarted;
|
||||||
|
private readonly SwellSymbolPiece symbol;
|
||||||
|
|
||||||
public DrawableSwell(Swell swell)
|
public DrawableSwell(Swell swell)
|
||||||
: base(swell)
|
: base(swell)
|
||||||
@ -54,12 +62,14 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
{
|
{
|
||||||
Children = new Framework.Graphics.Drawable[]
|
Children = new Framework.Graphics.Drawable[]
|
||||||
{
|
{
|
||||||
innerRing = new CircularContainer
|
expandingRing = new CircularContainer
|
||||||
{
|
{
|
||||||
Name = "Inner ring",
|
Name = "Expanding ring",
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
Alpha = 0,
|
||||||
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
||||||
|
BlendingMode = BlendingMode.Additive,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Children = new []
|
Children = new []
|
||||||
{
|
{
|
||||||
@ -78,6 +88,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
||||||
Masking = true,
|
Masking = true,
|
||||||
BorderThickness = target_ring_thick_border,
|
BorderThickness = target_ring_thick_border,
|
||||||
|
BlendingMode = BlendingMode.Additive,
|
||||||
Children = new Framework.Graphics.Drawable[]
|
Children = new Framework.Graphics.Drawable[]
|
||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
@ -107,7 +118,13 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new SwellCirclePiece(new CirclePiece())
|
circlePiece = new CirclePiece
|
||||||
|
{
|
||||||
|
Children = new []
|
||||||
|
{
|
||||||
|
symbol = new SwellSymbolPiece()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -116,29 +133,27 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
innerRing.Colour = colours.YellowDark;
|
circlePiece.AccentColour = colours.YellowDark;
|
||||||
|
expandingRing.Colour = colours.YellowLight;
|
||||||
targetRing.BorderColour = colours.YellowDark.Opacity(0.25f);
|
targetRing.BorderColour = colours.YellowDark.Opacity(0.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
targetRing.Delay(HitObject.StartTime - Time.Current).ScaleTo(target_ring_scale, 600, EasingTypes.OutQuint);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void CheckJudgement(bool userTriggered)
|
protected override void CheckJudgement(bool userTriggered)
|
||||||
{
|
{
|
||||||
if (userTriggered)
|
if (userTriggered)
|
||||||
{
|
{
|
||||||
if (Time.Current < HitObject.StartTime)
|
|
||||||
return;
|
|
||||||
|
|
||||||
userHits++;
|
userHits++;
|
||||||
|
|
||||||
innerRing.FadeTo(1);
|
var completion = (float)userHits / swell.RequiredHits;
|
||||||
innerRing.FadeTo(inner_ring_alpha, 500, EasingTypes.OutQuint);
|
|
||||||
innerRing.ScaleTo(1f + (target_ring_scale - 1) * userHits / swell.RequiredHits, 1200, EasingTypes.OutElastic);
|
expandingRing.FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50);
|
||||||
|
expandingRing.Delay(50);
|
||||||
|
expandingRing.FadeTo(completion / 8, 2000, EasingTypes.OutQuint);
|
||||||
|
expandingRing.DelayReset();
|
||||||
|
|
||||||
|
symbol.RotateTo((float)(completion * swell.Duration / 8), 4000, EasingTypes.OutQuint);
|
||||||
|
|
||||||
|
expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, EasingTypes.OutQuint);
|
||||||
|
|
||||||
if (userHits == swell.RequiredHits)
|
if (userHits == swell.RequiredHits)
|
||||||
{
|
{
|
||||||
@ -151,6 +166,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
if (Judgement.TimeOffset < 0)
|
if (Judgement.TimeOffset < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//TODO: THIS IS SHIT AND CAN'T EXIST POST-TAIKO WORLD CUP
|
||||||
if (userHits > swell.RequiredHits / 2)
|
if (userHits > swell.RequiredHits / 2)
|
||||||
{
|
{
|
||||||
Judgement.Result = HitResult.Hit;
|
Judgement.Result = HitResult.Hit;
|
||||||
@ -163,21 +179,28 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
|
|
||||||
protected override void UpdateState(ArmedState state)
|
protected override void UpdateState(ArmedState state)
|
||||||
{
|
{
|
||||||
|
const float preempt = 100;
|
||||||
|
|
||||||
|
Delay(HitObject.StartTime - Time.Current - preempt, true);
|
||||||
|
|
||||||
|
targetRing.ScaleTo(target_ring_scale, preempt * 4, EasingTypes.OutQuint);
|
||||||
|
|
||||||
|
Delay(preempt, true);
|
||||||
|
|
||||||
|
Delay(Judgement.TimeOffset + swell.Duration, true);
|
||||||
|
|
||||||
|
const float out_transition_time = 300;
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case ArmedState.Idle:
|
|
||||||
break;
|
|
||||||
case ArmedState.Miss:
|
|
||||||
FadeOut(100);
|
|
||||||
Expire();
|
|
||||||
break;
|
|
||||||
case ArmedState.Hit:
|
case ArmedState.Hit:
|
||||||
bodyContainer.ScaleTo(1.2f, 400, EasingTypes.OutQuad);
|
bodyContainer.ScaleTo(1.4f, out_transition_time);
|
||||||
|
|
||||||
FadeOut(600);
|
|
||||||
Expire();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FadeOut(out_transition_time, EasingTypes.Out);
|
||||||
|
|
||||||
|
Expire();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateScrollPosition(double time)
|
protected override void UpdateScrollPosition(double time)
|
||||||
@ -196,9 +219,21 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
|
|||||||
|
|
||||||
protected override bool HandleKeyPress(Key key)
|
protected override bool HandleKeyPress(Key key)
|
||||||
{
|
{
|
||||||
if (Judgement.Result.HasValue)
|
if (Judgement.Result != HitResult.None)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Don't handle keys before the swell starts
|
||||||
|
if (Time.Current < HitObject.StartTime)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Find the keyset which this key corresponds to
|
||||||
|
var keySet = rimKeys.Contains(key) ? rimKeys : centreKeys;
|
||||||
|
|
||||||
|
// Ensure alternating keysets
|
||||||
|
if (keySet == lastKeySet)
|
||||||
|
return false;
|
||||||
|
lastKeySet = keySet;
|
||||||
|
|
||||||
UpdateJudgement(true);
|
UpdateJudgement(true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using OpenTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A circle piece used for centre hits.
|
|
||||||
/// </summary>
|
|
||||||
public class CentreHitCirclePiece : Container
|
|
||||||
{
|
|
||||||
private readonly CirclePiece circle;
|
|
||||||
|
|
||||||
public CentreHitCirclePiece(CirclePiece piece)
|
|
||||||
{
|
|
||||||
Add(circle = piece);
|
|
||||||
|
|
||||||
circle.Add(new CircularContainer
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Size = new Vector2(CirclePiece.SYMBOL_INNER_SIZE),
|
|
||||||
Masking = true,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
circle.AccentColour = colours.PinkDarker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The symbol used for centre hit pieces.
|
||||||
|
/// </summary>
|
||||||
|
public class CentreHitSymbolPiece : CircularContainer
|
||||||
|
{
|
||||||
|
public CentreHitSymbolPiece()
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
Size = new Vector2(CirclePiece.SYMBOL_INNER_SIZE);
|
||||||
|
Masking = true;
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites;
|
|||||||
using osu.Game.Graphics.Backgrounds;
|
using osu.Game.Graphics.Backgrounds;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using System;
|
using System;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
||||||
{
|
{
|
||||||
@ -18,7 +19,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|||||||
/// a rounded (_[-Width-]_) figure such that a regular "circle" is the result of a parent with Width = 0.
|
/// a rounded (_[-Width-]_) figure such that a regular "circle" is the result of a parent with Width = 0.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CirclePiece : Container
|
public class CirclePiece : Container, IHasAccentColour
|
||||||
{
|
{
|
||||||
public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f;
|
public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f;
|
||||||
public const float SYMBOL_BORDER = 8;
|
public const float SYMBOL_BORDER = 8;
|
||||||
@ -35,8 +36,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|||||||
{
|
{
|
||||||
accentColour = value;
|
accentColour = value;
|
||||||
|
|
||||||
innerBackground.Colour = AccentColour;
|
background.Colour = AccentColour;
|
||||||
triangles.Colour = AccentColour;
|
|
||||||
|
|
||||||
resetEdgeEffects();
|
resetEdgeEffects();
|
||||||
}
|
}
|
||||||
@ -66,10 +66,8 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|||||||
protected override Container<Framework.Graphics.Drawable> Content => SymbolContainer;
|
protected override Container<Framework.Graphics.Drawable> Content => SymbolContainer;
|
||||||
protected readonly Container SymbolContainer;
|
protected readonly Container SymbolContainer;
|
||||||
|
|
||||||
|
private readonly Container background;
|
||||||
private readonly Container innerLayer;
|
private readonly Container innerLayer;
|
||||||
private readonly Container innerCircleContainer;
|
|
||||||
private readonly Box innerBackground;
|
|
||||||
private readonly Triangles triangles;
|
|
||||||
|
|
||||||
public CirclePiece()
|
public CirclePiece()
|
||||||
{
|
{
|
||||||
@ -85,22 +83,22 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Children = new Framework.Graphics.Drawable[]
|
Children = new Framework.Graphics.Drawable[]
|
||||||
{
|
{
|
||||||
innerCircleContainer = new CircularContainer
|
background = new CircularContainer
|
||||||
{
|
{
|
||||||
Name = "Inner Circle",
|
Name = "Background",
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Children = new Framework.Graphics.Drawable[]
|
Children = new Framework.Graphics.Drawable[]
|
||||||
{
|
{
|
||||||
innerBackground = new Box
|
new Box
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
triangles = new Triangles
|
new Triangles
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -149,7 +147,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|||||||
|
|
||||||
private void resetEdgeEffects()
|
private void resetEdgeEffects()
|
||||||
{
|
{
|
||||||
innerCircleContainer.EdgeEffect = new EdgeEffect
|
background.EdgeEffect = new EdgeEffect
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Colour = AccentColour,
|
Colour = AccentColour,
|
||||||
|
@ -1,57 +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 OpenTK;
|
|
||||||
using OpenTK.Graphics;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.MathUtils;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A circle piece used for drumrolls.
|
|
||||||
/// </summary>
|
|
||||||
public class DrumRollCirclePiece : Container
|
|
||||||
{
|
|
||||||
private float completion;
|
|
||||||
/// <summary>
|
|
||||||
/// The amount of the drumroll that has been completed, as a percentage of the number
|
|
||||||
/// of ticks in the drumroll. This determines the internal colour of the drumroll.
|
|
||||||
/// </summary>
|
|
||||||
public float Completion
|
|
||||||
{
|
|
||||||
get { return completion; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
completion = MathHelper.Clamp(value, 0, 1);
|
|
||||||
|
|
||||||
if (!IsLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
circle.AccentColour = Interpolation.ValueAt(completion, baseColour, finalColour, 0, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly CirclePiece circle;
|
|
||||||
|
|
||||||
private Color4 baseColour;
|
|
||||||
private Color4 finalColour;
|
|
||||||
|
|
||||||
public DrumRollCirclePiece(CirclePiece piece)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X;
|
|
||||||
|
|
||||||
Add(circle = piece);
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
circle.AccentColour = baseColour = colours.YellowDark;
|
|
||||||
finalColour = colours.YellowDarker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +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 OpenTK;
|
|
||||||
using OpenTK.Graphics;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|
||||||
{
|
|
||||||
public class RimHitCirclePiece : Container
|
|
||||||
{
|
|
||||||
private readonly CirclePiece circle;
|
|
||||||
|
|
||||||
public RimHitCirclePiece(CirclePiece piece)
|
|
||||||
{
|
|
||||||
Add(circle = piece);
|
|
||||||
|
|
||||||
circle.Add(new CircularContainer
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Size = new Vector2(CirclePiece.SYMBOL_SIZE),
|
|
||||||
BorderThickness = CirclePiece.SYMBOL_BORDER,
|
|
||||||
BorderColour = Color4.White,
|
|
||||||
Masking = true,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
circle.AccentColour = colours.BlueDarker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The symbol used for rim hit pieces.
|
||||||
|
/// </summary>
|
||||||
|
public class RimHitSymbolPiece : CircularContainer
|
||||||
|
{
|
||||||
|
public RimHitSymbolPiece()
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
Size = new Vector2(CirclePiece.SYMBOL_SIZE);
|
||||||
|
BorderThickness = CirclePiece.SYMBOL_BORDER;
|
||||||
|
BorderColour = Color4.White;
|
||||||
|
Masking = true;
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,35 +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.Allocation;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
|
||||||
{
|
|
||||||
public class SwellCirclePiece : Container
|
|
||||||
{
|
|
||||||
private readonly CirclePiece circle;
|
|
||||||
|
|
||||||
public SwellCirclePiece(CirclePiece piece)
|
|
||||||
{
|
|
||||||
Add(circle = piece);
|
|
||||||
|
|
||||||
circle.Add(new TextAwesome
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
TextSize = CirclePiece.SYMBOL_INNER_SIZE,
|
|
||||||
Icon = FontAwesome.fa_asterisk,
|
|
||||||
Shadow = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
circle.AccentColour = colours.YellowDark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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.Game.Graphics;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The symbol used for swell pieces.
|
||||||
|
/// </summary>
|
||||||
|
public class SwellSymbolPiece : TextAwesome
|
||||||
|
{
|
||||||
|
public SwellSymbolPiece()
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
UseFullGlyphHeight = true;
|
||||||
|
TextSize = CirclePiece.SYMBOL_INNER_SIZE;
|
||||||
|
Icon = FontAwesome.fa_asterisk;
|
||||||
|
Shadow = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,7 @@ namespace osu.Game.Modes.Taiko.Objects
|
|||||||
/// The distance between ticks of this drumroll.
|
/// The distance between ticks of this drumroll.
|
||||||
/// <para>Half of this value is the hit window of the ticks.</para>
|
/// <para>Half of this value is the hit window of the ticks.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double TickTimeDistance { get; protected set; } = 200;
|
public double TickTimeDistance { get; protected set; } = 100;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of drum roll ticks required for a "Good" hit.
|
/// Number of drum roll ticks required for a "Good" hit.
|
||||||
|
@ -8,11 +8,6 @@ namespace osu.Game.Modes.Taiko.Objects
|
|||||||
{
|
{
|
||||||
public class Hit : TaikoHitObject
|
public class Hit : TaikoHitObject
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Whether this hit is a centre-hit or a rim-hit.
|
|
||||||
/// </summary>
|
|
||||||
public HitType Type;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The hit window that results in a "GREAT" hit.
|
/// The hit window that results in a "GREAT" hit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
9
osu.Game.Modes.Taiko/Objects/RimHit.cs
Normal file
9
osu.Game.Modes.Taiko/Objects/RimHit.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.Objects
|
||||||
|
{
|
||||||
|
public class RimHit : Hit
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ namespace osu.Game.Modes.Taiko.Objects
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// HitCircle radius.
|
/// HitCircle radius.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float CIRCLE_RADIUS = 64;
|
public const float CIRCLE_RADIUS = 42f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time to scroll in the HitObject.
|
/// The time to scroll in the HitObject.
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using osu.Game.Modes.Taiko.Objects;
|
using System;
|
||||||
using osu.Game.Modes.Objects.Types;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Modes.Objects.Types;
|
||||||
|
using osu.Game.Modes.Taiko.Objects;
|
||||||
|
using osu.Game.Modes.Replays;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko
|
namespace osu.Game.Modes.Taiko.Replays
|
||||||
{
|
{
|
||||||
public class TaikoAutoReplay : LegacyTaikoReplay
|
public class TaikoAutoReplay : Replay
|
||||||
{
|
{
|
||||||
private readonly Beatmap<TaikoHitObject> beatmap;
|
private readonly Beatmap<TaikoHitObject> beatmap;
|
||||||
|
|
||||||
@ -22,100 +24,98 @@ namespace osu.Game.Modes.Taiko
|
|||||||
{
|
{
|
||||||
bool hitButton = true;
|
bool hitButton = true;
|
||||||
|
|
||||||
Frames.Add(new LegacyReplayFrame(-100000, 320, 240, LegacyButtonState.None));
|
Frames.Add(new ReplayFrame(-100000, 320, 240, ReplayButtonState.None));
|
||||||
Frames.Add(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 320, 240, LegacyButtonState.None));
|
Frames.Add(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 320, 240, ReplayButtonState.None));
|
||||||
|
|
||||||
for (int i = 0; i < beatmap.HitObjects.Count; i++)
|
for (int i = 0; i < beatmap.HitObjects.Count; i++)
|
||||||
{
|
{
|
||||||
TaikoHitObject h = beatmap.HitObjects[i];
|
TaikoHitObject h = beatmap.HitObjects[i];
|
||||||
|
|
||||||
LegacyButtonState button;
|
ReplayButtonState button;
|
||||||
|
|
||||||
IHasEndTime endTimeData = h as IHasEndTime;
|
IHasEndTime endTimeData = h as IHasEndTime;
|
||||||
double endTime = endTimeData?.EndTime ?? h.StartTime;
|
double endTime = endTimeData?.EndTime ?? h.StartTime;
|
||||||
|
|
||||||
Swell sp = h as Swell;
|
Swell swell = h as Swell;
|
||||||
if (sp != null)
|
DrumRoll drumRoll = h as DrumRoll;
|
||||||
|
Hit hit = h as Hit;
|
||||||
|
|
||||||
|
if (swell != null)
|
||||||
{
|
{
|
||||||
int d = 0;
|
int d = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int req = sp.RequiredHits;
|
int req = swell.RequiredHits;
|
||||||
double hitRate = sp.Duration / req;
|
double hitRate = swell.Duration / req;
|
||||||
for (double j = h.StartTime; j < endTime; j += hitRate)
|
for (double j = h.StartTime; j < endTime; j += hitRate)
|
||||||
{
|
{
|
||||||
switch (d)
|
switch (d)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
button = LegacyButtonState.Left1;
|
button = ReplayButtonState.Left1;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
button = LegacyButtonState.Right1;
|
button = ReplayButtonState.Right1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
button = LegacyButtonState.Left2;
|
button = ReplayButtonState.Left2;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
button = LegacyButtonState.Right2;
|
button = ReplayButtonState.Right2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Frames.Add(new LegacyReplayFrame(j, 0, 0, button));
|
Frames.Add(new ReplayFrame(j, 0, 0, button));
|
||||||
d = (d + 1) % 4;
|
d = (d + 1) % 4;
|
||||||
if (++count > req)
|
if (++count > req)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (h is DrumRoll)
|
else if (drumRoll != null)
|
||||||
{
|
{
|
||||||
DrumRoll d = h as DrumRoll;
|
double delay = drumRoll.TickTimeDistance;
|
||||||
|
|
||||||
double delay = d.TickTimeDistance;
|
double time = drumRoll.StartTime;
|
||||||
|
|
||||||
double time = d.StartTime;
|
for (int j = 0; j < drumRoll.TotalTicks; j++)
|
||||||
|
|
||||||
for (int j = 0; j < d.TotalTicks; j++)
|
|
||||||
{
|
{
|
||||||
Frames.Add(new LegacyReplayFrame((int)time, 0, 0, hitButton ? LegacyButtonState.Left1 : LegacyButtonState.Left2));
|
Frames.Add(new ReplayFrame((int)time, 0, 0, hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2));
|
||||||
time += delay;
|
time += delay;
|
||||||
hitButton = !hitButton;
|
hitButton = !hitButton;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (hit != null)
|
||||||
{
|
{
|
||||||
Hit hit = h as Hit;
|
if (hit is CentreHit)
|
||||||
|
|
||||||
if (hit.Type == HitType.Centre)
|
|
||||||
{
|
{
|
||||||
if (h.IsStrong)
|
if (h.IsStrong)
|
||||||
button = LegacyButtonState.Right1 | LegacyButtonState.Right2;
|
button = ReplayButtonState.Right1 | ReplayButtonState.Right2;
|
||||||
else
|
else
|
||||||
button = hitButton ? LegacyButtonState.Right1 : LegacyButtonState.Right2;
|
button = hitButton ? ReplayButtonState.Right1 : ReplayButtonState.Right2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (h.IsStrong)
|
if (h.IsStrong)
|
||||||
button = LegacyButtonState.Left1 | LegacyButtonState.Left2;
|
button = ReplayButtonState.Left1 | ReplayButtonState.Left2;
|
||||||
else
|
else
|
||||||
button = hitButton ? LegacyButtonState.Left1 : LegacyButtonState.Left2;
|
button = hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Frames.Add(new LegacyReplayFrame(h.StartTime, 0, 0, button));
|
Frames.Add(new ReplayFrame(h.StartTime, 0, 0, button));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
throw new Exception("Unknown hit object type.");
|
||||||
|
|
||||||
Frames.Add(new LegacyReplayFrame(endTime + 1, 0, 0, LegacyButtonState.None));
|
Frames.Add(new ReplayFrame(endTime + 1, 0, 0, ReplayButtonState.None));
|
||||||
|
|
||||||
if (i < beatmap.HitObjects.Count - 1)
|
if (i < beatmap.HitObjects.Count - 1)
|
||||||
{
|
{
|
||||||
double waitTime = beatmap.HitObjects[i + 1].StartTime - 1000;
|
double waitTime = beatmap.HitObjects[i + 1].StartTime - 1000;
|
||||||
if (waitTime > endTime)
|
if (waitTime > endTime)
|
||||||
Frames.Add(new LegacyReplayFrame(waitTime, 0, 0, LegacyButtonState.None));
|
Frames.Add(new ReplayFrame(waitTime, 0, 0, ReplayButtonState.None));
|
||||||
}
|
}
|
||||||
|
|
||||||
hitButton = !hitButton;
|
hitButton = !hitButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Player.currentScore.Replay = InputManager.ReplayScore.Replay;
|
|
||||||
//Player.currentScore.PlayerName = "mekkadosu!";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
// 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.Replays;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using OpenTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Taiko.Replays
|
||||||
|
{
|
||||||
|
internal class TaikoFramedReplayInputHandler : FramedReplayInputHandler
|
||||||
|
{
|
||||||
|
public TaikoFramedReplayInputHandler(Replay replay)
|
||||||
|
: base(replay)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<InputState> GetPendingStates()
|
||||||
|
{
|
||||||
|
var keys = new List<Key>();
|
||||||
|
|
||||||
|
if (CurrentFrame?.MouseRight1 == true)
|
||||||
|
keys.Add(Key.F);
|
||||||
|
if (CurrentFrame?.MouseRight2 == true)
|
||||||
|
keys.Add(Key.J);
|
||||||
|
if (CurrentFrame?.MouseLeft1 == true)
|
||||||
|
keys.Add(Key.D);
|
||||||
|
if (CurrentFrame?.MouseLeft2 == true)
|
||||||
|
keys.Add(Key.K);
|
||||||
|
|
||||||
|
return new List<InputState>
|
||||||
|
{
|
||||||
|
new InputState { Keyboard = new ReplayKeyboardState(keys) }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -96,9 +96,9 @@ namespace osu.Game.Modes.Taiko.Scoring
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The multiple of the original score added to the combo portion of the score
|
/// The multiple of the original score added to the combo portion of the score
|
||||||
/// for correctly hitting an accented hit object with both keys.
|
/// for correctly hitting a strong hit object with both keys.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private double accentedHitScale;
|
private double strongHitScale;
|
||||||
|
|
||||||
private double hpIncreaseTick;
|
private double hpIncreaseTick;
|
||||||
private double hpIncreaseGreat;
|
private double hpIncreaseGreat;
|
||||||
@ -119,15 +119,6 @@ namespace osu.Game.Modes.Taiko.Scoring
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Score CreateScore() => new TaikoScore
|
|
||||||
{
|
|
||||||
TotalScore = TotalScore,
|
|
||||||
Combo = Combo,
|
|
||||||
MaxCombo = HighestCombo,
|
|
||||||
Accuracy = Accuracy,
|
|
||||||
Health = Health,
|
|
||||||
};
|
|
||||||
|
|
||||||
protected override void ComputeTargets(Beatmap<TaikoHitObject> beatmap)
|
protected override void ComputeTargets(Beatmap<TaikoHitObject> beatmap)
|
||||||
{
|
{
|
||||||
double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, 0.5, 0.75, 0.98));
|
double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, 0.5, 0.75, 0.98));
|
||||||
@ -137,12 +128,12 @@ namespace osu.Game.Modes.Taiko.Scoring
|
|||||||
hpIncreaseGood = hpMultiplierNormal * hp_hit_good;
|
hpIncreaseGood = hpMultiplierNormal * hp_hit_good;
|
||||||
hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max);
|
hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max);
|
||||||
|
|
||||||
var accentedHits = beatmap.HitObjects.FindAll(o => o is Hit && o.IsStrong);
|
var strongHits = beatmap.HitObjects.FindAll(o => o is Hit && o.IsStrong);
|
||||||
|
|
||||||
// This is a linear function that awards:
|
// This is a linear function that awards:
|
||||||
// 10 times bonus points for hitting an accented hit object with both keys with 30 accented hit objects in the map
|
// 10 times bonus points for hitting a strong hit object with both keys with 30 strong hit objects in the map
|
||||||
// 3 times bonus points for hitting an accented hit object with both keys with 120 accented hit objects in the map
|
// 3 times bonus points for hitting a strong hit object with both keys with 120 strong hit objects in the map
|
||||||
accentedHitScale = -7d / 90d * MathHelper.Clamp(accentedHits.Count, 30, 120) + 111d / 9d;
|
strongHitScale = -7d / 90d * MathHelper.Clamp(strongHits.Count, 30, 120) + 111d / 9d;
|
||||||
|
|
||||||
foreach (var obj in beatmap.HitObjects)
|
foreach (var obj in beatmap.HitObjects)
|
||||||
{
|
{
|
||||||
@ -188,7 +179,7 @@ namespace osu.Game.Modes.Taiko.Scoring
|
|||||||
maxComboPortion = comboPortion;
|
maxComboPortion = comboPortion;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewJugement(TaikoJudgement judgement)
|
protected override void OnNewJudgement(TaikoJudgement judgement)
|
||||||
{
|
{
|
||||||
bool isTick = judgement is TaikoDrumRollTickJudgement;
|
bool isTick = judgement is TaikoDrumRollTickJudgement;
|
||||||
|
|
||||||
@ -196,29 +187,12 @@ namespace osu.Game.Modes.Taiko.Scoring
|
|||||||
if (!isTick)
|
if (!isTick)
|
||||||
totalHits++;
|
totalHits++;
|
||||||
|
|
||||||
// Apply score changes
|
// Apply combo changes, must be done before the hit score is added
|
||||||
if (judgement.Result == HitResult.Hit)
|
if (!isTick && judgement.Result == HitResult.Hit)
|
||||||
{
|
|
||||||
double baseValue = judgement.ResultValueForScore;
|
|
||||||
|
|
||||||
// Add bonus points for hitting an accented hit object with the second key
|
|
||||||
if (judgement.SecondHit)
|
|
||||||
baseValue += baseValue * accentedHitScale;
|
|
||||||
|
|
||||||
// Add score to portions
|
|
||||||
if (isTick)
|
|
||||||
bonusScore += baseValue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Combo.Value++;
|
Combo.Value++;
|
||||||
|
|
||||||
// A relevance factor that needs to be applied to make higher combos more relevant
|
// Apply score changes
|
||||||
// Value is capped at 400 combo
|
addHitScore(judgement);
|
||||||
double comboRelevance = Math.Min(Math.Log(400, combo_base), Math.Max(0.5, Math.Log(Combo.Value, combo_base)));
|
|
||||||
|
|
||||||
comboPortion += baseValue * comboRelevance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply HP changes
|
// Apply HP changes
|
||||||
switch (judgement.Result)
|
switch (judgement.Result)
|
||||||
@ -244,7 +218,43 @@ namespace osu.Game.Modes.Taiko.Scoring
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the new score + accuracy
|
calculateScore();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnJudgementChanged(TaikoJudgement judgement)
|
||||||
|
{
|
||||||
|
// Apply score changes
|
||||||
|
addHitScore(judgement);
|
||||||
|
|
||||||
|
calculateScore();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addHitScore(TaikoJudgement judgement)
|
||||||
|
{
|
||||||
|
if (judgement.Result != HitResult.Hit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double baseValue = judgement.ResultValueForScore;
|
||||||
|
|
||||||
|
// Add increased score for hitting a strong hit object with the second key
|
||||||
|
if (judgement.SecondHit)
|
||||||
|
baseValue *= strongHitScale;
|
||||||
|
|
||||||
|
// Add score to portions
|
||||||
|
if (judgement is TaikoDrumRollTickJudgement)
|
||||||
|
bonusScore += baseValue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A relevance factor that needs to be applied to make higher combos more relevant
|
||||||
|
// Value is capped at 400 combo
|
||||||
|
double comboRelevance = Math.Min(Math.Log(400, combo_base), Math.Max(0.5, Math.Log(Combo.Value, combo_base)));
|
||||||
|
|
||||||
|
comboPortion += baseValue * comboRelevance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateScore()
|
||||||
|
{
|
||||||
int scoreForAccuracy = 0;
|
int scoreForAccuracy = 0;
|
||||||
int maxScoreForAccuracy = 0;
|
int maxScoreForAccuracy = 0;
|
||||||
|
|
||||||
|
@ -1,13 +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.Scoring;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace osu.Game.Modes.Taiko
|
|
||||||
{
|
|
||||||
public class TaikoScore : Score
|
|
||||||
{
|
|
||||||
public override Replay CreateLegacyReplayFrom(StreamReader reader) => new LegacyTaikoReplay(reader);
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,7 +18,7 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Diameter of normal hit object circles.
|
/// Diameter of normal hit object circles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const float normal_diameter = TaikoHitObject.CIRCLE_RADIUS * 2 * TaikoPlayfield.PLAYFIELD_SCALE;
|
private const float normal_diameter = TaikoHitObject.CIRCLE_RADIUS * 2;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Diameter of finisher hit object circles.
|
/// Diameter of finisher hit object circles.
|
||||||
@ -47,7 +47,7 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
Y = border_offset,
|
Y = border_offset,
|
||||||
Size = new Vector2(border_thickness, (TaikoPlayfield.PlayfieldHeight - finisher_diameter) / 2f - border_offset),
|
Size = new Vector2(border_thickness, (TaikoPlayfield.PLAYFIELD_HEIGHT - finisher_diameter) / 2f - border_offset),
|
||||||
Alpha = 0.1f
|
Alpha = 0.1f
|
||||||
},
|
},
|
||||||
new CircularContainer
|
new CircularContainer
|
||||||
@ -96,7 +96,7 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
Anchor = Anchor.BottomCentre,
|
Anchor = Anchor.BottomCentre,
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
Y = -border_offset,
|
Y = -border_offset,
|
||||||
Size = new Vector2(border_thickness, (TaikoPlayfield.PlayfieldHeight - finisher_diameter) / 2f - border_offset),
|
Size = new Vector2(border_thickness, (TaikoPlayfield.PLAYFIELD_HEIGHT - finisher_diameter) / 2f - border_offset),
|
||||||
Alpha = 0.1f
|
Alpha = 0.1f
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
{
|
{
|
||||||
public InputDrum()
|
public InputDrum()
|
||||||
{
|
{
|
||||||
Size = new Vector2(TaikoPlayfield.PlayfieldHeight);
|
Size = new Vector2(TaikoPlayfield.PLAYFIELD_HEIGHT);
|
||||||
|
|
||||||
const float middle_split = 10;
|
const float middle_split = 10;
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Modes.Objects.Drawables;
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
|
using osu.Game.Modes.Replays;
|
||||||
using osu.Game.Modes.Scoring;
|
using osu.Game.Modes.Scoring;
|
||||||
using osu.Game.Modes.Taiko.Beatmaps;
|
using osu.Game.Modes.Taiko.Beatmaps;
|
||||||
using osu.Game.Modes.Taiko.Judgements;
|
using osu.Game.Modes.Taiko.Judgements;
|
||||||
using osu.Game.Modes.Taiko.Objects;
|
using osu.Game.Modes.Taiko.Objects;
|
||||||
using osu.Game.Modes.Taiko.Objects.Drawable;
|
using osu.Game.Modes.Taiko.Objects.Drawable;
|
||||||
|
using osu.Game.Modes.Taiko.Replays;
|
||||||
using osu.Game.Modes.Taiko.Scoring;
|
using osu.Game.Modes.Taiko.Scoring;
|
||||||
using osu.Game.Modes.UI;
|
using osu.Game.Modes.UI;
|
||||||
|
|
||||||
|
@ -21,25 +21,15 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgement>
|
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgement>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default play field height.
|
/// The play field height. This is relative to the size of hit objects
|
||||||
|
/// such that the playfield is just a bit larger than finishers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float PLAYFIELD_BASE_HEIGHT = 242;
|
public const float PLAYFIELD_HEIGHT = TaikoHitObject.CIRCLE_RADIUS * 2 * 2;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The play field height scale.
|
|
||||||
/// This also uniformly scales the notes to match the new playfield height.
|
|
||||||
/// </summary>
|
|
||||||
public const float PLAYFIELD_SCALE = 0.65f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The play field height after scaling.
|
|
||||||
/// </summary>
|
|
||||||
public static float PlayfieldHeight => PLAYFIELD_BASE_HEIGHT * PLAYFIELD_SCALE;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The offset from <see cref="left_area_size"/> which the center of the hit target lies at.
|
/// The offset from <see cref="left_area_size"/> which the center of the hit target lies at.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const float hit_target_offset = 80;
|
private const float hit_target_offset = TaikoHitObject.CIRCLE_RADIUS * 1.5f + 40;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The size of the left area of the playfield. This area contains the input drum.
|
/// The size of the left area of the playfield. This area contains the input drum.
|
||||||
@ -62,7 +52,7 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
public TaikoPlayfield()
|
public TaikoPlayfield()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = PlayfieldHeight;
|
Height = PLAYFIELD_HEIGHT;
|
||||||
|
|
||||||
AddInternal(new Drawable[]
|
AddInternal(new Drawable[]
|
||||||
{
|
{
|
||||||
@ -103,7 +93,6 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
|
||||||
Scale = new Vector2(PLAYFIELD_SCALE),
|
|
||||||
BlendingMode = BlendingMode.Additive
|
BlendingMode = BlendingMode.Additive
|
||||||
},
|
},
|
||||||
//barLineContainer = new Container<DrawableBarLine>
|
//barLineContainer = new Container<DrawableBarLine>
|
||||||
@ -130,7 +119,7 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
},
|
},
|
||||||
leftBackgroundContainer = new Container
|
leftBackgroundContainer = new Container
|
||||||
{
|
{
|
||||||
Size = new Vector2(left_area_size, PlayfieldHeight),
|
Size = new Vector2(left_area_size, PLAYFIELD_HEIGHT),
|
||||||
BorderThickness = 1,
|
BorderThickness = 1,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -175,7 +164,6 @@ namespace osu.Game.Modes.Taiko.UI
|
|||||||
public override void Add(DrawableHitObject<TaikoHitObject, TaikoJudgement> h)
|
public override void Add(DrawableHitObject<TaikoHitObject, TaikoJudgement> h)
|
||||||
{
|
{
|
||||||
h.Depth = (float)h.HitObject.StartTime;
|
h.Depth = (float)h.HitObject.StartTime;
|
||||||
h.Scale = new Vector2(PLAYFIELD_SCALE);
|
|
||||||
|
|
||||||
base.Add(h);
|
base.Add(h);
|
||||||
|
|
||||||
|
@ -50,37 +50,37 @@
|
|||||||
<Compile Include="Beatmaps\TaikoBeatmapConverter.cs" />
|
<Compile Include="Beatmaps\TaikoBeatmapConverter.cs" />
|
||||||
<Compile Include="Beatmaps\TaikoBeatmapProcessor.cs" />
|
<Compile Include="Beatmaps\TaikoBeatmapProcessor.cs" />
|
||||||
<Compile Include="Judgements\TaikoDrumRollTickJudgement.cs" />
|
<Compile Include="Judgements\TaikoDrumRollTickJudgement.cs" />
|
||||||
|
<Compile Include="Judgements\TaikoStrongHitJudgement.cs" />
|
||||||
<Compile Include="Judgements\TaikoJudgement.cs" />
|
<Compile Include="Judgements\TaikoJudgement.cs" />
|
||||||
<Compile Include="Judgements\TaikoHitResult.cs" />
|
<Compile Include="Judgements\TaikoHitResult.cs" />
|
||||||
<Compile Include="LegacyTaikoReplay.cs" />
|
<Compile Include="Objects\CentreHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableRimHit.cs" />
|
<Compile Include="Objects\Drawable\DrawableRimHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableStrongRimHit.cs" />
|
<Compile Include="Objects\Drawable\DrawableStrongRimHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\Pieces\CentreHitCirclePiece.cs" />
|
|
||||||
<Compile Include="Objects\Drawable\DrawableCentreHit.cs" />
|
<Compile Include="Objects\Drawable\DrawableCentreHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableHit.cs" />
|
<Compile Include="Objects\Drawable\DrawableHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableStrongCentreHit.cs" />
|
|
||||||
<Compile Include="Objects\Drawable\DrawableStrongDrumRoll.cs" />
|
<Compile Include="Objects\Drawable\DrawableStrongDrumRoll.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\DrawableStrongCentreHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableStrongHit.cs" />
|
<Compile Include="Objects\Drawable\DrawableStrongHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\Pieces\RimHitCirclePiece.cs" />
|
<Compile Include="Objects\Drawable\Pieces\CentreHitSymbolPiece.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableDrumRoll.cs" />
|
<Compile Include="Objects\Drawable\DrawableDrumRoll.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableDrumRollTick.cs" />
|
<Compile Include="Objects\Drawable\DrawableDrumRollTick.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableSwell.cs" />
|
<Compile Include="Objects\Drawable\DrawableSwell.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableTaikoHitObject.cs" />
|
<Compile Include="Objects\Drawable\DrawableTaikoHitObject.cs" />
|
||||||
<Compile Include="Objects\Drawable\Pieces\SwellCirclePiece.cs" />
|
<Compile Include="Objects\Drawable\Pieces\RimHitSymbolPiece.cs" />
|
||||||
<Compile Include="Objects\Drawable\Pieces\DrumRollCirclePiece.cs" />
|
|
||||||
<Compile Include="Objects\Drawable\Pieces\StrongCirclePiece.cs" />
|
<Compile Include="Objects\Drawable\Pieces\StrongCirclePiece.cs" />
|
||||||
<Compile Include="Objects\Drawable\Pieces\CirclePiece.cs" />
|
<Compile Include="Objects\Drawable\Pieces\CirclePiece.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\Pieces\SwellSymbolPiece.cs" />
|
||||||
<Compile Include="Objects\DrumRoll.cs" />
|
<Compile Include="Objects\DrumRoll.cs" />
|
||||||
<Compile Include="Objects\DrumRollTick.cs" />
|
<Compile Include="Objects\DrumRollTick.cs" />
|
||||||
<Compile Include="Objects\Hit.cs" />
|
<Compile Include="Objects\Hit.cs" />
|
||||||
<Compile Include="Objects\HitType.cs" />
|
<Compile Include="Objects\RimHit.cs" />
|
||||||
<Compile Include="Objects\Swell.cs" />
|
<Compile Include="Objects\Swell.cs" />
|
||||||
<Compile Include="TaikoAutoReplay.cs" />
|
<Compile Include="Replays\TaikoFramedReplayInputHandler.cs" />
|
||||||
|
<Compile Include="Replays\TaikoAutoReplay.cs" />
|
||||||
<Compile Include="Objects\TaikoHitObject.cs" />
|
<Compile Include="Objects\TaikoHitObject.cs" />
|
||||||
<Compile Include="TaikoDifficultyCalculator.cs" />
|
<Compile Include="TaikoDifficultyCalculator.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Scoring\TaikoScoreProcessor.cs" />
|
<Compile Include="Scoring\TaikoScoreProcessor.cs" />
|
||||||
<Compile Include="TaikoScore.cs" />
|
|
||||||
<Compile Include="UI\HitTarget.cs" />
|
<Compile Include="UI\HitTarget.cs" />
|
||||||
<Compile Include="UI\InputDrum.cs" />
|
<Compile Include="UI\InputDrum.cs" />
|
||||||
<Compile Include="UI\DrawableTaikoJudgement.cs" />
|
<Compile Include="UI\DrawableTaikoJudgement.cs" />
|
||||||
|
@ -33,18 +33,15 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new DelayedLoadContainer
|
new DelayedLoadWrapper(
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
TimeBeforeLoad = 100,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new PanelBackground(beatmap)
|
new PanelBackground(beatmap)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Depth = 1,
|
OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
{
|
||||||
|
TimeBeforeLoad = 300,
|
||||||
},
|
},
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
|
@ -101,7 +101,7 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize))
|
using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize))
|
||||||
using (var reader = new StreamReader(lzma))
|
using (var reader = new StreamReader(lzma))
|
||||||
score.Replay = score.CreateLegacyReplayFrom(reader);
|
score.Replay = score.CreateReplay(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
34
osu.Game/Graphics/IHasAccentColour.cs
Normal file
34
osu.Game/Graphics/IHasAccentColour.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics.Transforms;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A type of drawable that has an accent colour.
|
||||||
|
/// The accent colour is used to colorize various objects inside a drawable
|
||||||
|
/// without colorizing the drawable itself.
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasAccentColour : IDrawable
|
||||||
|
{
|
||||||
|
Color4 AccentColour { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AccentedColourExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tweens the accent colour of a drawable to another colour.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="accentedDrawable">The drawable to apply the accent colour to.</param>
|
||||||
|
/// <param name="newColour">The new accent colour.</param>
|
||||||
|
/// <param name="duration">The tween duration.</param>
|
||||||
|
/// <param name="easing">The tween easing.</param>
|
||||||
|
public static void FadeAccent(this IHasAccentColour accentedDrawable, Color4 newColour, double duration = 0, EasingTypes easing = EasingTypes.None)
|
||||||
|
{
|
||||||
|
accentedDrawable.TransformTo(accentedDrawable.AccentColour, newColour, duration, easing, new TransformAccent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
osu.Game/Graphics/Transforms/TransformAccent.cs
Normal file
37
osu.Game/Graphics/Transforms/TransformAccent.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 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.Graphics;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Transforms;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Transforms
|
||||||
|
{
|
||||||
|
public class TransformAccent : Transform<Color4>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Current value of the transformed colour in linear colour space.
|
||||||
|
/// </summary>
|
||||||
|
public override Color4 CurrentValue
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
double time = Time?.Current ?? 0;
|
||||||
|
if (time < StartTime) return StartValue;
|
||||||
|
if (time >= EndTime) return EndValue;
|
||||||
|
|
||||||
|
return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Apply(Drawable d)
|
||||||
|
{
|
||||||
|
base.Apply(d);
|
||||||
|
|
||||||
|
var accented = d as IHasAccentColour;
|
||||||
|
if (accented != null)
|
||||||
|
accented.AccentColour = CurrentValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ using osu.Framework.Graphics.UserInterface;
|
|||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
public class Nub : CircularContainer, IStateful<CheckBoxState>
|
public class Nub : CircularContainer, IStateful<CheckboxState>
|
||||||
{
|
{
|
||||||
public const float COLLAPSED_SIZE = 20;
|
public const float COLLAPSED_SIZE = 20;
|
||||||
public const float EXPANDED_SIZE = 40;
|
public const float EXPANDED_SIZE = 40;
|
||||||
@ -84,9 +84,9 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CheckBoxState state;
|
private CheckboxState state;
|
||||||
|
|
||||||
public CheckBoxState State
|
public CheckboxState State
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -98,10 +98,10 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case CheckBoxState.Checked:
|
case CheckboxState.Checked:
|
||||||
fill.FadeIn(200, EasingTypes.OutQuint);
|
fill.FadeIn(200, EasingTypes.OutQuint);
|
||||||
break;
|
break;
|
||||||
case CheckBoxState.Unchecked:
|
case CheckboxState.Unchecked:
|
||||||
fill.FadeTo(0.01f, 200, EasingTypes.OutQuint); //todo: remove once we figure why containers aren't drawing at all times
|
fill.FadeTo(0.01f, 200, EasingTypes.OutQuint); //todo: remove once we figure why containers aren't drawing at all times
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ using OpenTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
public class OsuCheckbox : CheckBox
|
public class OsuCheckbox : Checkbox
|
||||||
{
|
{
|
||||||
private Bindable<bool> bindable;
|
private Bindable<bool> bindable;
|
||||||
|
|
||||||
@ -29,9 +29,9 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
bindable = value;
|
bindable = value;
|
||||||
if (bindable != null)
|
if (bindable != null)
|
||||||
{
|
{
|
||||||
bool state = State == CheckBoxState.Checked;
|
bool state = State == CheckboxState.Checked;
|
||||||
if (state != bindable.Value)
|
if (state != bindable.Value)
|
||||||
State = bindable.Value ? CheckBoxState.Checked : CheckBoxState.Unchecked;
|
State = bindable.Value ? CheckboxState.Checked : CheckboxState.Unchecked;
|
||||||
bindable.ValueChanged += bindableValueChanged;
|
bindable.ValueChanged += bindableValueChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
private void bindableValueChanged(object sender, EventArgs e)
|
private void bindableValueChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
State = bindable.Value ? CheckBoxState.Checked : CheckBoxState.Unchecked;
|
State = bindable.Value ? CheckboxState.Checked : CheckboxState.Unchecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
@ -122,7 +122,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
protected override void OnChecked()
|
protected override void OnChecked()
|
||||||
{
|
{
|
||||||
sampleChecked?.Play();
|
sampleChecked?.Play();
|
||||||
nub.State = CheckBoxState.Checked;
|
nub.State = CheckboxState.Checked;
|
||||||
|
|
||||||
if (bindable != null)
|
if (bindable != null)
|
||||||
bindable.Value = true;
|
bindable.Value = true;
|
||||||
@ -131,7 +131,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
protected override void OnUnchecked()
|
protected override void OnUnchecked()
|
||||||
{
|
{
|
||||||
sampleUnchecked?.Play();
|
sampleUnchecked?.Play();
|
||||||
nub.State = CheckBoxState.Unchecked;
|
nub.State = CheckboxState.Unchecked;
|
||||||
|
|
||||||
if (bindable != null)
|
if (bindable != null)
|
||||||
bindable.Value = false;
|
bindable.Value = false;
|
||||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
nub = new Nub
|
nub = new Nub
|
||||||
{
|
{
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
State = CheckBoxState.Unchecked,
|
State = CheckboxState.Unchecked,
|
||||||
Expanded = true,
|
Expanded = true,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -94,13 +94,13 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||||
{
|
{
|
||||||
nub.State = CheckBoxState.Checked;
|
nub.State = CheckboxState.Checked;
|
||||||
return base.OnMouseDown(state, args);
|
return base.OnMouseDown(state, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||||
{
|
{
|
||||||
nub.State = CheckBoxState.Unchecked;
|
nub.State = CheckboxState.Unchecked;
|
||||||
return base.OnMouseUp(state, args);
|
return base.OnMouseUp(state, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,15 +16,15 @@ using osu.Game.Graphics.Sprites;
|
|||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A checkbox styled to be placed in line with an <see cref="OsuTabControl{T}"/>
|
/// A Checkbox styled to be placed in line with an <see cref="OsuTabControl{T}"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OsuTabControlCheckBox : CheckBox
|
public class OsuTabControlCheckbox : Checkbox
|
||||||
{
|
{
|
||||||
private readonly Box box;
|
private readonly Box box;
|
||||||
private readonly SpriteText text;
|
private readonly SpriteText text;
|
||||||
private readonly TextAwesome icon;
|
private readonly TextAwesome icon;
|
||||||
|
|
||||||
public event EventHandler<CheckBoxState> Action;
|
public event EventHandler<CheckboxState> Action;
|
||||||
|
|
||||||
private Color4? accentColour;
|
private Color4? accentColour;
|
||||||
public Color4 AccentColour
|
public Color4 AccentColour
|
||||||
@ -34,7 +34,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
{
|
{
|
||||||
accentColour = value;
|
accentColour = value;
|
||||||
|
|
||||||
if (State != CheckBoxState.Checked)
|
if (State != CheckboxState.Checked)
|
||||||
{
|
{
|
||||||
text.Colour = AccentColour;
|
text.Colour = AccentColour;
|
||||||
icon.Colour = AccentColour;
|
icon.Colour = AccentColour;
|
||||||
@ -84,7 +84,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
protected override void OnHoverLost(InputState state)
|
protected override void OnHoverLost(InputState state)
|
||||||
{
|
{
|
||||||
if (State == CheckBoxState.Unchecked)
|
if (State == CheckboxState.Unchecked)
|
||||||
fadeOut();
|
fadeOut();
|
||||||
|
|
||||||
base.OnHoverLost(state);
|
base.OnHoverLost(state);
|
||||||
@ -97,7 +97,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
AccentColour = colours.Blue;
|
AccentColour = colours.Blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsuTabControlCheckBox()
|
public OsuTabControlCheckbox()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
protected class TransformAccuracy : Transform<double>
|
protected class TransformAccuracy : Transform<double>
|
||||||
{
|
{
|
||||||
protected override double CurrentValue
|
public override double CurrentValue
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -51,7 +51,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
protected class TransformScore : Transform<double>
|
protected class TransformScore : Transform<double>
|
||||||
{
|
{
|
||||||
protected override double CurrentValue
|
public override double CurrentValue
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
26
osu.Game/Modes/Judgements/IPartialJudgement.cs
Normal file
26
osu.Game/Modes/Judgements/IPartialJudgement.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Game.Modes.Objects.Drawables;
|
||||||
|
using osu.Game.Modes.Scoring;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Judgements
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Inidicates that the judgement this is attached to is a partial judgement and the scoring value may change.
|
||||||
|
/// <para>
|
||||||
|
/// This judgement will be continually processed by <see cref="DrawableHitObject{TObject, TJudgement}.CheckJudgement(bool)"/>
|
||||||
|
/// unless the result is a miss and will trigger a full re-process of the <see cref="ScoreProcessor"/> when changed.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public interface IPartialJudgement
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that this partial judgement has changed and requires a full re-process of the <see cref="ScoreProcessor"/>.
|
||||||
|
/// <para>
|
||||||
|
/// This is set to false once the judgement has been re-processed.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
bool Changed { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ namespace osu.Game.Modes.Judgements
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this judgement is the result of a hit or a miss.
|
/// Whether this judgement is the result of a hit or a miss.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public HitResult? Result;
|
public HitResult Result;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The offset at which this judgement occurred.
|
/// The offset at which this judgement occurred.
|
||||||
@ -20,7 +20,7 @@ namespace osu.Game.Modes.Judgements
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The combo after this judgement was processed.
|
/// The combo after this judgement was processed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong? ComboAtHit;
|
public int ComboAtHit;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The string representation for the result achieved.
|
/// The string representation for the result achieved.
|
||||||
|
@ -1,268 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
|
||||||
using osu.Framework.Input;
|
|
||||||
using osu.Framework.MathUtils;
|
|
||||||
using osu.Game.Input.Handlers;
|
|
||||||
using osu.Game.IO.Legacy;
|
|
||||||
using OpenTK;
|
|
||||||
using OpenTK.Input;
|
|
||||||
using KeyboardState = osu.Framework.Input.KeyboardState;
|
|
||||||
using MouseState = osu.Framework.Input.MouseState;
|
|
||||||
|
|
||||||
namespace osu.Game.Modes
|
|
||||||
{
|
|
||||||
public class LegacyReplay : Replay
|
|
||||||
{
|
|
||||||
protected List<LegacyReplayFrame> Frames = new List<LegacyReplayFrame>();
|
|
||||||
|
|
||||||
protected LegacyReplay()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public LegacyReplay(StreamReader reader)
|
|
||||||
{
|
|
||||||
float lastTime = 0;
|
|
||||||
|
|
||||||
foreach (var l in reader.ReadToEnd().Split(','))
|
|
||||||
{
|
|
||||||
var split = l.Split('|');
|
|
||||||
|
|
||||||
if (split.Length < 4 || float.Parse(split[0]) < 0) continue;
|
|
||||||
|
|
||||||
lastTime += float.Parse(split[0]);
|
|
||||||
|
|
||||||
Frames.Add(new LegacyReplayFrame(
|
|
||||||
lastTime,
|
|
||||||
float.Parse(split[1]),
|
|
||||||
384 - float.Parse(split[2]),
|
|
||||||
(LegacyButtonState)int.Parse(split[3])
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ReplayInputHandler CreateInputHandler() => new LegacyReplayInputHandler(Frames);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The ReplayHandler will take a replay and handle the propagation of updates to the input stack.
|
|
||||||
/// It handles logic of any frames which *must* be executed.
|
|
||||||
/// </summary>
|
|
||||||
protected class LegacyReplayInputHandler : ReplayInputHandler
|
|
||||||
{
|
|
||||||
private readonly List<LegacyReplayFrame> replayContent;
|
|
||||||
|
|
||||||
public LegacyReplayFrame CurrentFrame => !hasFrames ? null : replayContent[currentFrameIndex];
|
|
||||||
public LegacyReplayFrame NextFrame => !hasFrames ? null : replayContent[nextFrameIndex];
|
|
||||||
|
|
||||||
private int currentFrameIndex;
|
|
||||||
|
|
||||||
private int nextFrameIndex => MathHelper.Clamp(currentFrameIndex + (currentDirection > 0 ? 1 : -1), 0, replayContent.Count - 1);
|
|
||||||
|
|
||||||
public LegacyReplayInputHandler(List<LegacyReplayFrame> replayContent)
|
|
||||||
{
|
|
||||||
this.replayContent = replayContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool advanceFrame()
|
|
||||||
{
|
|
||||||
int newFrame = nextFrameIndex;
|
|
||||||
|
|
||||||
//ensure we aren't at an extent.
|
|
||||||
if (newFrame == currentFrameIndex) return false;
|
|
||||||
|
|
||||||
currentFrameIndex = newFrame;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetPosition(Vector2 pos)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private Vector2? position
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!hasFrames)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return Interpolation.ValueAt(currentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override List<InputState> GetPendingStates()
|
|
||||||
{
|
|
||||||
var buttons = new HashSet<MouseButton>();
|
|
||||||
if (CurrentFrame?.MouseLeft ?? false)
|
|
||||||
buttons.Add(MouseButton.Left);
|
|
||||||
if (CurrentFrame?.MouseRight ?? false)
|
|
||||||
buttons.Add(MouseButton.Right);
|
|
||||||
|
|
||||||
return new List<InputState>
|
|
||||||
{
|
|
||||||
new InputState
|
|
||||||
{
|
|
||||||
Mouse = new ReplayMouseState(ToScreenSpace(position ?? Vector2.Zero), buttons),
|
|
||||||
Keyboard = new ReplayKeyboardState(new List<Key>())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AtLastFrame => currentFrameIndex == replayContent.Count - 1;
|
|
||||||
public bool AtFirstFrame => currentFrameIndex == 0;
|
|
||||||
|
|
||||||
public Vector2 Size => new Vector2(512, 384);
|
|
||||||
|
|
||||||
private const double sixty_frame_time = 1000.0 / 60;
|
|
||||||
|
|
||||||
private double currentTime;
|
|
||||||
private int currentDirection;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When set, we will ensure frames executed by nested drawables are frame-accurate to replay data.
|
|
||||||
/// Disabling this can make replay playback smoother (useful for autoplay, currently).
|
|
||||||
/// </summary>
|
|
||||||
public bool FrameAccuratePlayback = true;
|
|
||||||
|
|
||||||
private bool hasFrames => replayContent.Count > 0;
|
|
||||||
|
|
||||||
private bool inImportantSection =>
|
|
||||||
FrameAccuratePlayback &&
|
|
||||||
//a button is in a pressed state
|
|
||||||
(currentDirection > 0 ? CurrentFrame : NextFrame)?.ButtonState > LegacyButtonState.None &&
|
|
||||||
//the next frame is within an allowable time span
|
|
||||||
Math.Abs(currentTime - NextFrame?.Time ?? 0) <= sixty_frame_time * 1.2;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update the current frame based on an incoming time value.
|
|
||||||
/// There are cases where we return a "must-use" time value that is different from the input.
|
|
||||||
/// This is to ensure accurate playback of replay data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="time">The time which we should use for finding the current frame.</param>
|
|
||||||
/// <returns>The usable time value. If null, we should not advance time as we do not have enough data.</returns>
|
|
||||||
public override double? SetFrameFromTime(double time)
|
|
||||||
{
|
|
||||||
currentDirection = time.CompareTo(currentTime);
|
|
||||||
if (currentDirection == 0) currentDirection = 1;
|
|
||||||
|
|
||||||
if (hasFrames)
|
|
||||||
{
|
|
||||||
//if we changed frames, we want to execute once *exactly* on the frame's time.
|
|
||||||
if (currentDirection == time.CompareTo(NextFrame.Time) && advanceFrame())
|
|
||||||
return currentTime = CurrentFrame.Time;
|
|
||||||
|
|
||||||
//if we didn't change frames, we need to ensure we are allowed to run frames in between, else return null.
|
|
||||||
if (inImportantSection)
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentTime = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class ReplayMouseState : MouseState
|
|
||||||
{
|
|
||||||
public ReplayMouseState(Vector2 position, IEnumerable<MouseButton> list)
|
|
||||||
{
|
|
||||||
Position = position;
|
|
||||||
list.ForEach(b => PressedButtons.Add(b));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class ReplayKeyboardState : KeyboardState
|
|
||||||
{
|
|
||||||
public ReplayKeyboardState(List<Key> keys)
|
|
||||||
{
|
|
||||||
Keys = keys;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
protected enum LegacyButtonState
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Left1 = 1,
|
|
||||||
Right1 = 2,
|
|
||||||
Left2 = 4,
|
|
||||||
Right2 = 8,
|
|
||||||
Smoke = 16
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class LegacyReplayFrame
|
|
||||||
{
|
|
||||||
public Vector2 Position => new Vector2(MouseX, MouseY);
|
|
||||||
|
|
||||||
public float MouseX;
|
|
||||||
public float MouseY;
|
|
||||||
public bool MouseLeft;
|
|
||||||
public bool MouseRight;
|
|
||||||
public bool MouseLeft1;
|
|
||||||
public bool MouseRight1;
|
|
||||||
public bool MouseLeft2;
|
|
||||||
public bool MouseRight2;
|
|
||||||
public LegacyButtonState ButtonState;
|
|
||||||
public double Time;
|
|
||||||
|
|
||||||
public LegacyReplayFrame(double time, float posX, float posY, LegacyButtonState buttonState)
|
|
||||||
{
|
|
||||||
MouseX = posX;
|
|
||||||
MouseY = posY;
|
|
||||||
ButtonState = buttonState;
|
|
||||||
SetButtonStates(buttonState);
|
|
||||||
Time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetButtonStates(LegacyButtonState buttonState)
|
|
||||||
{
|
|
||||||
ButtonState = buttonState;
|
|
||||||
MouseLeft = (buttonState & (LegacyButtonState.Left1 | LegacyButtonState.Left2)) > 0;
|
|
||||||
MouseLeft1 = (buttonState & LegacyButtonState.Left1) > 0;
|
|
||||||
MouseLeft2 = (buttonState & LegacyButtonState.Left2) > 0;
|
|
||||||
MouseRight = (buttonState & (LegacyButtonState.Right1 | LegacyButtonState.Right2)) > 0;
|
|
||||||
MouseRight1 = (buttonState & LegacyButtonState.Right1) > 0;
|
|
||||||
MouseRight2 = (buttonState & LegacyButtonState.Right2) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LegacyReplayFrame(Stream s) : this(new SerializationReader(s))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public LegacyReplayFrame(SerializationReader sr)
|
|
||||||
{
|
|
||||||
ButtonState = (LegacyButtonState)sr.ReadByte();
|
|
||||||
SetButtonStates(ButtonState);
|
|
||||||
|
|
||||||
byte bt = sr.ReadByte();
|
|
||||||
if (bt > 0)//Handle Pre-Taiko compatible replays.
|
|
||||||
SetButtonStates(LegacyButtonState.Right1);
|
|
||||||
|
|
||||||
MouseX = sr.ReadSingle();
|
|
||||||
MouseY = sr.ReadSingle();
|
|
||||||
Time = sr.ReadInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReadFromStream(SerializationReader sr)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteToStream(SerializationWriter sw)
|
|
||||||
{
|
|
||||||
sw.Write((byte)ButtonState);
|
|
||||||
sw.Write((byte)0);
|
|
||||||
sw.Write(MouseX);
|
|
||||||
sw.Write(MouseY);
|
|
||||||
sw.Write(Time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{Time}\t({MouseX},{MouseY})\t{MouseLeft}\t{MouseRight}\t{MouseLeft1}\t{MouseRight1}\t{MouseLeft2}\t{MouseRight2}\t{ButtonState}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -157,7 +157,7 @@ namespace osu.Game.Modes.Mods
|
|||||||
|
|
||||||
public void Apply(HitRenderer<T> hitRenderer)
|
public void Apply(HitRenderer<T> hitRenderer)
|
||||||
{
|
{
|
||||||
hitRenderer.InputManager.ReplayInputHandler = CreateReplayScore(hitRenderer.Beatmap)?.Replay?.CreateInputHandler();
|
hitRenderer.SetReplay(CreateReplayScore(hitRenderer.Beatmap)?.Replay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,16 +93,26 @@ namespace osu.Game.Modes.Objects.Drawables
|
|||||||
/// <returns>Whether a hit was processed.</returns>
|
/// <returns>Whether a hit was processed.</returns>
|
||||||
protected bool UpdateJudgement(bool userTriggered)
|
protected bool UpdateJudgement(bool userTriggered)
|
||||||
{
|
{
|
||||||
if (Judgement.Result != null)
|
IPartialJudgement partial = Judgement as IPartialJudgement;
|
||||||
|
|
||||||
|
// Never re-process non-partial hits
|
||||||
|
if (Judgement.Result != HitResult.None && partial == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Update the judgement state
|
||||||
double endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
|
double endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
|
||||||
|
|
||||||
Judgement.TimeOffset = Time.Current - endTime;
|
Judgement.TimeOffset = Time.Current - endTime;
|
||||||
|
|
||||||
|
// Update the judgement state
|
||||||
|
bool hadResult = Judgement.Result != HitResult.None;
|
||||||
CheckJudgement(userTriggered);
|
CheckJudgement(userTriggered);
|
||||||
|
|
||||||
if (Judgement.Result == null)
|
// Don't process judgements with no result
|
||||||
|
if (Judgement.Result == HitResult.None)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't process judgements that previously had results but the results were unchanged
|
||||||
|
if (hadResult && partial?.Changed != true)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (Judgement.Result)
|
switch (Judgement.Result)
|
||||||
@ -117,6 +127,9 @@ namespace osu.Game.Modes.Objects.Drawables
|
|||||||
|
|
||||||
OnJudgement?.Invoke(this);
|
OnJudgement?.Invoke(this);
|
||||||
|
|
||||||
|
if (partial != null)
|
||||||
|
partial.Changed = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,19 @@ namespace osu.Game.Modes.Objects.Drawables
|
|||||||
{
|
{
|
||||||
public enum HitResult
|
public enum HitResult
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the object has not been judged yet.
|
||||||
|
/// </summary>
|
||||||
|
[Description("")]
|
||||||
|
None,
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the object has been judged as a miss.
|
||||||
|
/// </summary>
|
||||||
[Description(@"Miss")]
|
[Description(@"Miss")]
|
||||||
Miss,
|
Miss,
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the object has been judged as a hit.
|
||||||
|
/// </summary>
|
||||||
[Description(@"Hit")]
|
[Description(@"Hit")]
|
||||||
Hit,
|
Hit,
|
||||||
}
|
}
|
||||||
|
@ -1,12 +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.Input.Handlers;
|
|
||||||
|
|
||||||
namespace osu.Game.Modes
|
|
||||||
{
|
|
||||||
public abstract class Replay
|
|
||||||
{
|
|
||||||
public virtual ReplayInputHandler CreateInputHandler() => null;
|
|
||||||
}
|
|
||||||
}
|
|
151
osu.Game/Modes/Replays/FramedReplayInputHandler.cs
Normal file
151
osu.Game/Modes/Replays/FramedReplayInputHandler.cs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
|
using osu.Game.Input.Handlers;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Input;
|
||||||
|
using KeyboardState = osu.Framework.Input.KeyboardState;
|
||||||
|
using MouseState = osu.Framework.Input.MouseState;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Replays
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The ReplayHandler will take a replay and handle the propagation of updates to the input stack.
|
||||||
|
/// It handles logic of any frames which *must* be executed.
|
||||||
|
/// </summary>
|
||||||
|
public class FramedReplayInputHandler : ReplayInputHandler
|
||||||
|
{
|
||||||
|
private readonly Replay replay;
|
||||||
|
|
||||||
|
protected List<ReplayFrame> Frames => replay.Frames;
|
||||||
|
|
||||||
|
public ReplayFrame CurrentFrame => !hasFrames ? null : Frames[currentFrameIndex];
|
||||||
|
public ReplayFrame NextFrame => !hasFrames ? null : Frames[nextFrameIndex];
|
||||||
|
|
||||||
|
private int currentFrameIndex;
|
||||||
|
|
||||||
|
private int nextFrameIndex => MathHelper.Clamp(currentFrameIndex + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1);
|
||||||
|
|
||||||
|
public FramedReplayInputHandler(Replay replay)
|
||||||
|
{
|
||||||
|
this.replay = replay;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool advanceFrame()
|
||||||
|
{
|
||||||
|
int newFrame = nextFrameIndex;
|
||||||
|
|
||||||
|
//ensure we aren't at an extent.
|
||||||
|
if (newFrame == currentFrameIndex) return false;
|
||||||
|
|
||||||
|
currentFrameIndex = newFrame;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPosition(Vector2 pos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2? position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!hasFrames)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Interpolation.ValueAt(currentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<InputState> GetPendingStates()
|
||||||
|
{
|
||||||
|
var buttons = new HashSet<MouseButton>();
|
||||||
|
if (CurrentFrame?.MouseLeft ?? false)
|
||||||
|
buttons.Add(MouseButton.Left);
|
||||||
|
if (CurrentFrame?.MouseRight ?? false)
|
||||||
|
buttons.Add(MouseButton.Right);
|
||||||
|
|
||||||
|
return new List<InputState>
|
||||||
|
{
|
||||||
|
new InputState
|
||||||
|
{
|
||||||
|
Mouse = new ReplayMouseState(ToScreenSpace(position ?? Vector2.Zero), buttons),
|
||||||
|
Keyboard = new ReplayKeyboardState(new List<Key>())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AtLastFrame => currentFrameIndex == Frames.Count - 1;
|
||||||
|
public bool AtFirstFrame => currentFrameIndex == 0;
|
||||||
|
|
||||||
|
public Vector2 Size => new Vector2(512, 384);
|
||||||
|
|
||||||
|
private const double sixty_frame_time = 1000.0 / 60;
|
||||||
|
|
||||||
|
private double currentTime;
|
||||||
|
private int currentDirection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When set, we will ensure frames executed by nested drawables are frame-accurate to replay data.
|
||||||
|
/// Disabling this can make replay playback smoother (useful for autoplay, currently).
|
||||||
|
/// </summary>
|
||||||
|
public bool FrameAccuratePlayback = true;
|
||||||
|
|
||||||
|
private bool hasFrames => Frames.Count > 0;
|
||||||
|
|
||||||
|
private bool inImportantSection =>
|
||||||
|
FrameAccuratePlayback &&
|
||||||
|
//a button is in a pressed state
|
||||||
|
((currentDirection > 0 ? CurrentFrame : NextFrame)?.IsImportant ?? false) &&
|
||||||
|
//the next frame is within an allowable time span
|
||||||
|
Math.Abs(currentTime - NextFrame?.Time ?? 0) <= sixty_frame_time * 1.2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update the current frame based on an incoming time value.
|
||||||
|
/// There are cases where we return a "must-use" time value that is different from the input.
|
||||||
|
/// This is to ensure accurate playback of replay data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="time">The time which we should use for finding the current frame.</param>
|
||||||
|
/// <returns>The usable time value. If null, we should not advance time as we do not have enough data.</returns>
|
||||||
|
public override double? SetFrameFromTime(double time)
|
||||||
|
{
|
||||||
|
currentDirection = time.CompareTo(currentTime);
|
||||||
|
if (currentDirection == 0) currentDirection = 1;
|
||||||
|
|
||||||
|
if (hasFrames)
|
||||||
|
{
|
||||||
|
//if we changed frames, we want to execute once *exactly* on the frame's time.
|
||||||
|
if (currentDirection == time.CompareTo(NextFrame.Time) && advanceFrame())
|
||||||
|
return currentTime = CurrentFrame.Time;
|
||||||
|
|
||||||
|
//if we didn't change frames, we need to ensure we are allowed to run frames in between, else return null.
|
||||||
|
if (inImportantSection)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ReplayMouseState : MouseState
|
||||||
|
{
|
||||||
|
public ReplayMouseState(Vector2 position, IEnumerable<MouseButton> list)
|
||||||
|
{
|
||||||
|
Position = position;
|
||||||
|
list.ForEach(b => PressedButtons.Add(b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ReplayKeyboardState : KeyboardState
|
||||||
|
{
|
||||||
|
public ReplayKeyboardState(List<Key> keys)
|
||||||
|
{
|
||||||
|
Keys = keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
osu.Game/Modes/Replays/Replay.cs
Normal file
12
osu.Game/Modes/Replays/Replay.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Replays
|
||||||
|
{
|
||||||
|
public class Replay
|
||||||
|
{
|
||||||
|
public List<ReplayFrame> Frames = new List<ReplayFrame>();
|
||||||
|
}
|
||||||
|
}
|
18
osu.Game/Modes/Replays/ReplayButtonState.cs
Normal file
18
osu.Game/Modes/Replays/ReplayButtonState.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Replays
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum ReplayButtonState
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Left1 = 1,
|
||||||
|
Right1 = 2,
|
||||||
|
Left2 = 4,
|
||||||
|
Right2 = 8,
|
||||||
|
Smoke = 16
|
||||||
|
}
|
||||||
|
}
|
71
osu.Game/Modes/Replays/ReplayFrame.cs
Normal file
71
osu.Game/Modes/Replays/ReplayFrame.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace osu.Game.Modes.Replays
|
||||||
|
{
|
||||||
|
public class ReplayFrame
|
||||||
|
{
|
||||||
|
public Vector2 Position => new Vector2(MouseX, MouseY);
|
||||||
|
|
||||||
|
public bool IsImportant => MouseLeft || MouseRight;
|
||||||
|
|
||||||
|
public float MouseX;
|
||||||
|
public float MouseY;
|
||||||
|
|
||||||
|
public bool MouseLeft => MouseLeft1 || MouseLeft2;
|
||||||
|
public bool MouseRight => MouseRight1 || MouseRight2;
|
||||||
|
|
||||||
|
public bool MouseLeft1
|
||||||
|
{
|
||||||
|
get { return (ButtonState & ReplayButtonState.Left1) > 0; }
|
||||||
|
set { setButtonState(ReplayButtonState.Left1, value); }
|
||||||
|
}
|
||||||
|
public bool MouseRight1
|
||||||
|
{
|
||||||
|
get { return (ButtonState & ReplayButtonState.Right1) > 0; }
|
||||||
|
set { setButtonState(ReplayButtonState.Right1, value); }
|
||||||
|
}
|
||||||
|
public bool MouseLeft2
|
||||||
|
{
|
||||||
|
get { return (ButtonState & ReplayButtonState.Left2) > 0; }
|
||||||
|
set { setButtonState(ReplayButtonState.Left2, value); }
|
||||||
|
}
|
||||||
|
public bool MouseRight2
|
||||||
|
{
|
||||||
|
get { return (ButtonState & ReplayButtonState.Right2) > 0; }
|
||||||
|
set { setButtonState(ReplayButtonState.Right2, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setButtonState(ReplayButtonState singleButton, bool pressed)
|
||||||
|
{
|
||||||
|
if (pressed)
|
||||||
|
ButtonState |= singleButton;
|
||||||
|
else
|
||||||
|
ButtonState &= ~singleButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Time;
|
||||||
|
|
||||||
|
public ReplayButtonState ButtonState;
|
||||||
|
|
||||||
|
protected ReplayFrame()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReplayFrame(double time, float posX, float posY, ReplayButtonState buttonState)
|
||||||
|
{
|
||||||
|
MouseX = posX;
|
||||||
|
MouseY = posY;
|
||||||
|
ButtonState = buttonState;
|
||||||
|
Time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Time}\t({MouseX},{MouseY})\t{MouseLeft}\t{MouseRight}\t{MouseLeft1}\t{MouseRight1}\t{MouseLeft2}\t{MouseRight2}\t{ButtonState}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,11 +2,13 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Modes.Mods;
|
using osu.Game.Modes.Mods;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using osu.Game.Modes.Replays;
|
||||||
|
|
||||||
namespace osu.Game.Modes.Scoring
|
namespace osu.Game.Modes.Scoring
|
||||||
{
|
{
|
||||||
@ -45,11 +47,34 @@ namespace osu.Game.Modes.Scoring
|
|||||||
public DateTime Date;
|
public DateTime Date;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a legacy replay which is read from a stream.
|
/// Creates a replay which is read from a stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader">The stream reader.</param>
|
/// <param name="reader">The stream reader.</param>
|
||||||
/// <returns>The replay.</returns>
|
/// <returns>The replay.</returns>
|
||||||
public virtual Replay CreateLegacyReplayFrom(StreamReader reader) => new LegacyReplay(reader);
|
public virtual Replay CreateReplay(StreamReader reader)
|
||||||
|
{
|
||||||
|
var frames = new List<ReplayFrame>();
|
||||||
|
|
||||||
|
float lastTime = 0;
|
||||||
|
|
||||||
|
foreach (var l in reader.ReadToEnd().Split(','))
|
||||||
|
{
|
||||||
|
var split = l.Split('|');
|
||||||
|
|
||||||
|
if (split.Length < 4 || float.Parse(split[0]) < 0) continue;
|
||||||
|
|
||||||
|
lastTime += float.Parse(split[0]);
|
||||||
|
|
||||||
|
frames.Add(new ReplayFrame(
|
||||||
|
lastTime,
|
||||||
|
float.Parse(split[1]),
|
||||||
|
384 - float.Parse(split[2]),
|
||||||
|
(ReplayButtonState)int.Parse(split[3])
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Replay { Frames = frames };
|
||||||
|
}
|
||||||
|
|
||||||
// [JsonProperty(@"count50")] 0,
|
// [JsonProperty(@"count50")] 0,
|
||||||
//[JsonProperty(@"count100")] 0,
|
//[JsonProperty(@"count100")] 0,
|
||||||
|
@ -140,25 +140,45 @@ namespace osu.Game.Modes.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="judgement">The judgement to add.</param>
|
/// <param name="judgement">The judgement to add.</param>
|
||||||
protected void AddJudgement(TJudgement judgement)
|
protected void AddJudgement(TJudgement judgement)
|
||||||
|
{
|
||||||
|
bool exists = Judgements.Contains(judgement);
|
||||||
|
|
||||||
|
if (!exists)
|
||||||
{
|
{
|
||||||
Judgements.Add(judgement);
|
Judgements.Add(judgement);
|
||||||
|
OnNewJudgement(judgement);
|
||||||
|
|
||||||
OnNewJugement(judgement);
|
judgement.ComboAtHit = Combo.Value;
|
||||||
|
}
|
||||||
judgement.ComboAtHit = (ulong)Combo.Value;
|
else
|
||||||
|
OnJudgementChanged(judgement);
|
||||||
|
|
||||||
UpdateFailed();
|
UpdateFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Reset()
|
protected override void Reset()
|
||||||
{
|
{
|
||||||
|
base.Reset();
|
||||||
|
|
||||||
Judgements.Clear();
|
Judgements.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update any values that potentially need post-processing on a judgement change.
|
/// Updates any values that need post-processing. Invoked when a new judgement has occurred.
|
||||||
|
/// <para>
|
||||||
|
/// This is not triggered when existing judgements are changed - for that see <see cref="OnJudgementChanged(TJudgement)"/>.
|
||||||
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="judgement">The judgement that triggered this calculation.</param>
|
/// <param name="judgement">The judgement that triggered this calculation.</param>
|
||||||
protected abstract void OnNewJugement(TJudgement judgement);
|
protected abstract void OnNewJudgement(TJudgement judgement);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates any values that need post-processing. Invoked when an existing judgement has changed.
|
||||||
|
/// <para>
|
||||||
|
/// This is not triggered when a new judgement has occurred - for that see <see cref="OnNewJudgement(TJudgement)"/>.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="judgement">The judgement that triggered this calculation.</param>
|
||||||
|
protected virtual void OnJudgementChanged(TJudgement judgement) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -213,7 +213,7 @@ namespace osu.Game.Modes.UI
|
|||||||
|
|
||||||
protected class TransformComboRoll : Transform<int>
|
protected class TransformComboRoll : Transform<int>
|
||||||
{
|
{
|
||||||
protected override int CurrentValue
|
public override int CurrentValue
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Modes.UI
|
|||||||
|
|
||||||
protected class TransformComboResult : Transform<ulong>
|
protected class TransformComboResult : Transform<ulong>
|
||||||
{
|
{
|
||||||
protected override ulong CurrentValue
|
public override ulong CurrentValue
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using osu.Game.Modes.Replays;
|
||||||
using osu.Game.Modes.Scoring;
|
using osu.Game.Modes.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Modes.UI
|
namespace osu.Game.Modes.UI
|
||||||
@ -68,6 +69,14 @@ namespace osu.Game.Modes.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The input manager.</returns>
|
/// <returns>The input manager.</returns>
|
||||||
protected virtual KeyConversionInputManager CreateKeyConversionInputManager() => new KeyConversionInputManager();
|
protected virtual KeyConversionInputManager CreateKeyConversionInputManager() => new KeyConversionInputManager();
|
||||||
|
|
||||||
|
protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a replay to be used, overriding local input.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="replay">The replay, null for local input.</param>
|
||||||
|
public void SetReplay(Replay replay) => InputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -149,7 +158,7 @@ namespace osu.Game.Modes.UI
|
|||||||
public event Action<TJudgement> OnJudgement;
|
public event Action<TJudgement> OnJudgement;
|
||||||
|
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result.HasValue);
|
protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result != HitResult.None);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The playfield.
|
/// The playfield.
|
||||||
|
@ -125,7 +125,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
Beatmap.Value = BeatmapDatabase.GetWorkingBeatmap(s.Beatmap);
|
Beatmap.Value = BeatmapDatabase.GetWorkingBeatmap(s.Beatmap);
|
||||||
|
|
||||||
menu.Push(new PlayerLoader(new Player { ReplayInputHandler = s.Replay.CreateInputHandler() }));
|
menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -150,7 +150,7 @@ namespace osu.Game
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
(screenStack = new Loader()).LoadAsync(this, d =>
|
LoadComponentAsync(screenStack = new Loader(), d =>
|
||||||
{
|
{
|
||||||
screenStack.ModePushed += screenAdded;
|
screenStack.ModePushed += screenAdded;
|
||||||
screenStack.Exited += screenRemoved;
|
screenStack.Exited += screenRemoved;
|
||||||
@ -158,27 +158,27 @@ namespace osu.Game
|
|||||||
});
|
});
|
||||||
|
|
||||||
//overlay elements
|
//overlay elements
|
||||||
(chat = new ChatOverlay { Depth = 0 }).LoadAsync(this, overlayContent.Add);
|
LoadComponentAsync(chat = new ChatOverlay { Depth = 0 }, overlayContent.Add);
|
||||||
(options = new OptionsOverlay { Depth = -1 }).LoadAsync(this, overlayContent.Add);
|
LoadComponentAsync(options = new OptionsOverlay { Depth = -1 }, overlayContent.Add);
|
||||||
(musicController = new MusicController
|
LoadComponentAsync(musicController = new MusicController
|
||||||
{
|
{
|
||||||
Depth = -2,
|
Depth = -2,
|
||||||
Position = new Vector2(0, Toolbar.HEIGHT),
|
Position = new Vector2(0, Toolbar.HEIGHT),
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
}).LoadAsync(this, overlayContent.Add);
|
}, overlayContent.Add);
|
||||||
|
|
||||||
(notificationManager = new NotificationManager
|
LoadComponentAsync(notificationManager = new NotificationManager
|
||||||
{
|
{
|
||||||
Depth = -2,
|
Depth = -2,
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
}).LoadAsync(this, overlayContent.Add);
|
}, overlayContent.Add);
|
||||||
|
|
||||||
(dialogOverlay = new DialogOverlay
|
LoadComponentAsync(dialogOverlay = new DialogOverlay
|
||||||
{
|
{
|
||||||
Depth = -4,
|
Depth = -4,
|
||||||
}).LoadAsync(this, overlayContent.Add);
|
}, overlayContent.Add);
|
||||||
|
|
||||||
Logger.NewEntry += entry =>
|
Logger.NewEntry += entry =>
|
||||||
{
|
{
|
||||||
@ -195,12 +195,12 @@ namespace osu.Game
|
|||||||
Dependencies.Cache(notificationManager);
|
Dependencies.Cache(notificationManager);
|
||||||
Dependencies.Cache(dialogOverlay);
|
Dependencies.Cache(dialogOverlay);
|
||||||
|
|
||||||
(Toolbar = new Toolbar
|
LoadComponentAsync(Toolbar = new Toolbar
|
||||||
{
|
{
|
||||||
Depth = -3,
|
Depth = -3,
|
||||||
OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); },
|
OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); },
|
||||||
OnPlayModeChange = delegate (PlayMode m) { PlayMode.Value = m; },
|
OnPlayModeChange = m => PlayMode.Value = m,
|
||||||
}).LoadAsync(this, t =>
|
}, t =>
|
||||||
{
|
{
|
||||||
PlayMode.ValueChanged += delegate { Toolbar.SetGameMode(PlayMode.Value); };
|
PlayMode.ValueChanged += delegate { Toolbar.SetGameMode(PlayMode.Value); };
|
||||||
PlayMode.TriggerChange();
|
PlayMode.TriggerChange();
|
||||||
|
@ -347,12 +347,9 @@ namespace osu.Game.Overlays
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
dragContainer.Add(new AsyncLoadContainer
|
dragContainer.Add(new AsyncLoadWrapper(new MusicControllerBackground(beatmap)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
OnLoadComplete = d =>
|
||||||
Depth = float.MaxValue,
|
|
||||||
Children = new[] { new MusicControllerBackground(beatmap) },
|
|
||||||
FinishedLoading = d =>
|
|
||||||
{
|
{
|
||||||
switch (direction)
|
switch (direction)
|
||||||
{
|
{
|
||||||
@ -370,6 +367,9 @@ namespace osu.Game.Overlays
|
|||||||
currentBackground.Expire();
|
currentBackground.Expire();
|
||||||
currentBackground = d;
|
currentBackground = d;
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Depth = float.MaxValue,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -65,14 +65,13 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
|
|
||||||
foreach (PlayMode m in Ruleset.PlayModes)
|
foreach (PlayMode m in Ruleset.PlayModes)
|
||||||
{
|
{
|
||||||
var localMode = m;
|
|
||||||
modeButtons.Add(new ToolbarModeButton
|
modeButtons.Add(new ToolbarModeButton
|
||||||
{
|
{
|
||||||
Mode = m,
|
Mode = m,
|
||||||
Action = delegate
|
Action = delegate
|
||||||
{
|
{
|
||||||
SetGameMode(localMode);
|
SetGameMode(m);
|
||||||
OnPlayModeChange?.Invoke(localMode);
|
OnPlayModeChange?.Invoke(m);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
@ -27,21 +26,13 @@ namespace osu.Game.Screens
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Framework.Game game;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(Framework.Game game)
|
|
||||||
{
|
|
||||||
this.game = game;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Push(Screen screen)
|
public override bool Push(Screen screen)
|
||||||
{
|
{
|
||||||
// When trying to push a non-loaded GameMode, load it asynchronously and re-invoke Push
|
// When trying to push a non-loaded GameMode, load it asynchronously and re-invoke Push
|
||||||
// once it's done.
|
// once it's done.
|
||||||
if (screen.LoadState == LoadState.NotLoaded)
|
if (screen.LoadState == LoadState.NotLoaded)
|
||||||
{
|
{
|
||||||
screen.LoadAsync(game, d => Push((BackgroundScreen)d));
|
LoadComponentAsync(screen, d => Push((BackgroundScreen)d));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Screens.Backgrounds
|
|||||||
{
|
{
|
||||||
var newBackground = beatmap == null ? new Background(@"Backgrounds/bg1") : new BeatmapBackground(beatmap);
|
var newBackground = beatmap == null ? new Background(@"Backgrounds/bg1") : new BeatmapBackground(beatmap);
|
||||||
|
|
||||||
newBackground.LoadAsync(Game, delegate
|
LoadComponentAsync(newBackground, delegate
|
||||||
{
|
{
|
||||||
float newDepth = 0;
|
float newDepth = 0;
|
||||||
if (background != null)
|
if (background != null)
|
||||||
|
@ -20,9 +20,9 @@ namespace osu.Game.Screens
|
|||||||
private void load(OsuGame game)
|
private void load(OsuGame game)
|
||||||
{
|
{
|
||||||
if (game.IsDeployedBuild)
|
if (game.IsDeployedBuild)
|
||||||
new Disclaimer().LoadAsync(game, d => Push((Screen)d));
|
LoadComponentAsync(new Disclaimer(), d => Push((Screen)d));
|
||||||
else
|
else
|
||||||
new Intro().LoadAsync(game, d => Push((Screen)d));
|
LoadComponentAsync(new Intro(), d => Push((Screen)d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,9 @@ namespace osu.Game.Screens.Menu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuGame game, OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
(intro = new Intro()).LoadAsync(game);
|
LoadComponentAsync(intro = new Intro());
|
||||||
|
|
||||||
iconColour = colours.Yellow;
|
iconColour = colours.Yellow;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user