1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-17 03:43:52 +08:00

Merge branch 'master' into taiko_note_circle

This commit is contained in:
Dan Balasescu 2017-03-23 14:29:24 +09:00 committed by GitHub
commit a40338614a
173 changed files with 2369 additions and 991 deletions

@ -1 +1 @@
Subproject commit e6394035d443d4498b71e845e5763dd3faf98c7c Subproject commit 06e426da039f7bb54aedf5d82c21b8d858a0310e

View File

@ -53,7 +53,7 @@ namespace osu.Desktop.Deploy
private static string nupkgFilename(string ver) => $"{PackageName}.{ver}.nupkg"; private static string nupkgFilename(string ver) => $"{PackageName}.{ver}.nupkg";
private static string nupkgDistroFilename(string ver) => $"{PackageName}-{ver}-full.nupkg"; private static string nupkgDistroFilename(string ver) => $"{PackageName}-{ver}-full.nupkg";
private static Stopwatch sw = new Stopwatch(); private static readonly Stopwatch sw = new Stopwatch();
private static string codeSigningPassword; private static string codeSigningPassword;

View File

@ -0,0 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
namespace osu.Desktop.VisualTests.Beatmaps
{
public class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
{
this.beatmap = beatmap;
}
private readonly Beatmap beatmap;
protected override Beatmap GetBeatmap() => beatmap;
protected override Texture GetBackground() => null;
protected override Track GetTrack() => null;
}
}

View File

@ -10,7 +10,7 @@ namespace osu.Desktop.VisualTests
{ {
public class Benchmark : OsuGameBase public class Benchmark : OsuGameBase
{ {
private double timePerTest = 200; private const double time_per_test = 200;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
@ -27,7 +27,7 @@ namespace osu.Desktop.VisualTests
TestBrowser f = new TestBrowser(); TestBrowser f = new TestBrowser();
Add(f); Add(f);
Console.WriteLine($@"{Time}: Running {f.TestCount} tests for {timePerTest}ms each..."); Console.WriteLine($@"{Time}: Running {f.TestCount} tests for {time_per_test}ms each...");
for (int i = 1; i < f.TestCount; i++) for (int i = 1; i < f.TestCount; i++)
{ {
@ -36,10 +36,10 @@ namespace osu.Desktop.VisualTests
{ {
f.LoadTest(loadableCase); f.LoadTest(loadableCase);
Console.WriteLine($@"{Time}: Switching to test #{loadableCase}"); Console.WriteLine($@"{Time}: Switching to test #{loadableCase}");
}, loadableCase * timePerTest); }, loadableCase * time_per_test);
} }
Scheduler.AddDelayed(Host.Exit, f.TestCount * timePerTest); Scheduler.AddDelayed(Host.Exit, f.TestCount * time_per_test);
} }
} }
} }

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using osu.Framework.Screens.Testing; using osu.Framework.Screens.Testing;
using osu.Game.Screens.Tournament; using osu.Game.Screens.Tournament;
using osu.Game.Screens.Tournament.Teams; using osu.Game.Screens.Tournament.Teams;
using osu.Game.Users;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
@ -24,57 +25,57 @@ namespace osu.Desktop.VisualTests.Tests
private class TestTeamList : ITeamList private class TestTeamList : ITeamList
{ {
public IEnumerable<Team> Teams { get; } = new[] public IEnumerable<Country> Teams { get; } = new[]
{ {
new Team new Country
{ {
FlagName = "GB", FlagName = "GB",
FullName = "United Kingdom", FullName = "United Kingdom",
Acronym = "UK" Acronym = "UK"
}, },
new Team new Country
{ {
FlagName = "FR", FlagName = "FR",
FullName = "France", FullName = "France",
Acronym = "FRA" Acronym = "FRA"
}, },
new Team new Country
{ {
FlagName = "CN", FlagName = "CN",
FullName = "China", FullName = "China",
Acronym = "CHN" Acronym = "CHN"
}, },
new Team new Country
{ {
FlagName = "AU", FlagName = "AU",
FullName = "Australia", FullName = "Australia",
Acronym = "AUS" Acronym = "AUS"
}, },
new Team new Country
{ {
FlagName = "JP", FlagName = "JP",
FullName = "Japan", FullName = "Japan",
Acronym = "JPN" Acronym = "JPN"
}, },
new Team new Country
{ {
FlagName = "RO", FlagName = "RO",
FullName = "Romania", FullName = "Romania",
Acronym = "ROM" Acronym = "ROM"
}, },
new Team new Country
{ {
FlagName = "IT", FlagName = "IT",
FullName = "Italy", FullName = "Italy",
Acronym = "PIZZA" Acronym = "PIZZA"
}, },
new Team new Country
{ {
FlagName = "VE", FlagName = "VE",
FullName = "Venezuela", FullName = "Venezuela",
Acronym = "VNZ" Acronym = "VNZ"
}, },
new Team new Country
{ {
FlagName = "US", FlagName = "US",
FullName = "United States of America", FullName = "United States of America",

View File

@ -8,7 +8,6 @@ using osu.Framework.MathUtils;
using osu.Framework.Screens.Testing; using osu.Framework.Screens.Testing;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.IO;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Modes.Catch.UI; using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Mania.UI; using osu.Game.Modes.Mania.UI;
@ -17,6 +16,7 @@ using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI; using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.Taiko.UI; using osu.Game.Modes.Taiko.UI;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Desktop.VisualTests.Beatmaps;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
@ -95,16 +95,5 @@ namespace osu.Desktop.VisualTests.Tests
} }
}); });
} }
private class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
{
Beatmap = beatmap;
}
protected override ArchiveReader GetReader() => null;
}
} }
} }

View File

@ -21,7 +21,7 @@ namespace osu.Desktop.VisualTests.Tests
{ {
internal class TestCaseHitObjects : TestCase internal class TestCaseHitObjects : TestCase
{ {
private FramedClock framedClock; private readonly FramedClock framedClock;
private bool auto; private bool auto;
@ -34,7 +34,7 @@ namespace osu.Desktop.VisualTests.Tests
private HitObjectType mode = HitObjectType.Slider; private HitObjectType mode = HitObjectType.Slider;
private BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 }; private readonly BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 };
private Container playfieldContainer; private Container playfieldContainer;
private Container approachContainer; private Container approachContainer;

View File

@ -0,0 +1,225 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Screens.Testing;
using osu.Game.Modes;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Osu.Mods;
using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Users;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseLeaderboard : TestCase
{
public override string Description => @"From song select";
private Leaderboard leaderboard;
private void newScores()
{
var scores = new[]
{
new Score
{
Rank = ScoreRank.XH,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 6602580,
Username = @"waaiiru",
Country = new Country
{
FullName = @"Spain",
FlagName = @"ES",
},
},
},
new Score
{
Rank = ScoreRank.X,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 4608074,
Username = @"Skycries",
Country = new Country
{
FullName = @"Brazil",
FlagName = @"BR",
},
},
},
new Score
{
Rank = ScoreRank.SH,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 1014222,
Username = @"eLy",
Country = new Country
{
FullName = @"Japan",
FlagName = @"JP",
},
},
},
new Score
{
Rank = ScoreRank.S,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 1541390,
Username = @"Toukai",
Country = new Country
{
FullName = @"Canada",
FlagName = @"CA",
},
},
},
new Score
{
Rank = ScoreRank.A,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 2243452,
Username = @"Satoruu",
Country = new Country
{
FullName = @"Venezuela",
FlagName = @"VE",
},
},
},
new Score
{
Rank = ScoreRank.B,
Accuracy = 98.26,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 2705430,
Username = @"Mooha",
Country = new Country
{
FullName = @"France",
FlagName = @"FR",
},
},
},
new Score
{
Rank = ScoreRank.C,
Accuracy = 96.54,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 7151382,
Username = @"Mayuri Hana",
Country = new Country
{
FullName = @"Thailand",
FlagName = @"TH",
},
},
},
new Score
{
Rank = ScoreRank.F,
Accuracy = 60.25,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 2051389,
Username = @"FunOrange",
Country = new Country
{
FullName = @"Canada",
FlagName = @"CA",
},
},
},
new Score
{
Rank = ScoreRank.F,
Accuracy = 51.40,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 6169483,
Username = @"-Hebel-",
Country = new Country
{
FullName = @"Mexico",
FlagName = @"MX",
},
},
},
new Score
{
Rank = ScoreRank.F,
Accuracy = 42.22,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 6702666,
Username = @"prhtnsm",
Country = new Country
{
FullName = @"Germany",
FlagName = @"DE",
},
},
},
};
leaderboard.Scores = scores;
}
public override void Reset()
{
base.Reset();
Add(leaderboard = new Leaderboard
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(550f, 450f),
});
AddButton(@"New Scores", newScores);
newScores();
}
}
}

View File

@ -95,7 +95,7 @@ namespace osu.Desktop.VisualTests.Tests
progressingNotifications.Add(n); progressingNotifications.Add(n);
} }
private List<ProgressNotification> progressingNotifications = new List<ProgressNotification>(); private readonly List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
private void sendProgress1() private void sendProgress1()
{ {

View File

@ -8,13 +8,13 @@ using osu.Framework.Screens.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using OpenTK; using OpenTK;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps.IO;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Modes; using osu.Game.Modes;
using osu.Game.Modes.Objects; using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Desktop.VisualTests.Beatmaps;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
@ -23,7 +23,6 @@ namespace osu.Desktop.VisualTests.Tests
protected Player Player; protected Player Player;
private BeatmapDatabase db; private BeatmapDatabase db;
public override string Description => @"Showing everything to play the game."; public override string Description => @"Showing everything to play the game.";
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -97,16 +96,5 @@ namespace osu.Desktop.VisualTests.Tests
Beatmap = beatmap Beatmap = beatmap
}; };
} }
private class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
{
Beatmap = beatmap;
}
protected override ArchiveReader GetReader() => null;
}
} }
} }

View File

@ -205,9 +205,14 @@
<Compile Include="Tests\TestCaseModSelectOverlay.cs" /> <Compile Include="Tests\TestCaseModSelectOverlay.cs" />
<Compile Include="Tests\TestCaseDialogOverlay.cs" /> <Compile Include="Tests\TestCaseDialogOverlay.cs" />
<Compile Include="Tests\TestCaseBeatmapOptionsOverlay.cs" /> <Compile Include="Tests\TestCaseBeatmapOptionsOverlay.cs" />
<Compile Include="Tests\TestCaseLeaderboard.cs" />
<Compile Include="Beatmaps\TestWorkingBeatmap.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<ItemGroup /> <ItemGroup />
<ItemGroup>
<Folder Include="Beatmaps\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -17,7 +17,7 @@ namespace osu.Desktop
{ {
internal class OsuGameDesktop : OsuGame internal class OsuGameDesktop : OsuGame
{ {
private VersionManager versionManager; private readonly VersionManager versionManager;
public OsuGameDesktop(string[] args = null) public OsuGameDesktop(string[] args = null)
: base(args) : base(args)

View File

@ -215,6 +215,7 @@ namespace osu.Desktop.Overlays
Origin = Anchor.Centre, Origin = Anchor.Centre,
Icon = FontAwesome.fa_upload, Icon = FontAwesome.fa_upload,
Colour = Color4.White, Colour = Color4.White,
TextSize = 20
} }
}); });
} }

View File

@ -12,7 +12,7 @@ namespace osu.Game.Modes.Catch.Objects.Drawable
{ {
internal class DrawableFruit : Sprite internal class DrawableFruit : Sprite
{ {
private CatchBaseHit h; private readonly CatchBaseHit h;
public DrawableFruit(CatchBaseHit h) public DrawableFruit(CatchBaseHit h)
{ {
@ -29,7 +29,7 @@ namespace osu.Game.Modes.Catch.Objects.Drawable
{ {
Texture = textures.Get(@"Menu/logo"); Texture = textures.Get(@"Menu/logo");
double duration = 0; const double duration = 0;
Transforms.Add(new TransformPosition { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position, -0.1f), EndValue = new Vector2(h.Position, 0.9f) }); Transforms.Add(new TransformPosition { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position, -0.1f), EndValue = new Vector2(h.Position, 0.9f) });
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 }); Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 });

View File

@ -26,7 +26,7 @@ namespace osu.Game.Modes.Mania.Objects.Drawable
{ {
Texture = textures.Get(@"Menu/logo"); Texture = textures.Get(@"Menu/logo");
double duration = 0; const double duration = 0;
Transforms.Add(new TransformPositionY { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f }); Transforms.Add(new TransformPositionY { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f });
Transforms.Add(new TransformAlpha { StartTime = note.StartTime + duration + 200, EndTime = note.StartTime + duration + 400, StartValue = 1, EndValue = 0 }); Transforms.Add(new TransformAlpha { StartTime = note.StartTime + duration + 200, EndTime = note.StartTime + duration + 400, StartValue = 1, EndValue = 0 });

View File

@ -81,7 +81,7 @@ namespace osu.Game.Modes.Osu.Beatmaps
if (endIndex == -1) if (endIndex == -1)
endIndex = hitObjects.Count - 1; endIndex = hitObjects.Count - 1;
int stackDistance = 3; const int stack_distance = 3;
float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * stackLeniency; float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * stackLeniency;
// Reset stacking inside the update range // Reset stacking inside the update range
@ -108,8 +108,8 @@ namespace osu.Game.Modes.Osu.Beatmaps
//We are no longer within stacking range of the next object. //We are no longer within stacking range of the next object.
break; break;
if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stackDistance || if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stack_distance ||
stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stackDistance) stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
{ {
stackBaseIndex = n; stackBaseIndex = n;
@ -174,14 +174,14 @@ namespace osu.Game.Modes.Osu.Beatmaps
* o <- hitCircle has stack of -1 * o <- hitCircle has stack of -1
* o <- hitCircle has stack of -2 * o <- hitCircle has stack of -2
*/ */
if (objectN is Slider && Vector2.Distance(objectN.EndPosition, objectI.Position) < stackDistance) if (objectN is Slider && Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
{ {
int offset = objectI.StackHeight - objectN.StackHeight + 1; int offset = objectI.StackHeight - objectN.StackHeight + 1;
for (int j = n + 1; j <= i; j++) for (int j = n + 1; j <= i; j++)
{ {
//For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above). //For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
OsuHitObject objectJ = hitObjects[j]; OsuHitObject objectJ = hitObjects[j];
if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stackDistance) if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stack_distance)
objectJ.StackHeight -= offset; objectJ.StackHeight -= offset;
} }
@ -190,7 +190,7 @@ namespace osu.Game.Modes.Osu.Beatmaps
break; break;
} }
if (Vector2.Distance(objectN.Position, objectI.Position) < stackDistance) if (Vector2.Distance(objectN.Position, objectI.Position) < stack_distance)
{ {
//Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out. //Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out.
//NOTE: Sliders with start positions stacking are a special case that is also handled here. //NOTE: Sliders with start positions stacking are a special case that is also handled here.
@ -214,7 +214,7 @@ namespace osu.Game.Modes.Osu.Beatmaps
//We are no longer within stacking range of the previous object. //We are no longer within stacking range of the previous object.
break; break;
if (Vector2.Distance(objectN.EndPosition, objectI.Position) < stackDistance) if (Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
{ {
objectN.StackHeight = objectI.StackHeight + 1; objectN.StackHeight = objectI.StackHeight + 1;
objectI = objectN; objectI = objectN;

View File

@ -13,15 +13,15 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach
{ {
private OsuHitObject osuObject; private readonly OsuHitObject osuObject;
public ApproachCircle ApproachCircle; public ApproachCircle ApproachCircle;
private CirclePiece circle; private readonly CirclePiece circle;
private RingPiece ring; private readonly RingPiece ring;
private FlashPiece flash; private readonly FlashPiece flash;
private ExplodePiece explode; private readonly ExplodePiece explode;
private NumberPiece number; private readonly NumberPiece number;
private GlowPiece glow; private readonly GlowPiece glow;
public DrawableHitCircle(OsuHitObject h) : base(h) public DrawableHitCircle(OsuHitObject h) : base(h)
{ {
@ -111,8 +111,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
if (!IsLoaded) return;
base.UpdateState(state); base.UpdateState(state);
ApproachCircle.FadeOut(); ApproachCircle.FadeOut();

View File

@ -22,8 +22,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
if (!IsLoaded) return;
Flush(); Flush();
UpdateInitialState(); UpdateInitialState();

View File

@ -13,18 +13,18 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach
{ {
private Slider slider; private readonly Slider slider;
private DrawableHitCircle initialCircle; private readonly DrawableHitCircle initialCircle;
private List<ISliderProgress> components = new List<ISliderProgress>(); private readonly List<ISliderProgress> components = new List<ISliderProgress>();
private Container<DrawableSliderTick> ticks; private readonly Container<DrawableSliderTick> ticks;
private SliderBody body; private readonly SliderBody body;
private SliderBall ball; private readonly SliderBall ball;
private SliderBouncer bouncer2; private readonly SliderBouncer bouncer2;
public DrawableSlider(Slider s) : base(s) public DrawableSlider(Slider s) : base(s)
{ {

View File

@ -18,7 +18,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
public class DrawableSliderTick : DrawableOsuHitObject public class DrawableSliderTick : DrawableOsuHitObject
{ {
private SliderTick sliderTick; private readonly SliderTick sliderTick;
public double FadeInTime; public double FadeInTime;
public double FadeOutTime; public double FadeOutTime;
@ -95,8 +95,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
if (!IsLoaded) return;
base.UpdateState(state); base.UpdateState(state);
switch (state) switch (state)

View File

@ -15,12 +15,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
public class DrawableSpinner : DrawableOsuHitObject public class DrawableSpinner : DrawableOsuHitObject
{ {
private Spinner spinner; private readonly Spinner spinner;
private SpinnerDisc disc; private readonly SpinnerDisc disc;
private SpinnerBackground background; private readonly SpinnerBackground background;
private Container circleContainer; private readonly Container circleContainer;
private DrawableHitCircle circle; private readonly DrawableHitCircle circle;
public DrawableSpinner(Spinner s) : base(s) public DrawableSpinner(Spinner s) : base(s)
{ {
@ -108,9 +108,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
private Vector2 scaleToCircle => circle.Scale * circle.DrawWidth / DrawWidth * 0.95f; private Vector2 scaleToCircle => circle.Scale * circle.DrawWidth / DrawWidth * 0.95f;
private float spinsPerMinuteNeeded = 100 + 5 * 15; //TODO: read per-map OD and place it on the 5 private const float spins_per_minute_needed = 100 + 5 * 15; //TODO: read per-map OD and place it on the 5
private float rotationsNeeded => (float)(spinsPerMinuteNeeded * (spinner.EndTime - spinner.StartTime) / 60000f); private float rotationsNeeded => (float)(spins_per_minute_needed * (spinner.EndTime - spinner.StartTime) / 60000f);
public float Progress => MathHelper.Clamp(disc.RotationAbsolute / 360 / rotationsNeeded, 0, 1); public float Progress => MathHelper.Clamp(disc.RotationAbsolute / 360 / rotationsNeeded, 0, 1);
@ -134,8 +134,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
if (!IsLoaded) return;
base.UpdateState(state); base.UpdateState(state);
Delay(spinner.Duration, true); Delay(spinner.Duration, true);

View File

@ -17,8 +17,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
public class HitExplosion : FillFlowContainer public class HitExplosion : FillFlowContainer
{ {
private readonly OsuJudgementInfo judgement; private readonly OsuJudgementInfo judgement;
private SpriteText line1; private readonly SpriteText line1;
private SpriteText line2; private readonly SpriteText line2;
public HitExplosion(OsuJudgementInfo judgement, OsuHitObject h = null) public HitExplosion(OsuJudgementInfo judgement, OsuHitObject h = null)
{ {

View File

@ -11,7 +11,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
public class ApproachCircle : Container public class ApproachCircle : Container
{ {
private Sprite approachCircle; private readonly Sprite approachCircle;
public ApproachCircle() public ApproachCircle()
{ {

View File

@ -14,7 +14,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
public class CirclePiece : Container public class CirclePiece : Container
{ {
private Sprite disc; private readonly Sprite disc;
public Func<bool> Hit; public Func<bool> Hit;

View File

@ -11,7 +11,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
public class GlowPiece : Container public class GlowPiece : Container
{ {
private Sprite layer; private readonly Sprite layer;
public GlowPiece() public GlowPiece()
{ {

View File

@ -12,7 +12,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
public class NumberPiece : Container public class NumberPiece : Container
{ {
private SpriteText number; private readonly SpriteText number;
public string Text public string Text
{ {
@ -29,6 +29,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
new CircularContainer new CircularContainer
{ {
Masking = true,
Origin = Anchor.Centre,
EdgeEffect = new EdgeEffect EdgeEffect = new EdgeEffect
{ {
Type = EdgeEffectType.Glow, Type = EdgeEffectType.Glow,

View File

@ -13,7 +13,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
public class SliderBall : CircularContainer, ISliderProgress public class SliderBall : CircularContainer, ISliderProgress
{ {
private readonly Slider slider; private readonly Slider slider;
private Box follow; private readonly Box follow;
private const float width = 128; private const float width = 128;

View File

@ -18,8 +18,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
public class SliderBody : Container, ISliderProgress public class SliderBody : Container, ISliderProgress
{ {
private Path path; private readonly Path path;
private BufferedContainer container; private readonly BufferedContainer container;
public float PathWidth public float PathWidth
{ {
@ -33,7 +33,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
public double? SnakedStart { get; private set; } public double? SnakedStart { get; private set; }
public double? SnakedEnd { get; private set; } public double? SnakedEnd { get; private set; }
private Slider slider; private readonly Slider slider;
public SliderBody(Slider s) public SliderBody(Slider s)
{ {
slider = s; slider = s;
@ -122,7 +122,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
path.Texture = texture; path.Texture = texture;
} }
private List<Vector2> currentCurve = new List<Vector2>(); private readonly List<Vector2> currentCurve = new List<Vector2>();
private bool updateSnaking(double p0, double p1) private bool updateSnaking(double p0, double p1)
{ {
if (SnakedStart == p0 && SnakedEnd == p1) return false; if (SnakedStart == p0 && SnakedEnd == p1) return false;

View File

@ -11,7 +11,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
private readonly Slider slider; private readonly Slider slider;
private readonly bool isEnd; private readonly bool isEnd;
private TextAwesome icon; private readonly TextAwesome icon;
public SliderBouncer(Slider slider, bool isEnd) public SliderBouncer(Slider slider, bool isEnd)
{ {

View File

@ -33,6 +33,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
completeColour = colours.YellowLight.Opacity(0.8f); completeColour = colours.YellowLight.Opacity(0.8f);
Masking = true;
} }
private class SpinnerBorder : Container private class SpinnerBorder : Container
@ -61,6 +62,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
Colour = Color4.White, Colour = Color4.White,
RelativePositionAxes = Axes.Both, RelativePositionAxes = Axes.Both,
Masking = true,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(1 / ScreenSpaceDrawQuad.Width * 2000), Size = new Vector2(1 / ScreenSpaceDrawQuad.Width * 2000),
Children = new[] Children = new[]

View File

@ -47,11 +47,11 @@ namespace osu.Game.Modes.Osu.Objects
internal int MaxCombo = 1; internal int MaxCombo = 1;
private float scalingFactor; private readonly float scalingFactor;
private float lazySliderLength; private float lazySliderLength;
private Vector2 startPosition; private readonly Vector2 startPosition;
private Vector2 endPosition; private readonly Vector2 endPosition;
internal OsuHitObjectDifficulty(OsuHitObject baseHitObject) internal OsuHitObjectDifficulty(OsuHitObject baseHitObject)
{ {

View File

@ -20,7 +20,7 @@ namespace osu.Game.Modes.Osu
private const float spin_radius = 50; private const float spin_radius = 50;
private Beatmap<OsuHitObject> beatmap; private readonly Beatmap<OsuHitObject> beatmap;
public OsuAutoReplay(Beatmap<OsuHitObject> beatmap) public OsuAutoReplay(Beatmap<OsuHitObject> beatmap)
{ {
@ -37,11 +37,11 @@ namespace osu.Game.Modes.Osu
} }
} }
private static IComparer<LegacyReplayFrame> replayFrameComparer = new LegacyReplayFrameComparer(); private static readonly IComparer<LegacyReplayFrame> replay_frame_comparer = new LegacyReplayFrameComparer();
private int findInsertionIndex(LegacyReplayFrame frame) private int findInsertionIndex(LegacyReplayFrame frame)
{ {
int index = Frames.BinarySearch(frame, replayFrameComparer); int index = Frames.BinarySearch(frame, replay_frame_comparer);
if (index < 0) if (index < 0)
{ {

View File

@ -17,9 +17,9 @@ namespace osu.Game.Modes.Osu.UI
{ {
public class OsuPlayfield : Playfield<OsuHitObject, OsuJudgementInfo> public class OsuPlayfield : Playfield<OsuHitObject, OsuJudgementInfo>
{ {
private Container approachCircles; private readonly Container approachCircles;
private Container judgementLayer; private readonly Container judgementLayer;
private ConnectionRenderer<OsuHitObject> connectionLayer; private readonly ConnectionRenderer<OsuHitObject> connectionLayer;
public override Vector2 Size public override Vector2 Size
{ {

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Taiko.Judgements
{
public enum TaikoHitResult
{
Good,
Great
}
}

View File

@ -7,5 +7,77 @@ namespace osu.Game.Modes.Taiko.Judgements
{ {
public class TaikoJudgementInfo : JudgementInfo public class TaikoJudgementInfo : JudgementInfo
{ {
/// <summary>
/// The maximum score value.
/// </summary>
public const TaikoHitResult MAX_HIT_RESULT = TaikoHitResult.Great;
/// <summary>
/// The score value.
/// </summary>
public TaikoHitResult TaikoResult;
/// <summary>
/// The score value for the combo portion of the score.
/// </summary>
public int ScoreValue => NumericResultForScore(TaikoResult);
/// <summary>
/// The score value for the accuracy portion of the score.
/// </summary>
public int AccuracyScoreValue => NumericResultForAccuracy(TaikoResult);
/// <summary>
/// The maximum score value for the combo portion of the score.
/// </summary>
public int MaxScoreValue => NumericResultForScore(MAX_HIT_RESULT);
/// <summary>
/// The maximum score value for the accuracy portion of the score.
/// </summary>
public int MaxAccuracyScoreValue => NumericResultForAccuracy(MAX_HIT_RESULT);
/// <summary>
/// Whether this Judgement has a secondary hit in the case of finishers.
/// </summary>
public bool SecondHit;
/// <summary>
/// Computes the numeric score value for the combo portion of the score.
/// For the accuracy portion of the score (including accuracy percentage), see <see cref="NumericResultForAccuracy(TaikoHitResult)"/>.
/// </summary>
/// <param name="result">The result to compute the score value for.</param>
/// <returns>The numeric score value.</returns>
protected virtual int NumericResultForScore(TaikoHitResult result)
{
switch (result)
{
default:
return 0;
case TaikoHitResult.Good:
return 100;
case TaikoHitResult.Great:
return 300;
}
}
/// <summary>
/// Computes the numeric score value for the accuracy portion of the score.
/// For the combo portion of the score, see <see cref="NumericResultForScore(TaikoHitResult)"/>.
/// </summary>
/// <param name="result">The result to compute the score value for.</param>
/// <returns>The numeric score value.</returns>
protected virtual int NumericResultForAccuracy(TaikoHitResult result)
{
switch (result)
{
default:
return 0;
case TaikoHitResult.Good:
return 150;
case TaikoHitResult.Great:
return 300;
}
}
} }
} }

View File

@ -0,0 +1,30 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Taiko.Objects
{
public class Bash : TaikoHitObject, IHasEndTime
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
/// <summary>
/// The number of hits required to complete the bash successfully.
/// </summary>
public int RequiredHits { get; protected set; }
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{
base.ApplyDefaults(timing, difficulty);
double spinnerRotationRatio = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
RequiredHits = (int)Math.Max(1, Duration / 1000f * spinnerRotationRatio);
}
}
}

View File

@ -12,7 +12,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
{ {
internal class DrawableTaikoHit : Sprite internal class DrawableTaikoHit : Sprite
{ {
private TaikoHitObject h; private readonly TaikoHitObject h;
public DrawableTaikoHit(TaikoHitObject h) public DrawableTaikoHit(TaikoHitObject h)
{ {
@ -29,7 +29,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable
{ {
Texture = textures.Get(@"Menu/logo"); Texture = textures.Get(@"Menu/logo");
double duration = 0; const double duration = 0;
Transforms.Add(new TransformPositionX { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = 1.1f, EndValue = 0.1f }); Transforms.Add(new TransformPositionX { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = 1.1f, EndValue = 0.1f });
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 }); Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 });

View File

@ -0,0 +1,104 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps.Samples;
using osu.Game.Modes.Objects.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
namespace osu.Game.Modes.Taiko.Objects
{
public class DrumRoll : TaikoHitObject, IHasDistance
{
public double EndTime => StartTime + Distance / Velocity;
public double Duration => EndTime - StartTime;
/// <summary>
/// Raw length of the drum roll in positional length units.
/// </summary>
public double Distance { get; set; }
/// <summary>
/// Velocity of the drum roll in positional length units per millisecond.
/// </summary>
public double Velocity { get; protected set; }
/// <summary>
/// The distance between ticks of this drumroll.
/// <para>Half of this value is the hit window of the ticks.</para>
/// </summary>
public double TickTimeDistance { get; protected set; }
/// <summary>
/// Number of drum roll ticks required for a "Good" hit.
/// </summary>
public double RequiredGoodHits { get; protected set; }
/// <summary>
/// Number of drum roll ticks required for a "Great" hit.
/// </summary>
public double RequiredGreatHits { get; protected set; }
/// <summary>
/// Total number of drum roll ticks.
/// </summary>
public int TotalTicks => Ticks.Count();
/// <summary>
/// Initializes the drum roll ticks if not initialized and returns them.
/// </summary>
public IEnumerable<DrumRollTick> Ticks => ticks ?? (ticks = createTicks());
private List<DrumRollTick> ticks;
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{
base.ApplyDefaults(timing, difficulty);
Velocity = timing.SliderVelocityAt(StartTime) * difficulty.SliderMultiplier / 1000;
TickTimeDistance = timing.BeatLengthAt(StartTime);
//TODO: move this to legacy conversion code to allow for direct division without special case.
if (difficulty.SliderTickRate == 3)
TickTimeDistance /= 3;
else
TickTimeDistance /= 4;
RequiredGoodHits = TotalTicks * Math.Min(0.15, 0.05 + 0.10 / 6 * difficulty.OverallDifficulty);
RequiredGreatHits = TotalTicks * Math.Min(0.30, 0.10 + 0.20 / 6 * difficulty.OverallDifficulty);
}
private List<DrumRollTick> createTicks()
{
var ret = new List<DrumRollTick>();
if (TickTimeDistance == 0)
return ret;
bool first = true;
for (double t = StartTime; t < EndTime + (int)TickTimeDistance; t += TickTimeDistance)
{
ret.Add(new DrumRollTick
{
FirstTick = first,
PreEmpt = PreEmpt,
TickTimeDistance = TickTimeDistance,
StartTime = t,
Sample = new HitSampleInfo
{
Type = SampleType.None,
Set = SampleSet.Soft
}
});
first = false;
}
return ret;
}
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Taiko.Objects
{
public class DrumRollTick : TaikoHitObject
{
/// <summary>
/// Whether this is the first (initial) tick of the slider.
/// </summary>
public bool FirstTick;
/// <summary>
/// The distance between this tick and the next in milliseconds.
/// <para>Half of this value is the hit window of the tick.</para>
/// </summary>
public double TickTimeDistance;
}
}

View File

@ -57,6 +57,10 @@
<Compile Include="Objects\Drawable\Pieces\FinisherPiece.cs" /> <Compile Include="Objects\Drawable\Pieces\FinisherPiece.cs" />
<Compile Include="Objects\Drawable\Pieces\RimHitCirclePiece.cs" /> <Compile Include="Objects\Drawable\Pieces\RimHitCirclePiece.cs" />
<Compile Include="Objects\Drawable\Pieces\ScrollingCirclePiece.cs" /> <Compile Include="Objects\Drawable\Pieces\ScrollingCirclePiece.cs" />
<Compile Include="Judgements\TaikoHitResult.cs" />
<Compile Include="Objects\Bash.cs" />
<Compile Include="Objects\DrumRoll.cs" />
<Compile Include="Objects\DrumRollTick.cs" />
<Compile Include="TaikoDifficultyCalculator.cs" /> <Compile Include="TaikoDifficultyCalculator.cs" />
<Compile Include="Objects\Drawable\DrawableTaikoHit.cs" /> <Compile Include="Objects\Drawable\DrawableTaikoHit.cs" />
<Compile Include="Objects\TaikoHitObject.cs" /> <Compile Include="Objects\TaikoHitObject.cs" />

View File

@ -15,8 +15,8 @@ namespace osu.Game.Beatmaps
private void loadTiming() private void loadTiming()
{ {
// TODO: Handle mods // TODO: Handle mods
int audioRate = 100; const int audio_rate = 100;
TimeRate = audioRate / 100.0; TimeRate = audio_rate / 100.0;
} }
public double Calculate(Dictionary<string, string> categoryDifficulty = null) public double Calculate(Dictionary<string, string> categoryDifficulty = null)

View File

@ -21,12 +21,12 @@ namespace osu.Game.Beatmaps.Drawables
public class BeatmapPanel : Panel public class BeatmapPanel : Panel
{ {
public BeatmapInfo Beatmap; public BeatmapInfo Beatmap;
private Sprite background; private readonly Sprite background;
public Action<BeatmapPanel> GainedSelection; public Action<BeatmapPanel> GainedSelection;
public Action<BeatmapPanel> StartRequested; public Action<BeatmapPanel> StartRequested;
private Triangles triangles; private readonly Triangles triangles;
private StarCounter starCounter; private readonly StarCounter starCounter;
protected override void Selected() protected override void Selected()
{ {

View File

@ -20,11 +20,12 @@ namespace osu.Game.Beatmaps.Drawables
public class BeatmapSetHeader : Panel public class BeatmapSetHeader : Panel
{ {
public Action<BeatmapSetHeader> GainedSelection; public Action<BeatmapSetHeader> GainedSelection;
private SpriteText title, artist; private readonly SpriteText title;
private readonly SpriteText artist;
private OsuConfigManager config; private OsuConfigManager config;
private Bindable<bool> preferUnicode; private Bindable<bool> preferUnicode;
private WorkingBeatmap beatmap; private readonly WorkingBeatmap beatmap;
private FillFlowContainer difficultyIcons; private readonly FillFlowContainer difficultyIcons;
public BeatmapSetHeader(WorkingBeatmap beatmap) public BeatmapSetHeader(WorkingBeatmap beatmap)
{ {

View File

@ -18,7 +18,7 @@ namespace osu.Game.Beatmaps.Drawables
public override bool RemoveWhenNotAlive => false; public override bool RemoveWhenNotAlive => false;
private Container nestedContainer; private readonly Container nestedContainer;
protected override Container<Drawable> Content => nestedContainer; protected override Container<Drawable> Content => nestedContainer;

View File

@ -207,7 +207,8 @@ namespace osu.Game.Beatmaps.Formats
VelocityAdjustment = beatLength < 0 ? -beatLength / 100.0 : 1, VelocityAdjustment = beatLength < 0 ? -beatLength / 100.0 : 1,
TimingChange = split.Length <= 6 || split[6][0] == '1', TimingChange = split.Length <= 6 || split[6][0] == '1',
KiaiMode = (effectFlags & 1) > 0, KiaiMode = (effectFlags & 1) > 0,
OmitFirstBarLine = (effectFlags & 8) > 0 OmitFirstBarLine = (effectFlags & 8) > 0,
TimeSignature = (TimeSignatures)int.Parse(split[2])
}; };
} }

View File

@ -21,9 +21,9 @@ namespace osu.Game.Beatmaps.IO
OsuLegacyDecoder.Register(); OsuLegacyDecoder.Register();
} }
private Stream archiveStream; private readonly Stream archiveStream;
private ZipFile archive; private readonly ZipFile archive;
private Beatmap firstMap; private readonly Beatmap firstMap;
public OszArchiveReader(Stream archiveStream) public OszArchiveReader(Stream archiveStream)
{ {

View File

@ -11,18 +11,12 @@ namespace osu.Game.Beatmaps.Timing
TimingChange = true, TimingChange = true,
}; };
public TimeSignatures TimeSignature;
public double Time; public double Time;
public double BeatLength; public double BeatLength;
public double VelocityAdjustment; public double VelocityAdjustment;
public bool TimingChange; public bool TimingChange;
public bool KiaiMode; public bool KiaiMode;
public bool OmitFirstBarLine; public bool OmitFirstBarLine;
}
internal enum TimeSignatures
{
SimpleQuadruple = 4,
SimpleTriple = 3
} }
} }

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Beatmaps.Timing
{
public enum TimeSignatures
{
SimpleQuadruple = 4,
SimpleTriple = 3
}
}

View File

@ -4,14 +4,11 @@
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.IO;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Modes; using osu.Game.Modes;
using osu.Game.Modes.Mods; using osu.Game.Modes.Mods;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
@ -27,14 +24,12 @@ namespace osu.Game.Beatmaps
/// </summary> /// </summary>
public PlayMode? PreferredPlayMode; public PlayMode? PreferredPlayMode;
public PlayMode PlayMode => beatmap?.BeatmapInfo?.Mode > PlayMode.Osu ? beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu; public PlayMode PlayMode => Beatmap?.BeatmapInfo?.Mode > PlayMode.Osu ? Beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu;
public readonly Bindable<IEnumerable<Mod>> Mods = new Bindable<IEnumerable<Mod>>(); public readonly Bindable<IEnumerable<Mod>> Mods = new Bindable<IEnumerable<Mod>>();
public readonly bool WithStoryboard; public readonly bool WithStoryboard;
protected abstract ArchiveReader GetReader();
protected WorkingBeatmap(BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false) protected WorkingBeatmap(BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false)
{ {
BeatmapInfo = beatmapInfo; BeatmapInfo = beatmapInfo;
@ -42,116 +37,63 @@ namespace osu.Game.Beatmaps
WithStoryboard = withStoryboard; WithStoryboard = withStoryboard;
} }
private Texture background; protected abstract Beatmap GetBeatmap();
private object backgroundLock = new object(); protected abstract Texture GetBackground();
public Texture Background protected abstract Track GetTrack();
{
get
{
lock (backgroundLock)
{
if (background != null) return background;
if (BeatmapInfo?.Metadata?.BackgroundFile == null) return null;
try
{
using (var reader = GetReader())
background = new TextureStore(new RawTextureLoaderStore(reader), false).Get(BeatmapInfo.Metadata.BackgroundFile);
}
catch { }
return background;
}
}
set { lock (backgroundLock) background = value; }
}
private Beatmap beatmap; private Beatmap beatmap;
private object beatmapLock = new object(); private readonly object beatmapLock = new object();
public Beatmap Beatmap public Beatmap Beatmap
{ {
get get
{ {
lock (beatmapLock) lock (beatmapLock)
{ {
if (beatmap != null) return beatmap; return beatmap ?? (beatmap = GetBeatmap());
}
try }
{ }
using (var reader = GetReader())
{ private readonly object backgroundLock = new object();
BeatmapDecoder decoder; private Texture background;
using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path))) public Texture Background
{ {
decoder = BeatmapDecoder.GetDecoder(stream); get
beatmap = decoder?.Decode(stream); {
} lock (backgroundLock)
{
if (WithStoryboard && beatmap != null && BeatmapSetInfo.StoryboardFile != null) return background ?? (background = GetBackground());
using (var stream = new StreamReader(reader.GetStream(BeatmapSetInfo.StoryboardFile)))
decoder?.Decode(stream, beatmap);
}
}
catch { }
return beatmap;
} }
} }
set { lock (beatmapLock) beatmap = value; }
} }
private ArchiveReader trackReader;
private Track track; private Track track;
private object trackLock = new object(); private readonly object trackLock = new object();
public Track Track public Track Track
{ {
get get
{ {
lock (trackLock) lock (trackLock)
{ {
if (track != null) return track; return track ?? (track = GetTrack());
try
{
//store a reference to the reader as we may continue accessing the stream in the background.
trackReader = GetReader();
var trackData = trackReader?.GetStream(BeatmapInfo.Metadata.AudioFile);
if (trackData != null)
track = new TrackBass(trackData);
}
catch { }
return track;
} }
} }
set { lock (trackLock) track = value; }
} }
public bool TrackLoaded => track != null; public bool TrackLoaded => track != null;
private bool isDisposed; public void TransferTo(WorkingBeatmap other)
protected virtual void Dispose(bool disposing)
{ {
if (!isDisposed) if (track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo))
{ other.track = track;
track?.Dispose();
background?.Dispose();
isDisposed = true;
}
} }
public void Dispose() public virtual void Dispose()
{ {
Dispose(true); track?.Dispose();
GC.SuppressFinalize(this); track = null;
} background?.Dispose();
background = null;
public void TransferTo(WorkingBeatmap working)
{
if (track != null && BeatmapInfo.AudioEquals(working.BeatmapInfo))
working.track = track;
} }
} }
} }

View File

@ -23,7 +23,8 @@ namespace osu.Game.Configuration
Set(OsuConfig.SavePassword, false); Set(OsuConfig.SavePassword, false);
Set(OsuConfig.SaveUsername, true); Set(OsuConfig.SaveUsername, true);
Set(OsuConfig.CursorSize, 1.0, 0.5f, 2); Set(OsuConfig.MenuCursorSize, 1.0, 0.5f, 2);
Set(OsuConfig.GameplayCursorSize, 1.0, 0.5f, 2);
Set(OsuConfig.DimLevel, 30, 0, 100); Set(OsuConfig.DimLevel, 30, 0, 100);
Set(OsuConfig.MouseDisableButtons, false); Set(OsuConfig.MouseDisableButtons, false);
@ -175,11 +176,11 @@ namespace osu.Game.Configuration
ConfineMouseMode.Fullscreen : ConfineMouseMode.Never).Disabled = true; ConfineMouseMode.Fullscreen : ConfineMouseMode.Never).Disabled = true;
GetBindable<bool>(OsuConfig.SavePassword).ValueChanged += delegate GetOriginalBindable<bool>(OsuConfig.SavePassword).ValueChanged += delegate
{ {
if (Get<bool>(OsuConfig.SavePassword)) Set(OsuConfig.SaveUsername, true); if (Get<bool>(OsuConfig.SavePassword)) Set(OsuConfig.SaveUsername, true);
}; };
GetBindable<bool>(OsuConfig.SaveUsername).ValueChanged += delegate GetOriginalBindable<bool>(OsuConfig.SaveUsername).ValueChanged += delegate
{ {
if (!Get<bool>(OsuConfig.SaveUsername)) Set(OsuConfig.SavePassword, false); if (!Get<bool>(OsuConfig.SaveUsername)) Set(OsuConfig.SavePassword, false);
}; };
@ -223,7 +224,8 @@ namespace osu.Game.Configuration
ComboFireHeight, ComboFireHeight,
ConfirmExit, ConfirmExit,
AutoSendNowPlaying, AutoSendNowPlaying,
CursorSize, MenuCursorSize,
GameplayCursorSize,
AutomaticCursorSizing, AutomaticCursorSizing,
DimLevel, DimLevel,
Display, Display,

View File

@ -21,7 +21,7 @@ namespace osu.Game.Database
public class BeatmapDatabase public class BeatmapDatabase
{ {
private SQLiteConnection connection { get; } private SQLiteConnection connection { get; }
private Storage storage; private readonly Storage storage;
public event Action<BeatmapSetInfo> BeatmapSetAdded; public event Action<BeatmapSetInfo> BeatmapSetAdded;
public event Action<BeatmapSetInfo> BeatmapSetRemoved; public event Action<BeatmapSetInfo> BeatmapSetRemoved;
@ -342,18 +342,5 @@ namespace osu.Game.Database
} }
public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path); public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path);
private class DatabaseWorkingBeatmap : WorkingBeatmap
{
private readonly BeatmapDatabase database;
public DatabaseWorkingBeatmap(BeatmapDatabase database, BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false)
: base(beatmapInfo, beatmapSetInfo, withStoryboard)
{
this.database = database;
}
protected override ArchiveReader GetReader() => database?.GetReader(BeatmapSetInfo);
}
} }
} }

View File

@ -0,0 +1,73 @@
// 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.IO;
using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.IO;
namespace osu.Game.Database
{
internal class DatabaseWorkingBeatmap : WorkingBeatmap
{
private readonly BeatmapDatabase database;
public DatabaseWorkingBeatmap(BeatmapDatabase database, BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false)
: base(beatmapInfo, beatmapSetInfo, withStoryboard)
{
this.database = database;
}
private ArchiveReader getReader() => database?.GetReader(BeatmapSetInfo);
protected override Beatmap GetBeatmap()
{
try
{
Beatmap beatmap;
using (var reader = getReader())
{
BeatmapDecoder decoder;
using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path)))
{
decoder = BeatmapDecoder.GetDecoder(stream);
beatmap = decoder?.Decode(stream);
}
if (WithStoryboard && beatmap != null && BeatmapSetInfo.StoryboardFile != null)
using (var stream = new StreamReader(reader.GetStream(BeatmapSetInfo.StoryboardFile)))
decoder.Decode(stream, beatmap);
}
return beatmap;
}
catch { return null; }
}
protected override Texture GetBackground()
{
if (BeatmapInfo?.Metadata?.BackgroundFile == null)
return null;
try
{
using (var reader = getReader())
return new TextureStore(new RawTextureLoaderStore(reader), false).Get(BeatmapInfo.Metadata.BackgroundFile);
}
catch { return null; }
}
protected override Track GetTrack()
{
try
{
var trackData = getReader()?.GetStream(BeatmapInfo.Metadata.AudioFile);
return trackData == null ? null : new TrackBass(trackData);
}
catch { return null; }
}
}
}

View File

@ -14,7 +14,7 @@ namespace osu.Game.Graphics.Backgrounds
{ {
public Sprite Sprite; public Sprite Sprite;
private string textureName; private readonly string textureName;
public Background(string textureName = @"") public Background(string textureName = @"")
{ {

View File

@ -89,25 +89,24 @@ namespace osu.Game.Graphics.Backgrounds
protected virtual Triangle CreateTriangle() protected virtual Triangle CreateTriangle()
{ {
float stdDev = 0.16f; const float std_dev = 0.16f;
float mean = 0.5f; const float mean = 0.5f;
float u1 = 1 - RNG.NextSingle(); //uniform(0,1] random floats float u1 = 1 - RNG.NextSingle(); //uniform(0,1] random floats
float u2 = 1 - RNG.NextSingle(); float u2 = 1 - RNG.NextSingle();
float randStdNormal = (float)(Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2)); //random normal(0,1) float randStdNormal = (float)(Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2)); //random normal(0,1)
var scale = Math.Max(triangleScale * (mean + stdDev * randStdNormal), 0.1f); //random normal(mean,stdDev^2) var scale = Math.Max(triangleScale * (mean + std_dev * randStdNormal), 0.1f); //random normal(mean,stdDev^2)
const float size = 100; const float size = 100;
return new Triangle return new EquilateralTriangle
{ {
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
RelativePositionAxes = Axes.Both, RelativePositionAxes = Axes.Both,
Size = new Vector2(size),
Scale = new Vector2(scale), Scale = new Vector2(scale),
EdgeSmoothness = new Vector2(1), EdgeSmoothness = new Vector2(1),
Colour = GetTriangleShade(), Colour = GetTriangleShade(),
// Scaling height by 0.866 results in equiangular triangles (== 60° and equal side length)
Size = new Vector2(size, 0.866f * size),
Depth = scale, Depth = scale,
}; };
} }

View File

@ -31,7 +31,7 @@ namespace osu.Game.Graphics.Containers
}); });
} }
private Container content; private readonly Container content;
private InputManager input; private InputManager input;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;

View File

@ -31,10 +31,10 @@ namespace osu.Game.Graphics.Cursor
private float time; private float time;
private TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData(); private readonly TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData();
private const int max_sprites = 2048; private const int max_sprites = 2048;
private TrailPart[] parts = new TrailPart[max_sprites]; private readonly TrailPart[] parts = new TrailPart[max_sprites];
private Vector2? lastPosition; private Vector2? lastPosition;
@ -88,10 +88,10 @@ namespace osu.Game.Graphics.Cursor
Invalidate(Invalidation.DrawNode, shallPropagate: false); Invalidate(Invalidation.DrawNode, shallPropagate: false);
int fadeClockResetThreshold = 1000000; const int fade_clock_reset_threshold = 1000000;
time = (float)(Time.Current - timeOffset) / 500f; time = (float)(Time.Current - timeOffset) / 500f;
if (time > fadeClockResetThreshold) if (time > fade_clock_reset_threshold)
resetTime(); resetTime();
} }
@ -163,7 +163,7 @@ namespace osu.Game.Graphics.Cursor
public float Time; public float Time;
public TrailDrawNodeSharedData Shared; public TrailDrawNodeSharedData Shared;
public TrailPart[] Parts = new TrailPart[max_sprites]; public readonly TrailPart[] Parts = new TrailPart[max_sprites];
public Vector2 Size; public Vector2 Size;
public TrailDrawNode() public TrailDrawNode()

View File

@ -54,8 +54,6 @@ namespace osu.Game.Graphics.Cursor
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
{ {
cursorScale = config.GetBindable<double>(OsuConfig.CursorSize);
Children = new Drawable[] Children = new Drawable[]
{ {
cursorContainer = new CircularContainer cursorContainer = new CircularContainer
@ -63,7 +61,6 @@ namespace osu.Game.Graphics.Cursor
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Scale = new Vector2((float)cursorScale),
Masking = true, Masking = true,
BorderThickness = Size.X / 6, BorderThickness = Size.X / 6,
BorderColour = Color4.White, BorderColour = Color4.White,
@ -119,7 +116,9 @@ namespace osu.Game.Graphics.Cursor
}, },
}; };
cursorScale = config.GetBindable<double>(OsuConfig.GameplayCursorSize);
cursorScale.ValueChanged += scaleChanged; cursorScale.ValueChanged += scaleChanged;
cursorScale.TriggerChange();
} }
private void scaleChanged(object sender, EventArgs e) private void scaleChanged(object sender, EventArgs e)

View File

@ -97,8 +97,6 @@ namespace osu.Game.Graphics.Cursor
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config, TextureStore textures, OsuColour colour) private void load(OsuConfigManager config, TextureStore textures, OsuColour colour)
{ {
cursorScale = config.GetBindable<double>(OsuConfig.CursorSize);
Children = new Drawable[] Children = new Drawable[]
{ {
cursorContainer = new Container cursorContainer = new Container
@ -122,7 +120,10 @@ namespace osu.Game.Graphics.Cursor
} }
} }
}; };
cursorScale = config.GetBindable<double>(OsuConfig.MenuCursorSize);
cursorScale.ValueChanged += scaleChanged; cursorScale.ValueChanged += scaleChanged;
cursorScale.TriggerChange();
} }
private void scaleChanged(object sender, EventArgs e) private void scaleChanged(object sender, EventArgs e)

View File

@ -1,11 +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 osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics namespace osu.Game.Graphics
{ {
public class TextAwesome : SpriteText public class TextAwesome : OsuSpriteText
{ {
//public override FontFace FontFace => (int)Icon < 0xf000 ? FontFace.OsuFont : FontFace.FontAwesome; //public override FontFace FontFace => (int)Icon < 0xf000 ? FontFace.OsuFont : FontFace.FontAwesome;

View File

@ -81,9 +81,14 @@ namespace osu.Game.Graphics.UserInterface
public SampleChannel SampleClick, SampleHover; public SampleChannel SampleClick, SampleHover;
private Container backgroundContainer, colourContainer, glowContainer; private readonly Container backgroundContainer;
private Box leftGlow, centerGlow, rightGlow, background; private readonly Container colourContainer;
private SpriteText spriteText; private readonly Container glowContainer;
private readonly Box leftGlow;
private readonly Box centerGlow;
private readonly Box rightGlow;
private readonly Box background;
private readonly SpriteText spriteText;
private Vector2 hoverSpacing => new Vector2(3f, 0f); private Vector2 hoverSpacing => new Vector2(3f, 0f);
private bool didClick; // Used for making sure that the OnMouseDown animation can call instead of OnHoverLost's when clicking private bool didClick; // Used for making sure that the OnMouseDown animation can call instead of OnHoverLost's when clicking

View File

@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface
public const float COLLAPSED_SIZE = 20; public const float COLLAPSED_SIZE = 20;
public const float EXPANDED_SIZE = 40; public const float EXPANDED_SIZE = 40;
private Box fill; private readonly Box fill;
private const float border_width = 3; private const float border_width = 3;
private Color4 glowingColour, idleColour; private Color4 glowingColour, idleColour;
@ -30,6 +30,8 @@ namespace osu.Game.Graphics.UserInterface
BorderColour = Color4.White; BorderColour = Color4.White;
BorderThickness = border_width; BorderThickness = border_width;
Masking = true;
Children = new[] Children = new[]
{ {
fill = new Box fill = new Box

View File

@ -64,8 +64,8 @@ namespace osu.Game.Graphics.UserInterface
} }
} }
private Nub nub; private readonly Nub nub;
private SpriteText labelSpriteText; private readonly SpriteText labelSpriteText;
private SampleChannel sampleChecked; private SampleChannel sampleChecked;
private SampleChannel sampleUnchecked; private SampleChannel sampleUnchecked;

View File

@ -1,68 +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.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.Sprites;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
namespace osu.Game.Graphics.UserInterface
{
public class OsuDropDownHeader : DropDownHeader
{
private SpriteText label;
protected override string Label
{
get { return label.Text; }
set { label.Text = value; }
}
private Color4? accentColour;
public virtual Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
BackgroundColourHover = value;
}
}
public OsuDropDownHeader()
{
Foreground.Padding = new MarginPadding(4);
AutoSizeAxes = Axes.None;
Margin = new MarginPadding { Bottom = 4 };
CornerRadius = 4;
Height = 40;
Foreground.Children = new Drawable[]
{
label = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
new TextAwesome
{
Icon = FontAwesome.fa_chevron_down,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 4 },
}
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
BackgroundColour = Color4.Black.Opacity(0.5f);
BackgroundColourHover = accentColour ?? colours.PinkDarker;
}
}
}

View File

@ -1,61 +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.Linq;
using osu.Framework.Allocation;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Graphics.UserInterface;
namespace osu.Game.Graphics.UserInterface
{
public class OsuDropDownMenu<T> : DropDownMenu<T>
{
protected override DropDownHeader CreateHeader() => new OsuDropDownHeader { AccentColour = AccentColour };
private Color4? accentColour;
public virtual Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
if (Header != null)
((OsuDropDownHeader)Header).AccentColour = value;
foreach (var item in ItemList.OfType<OsuDropDownMenuItem<T>>())
item.AccentColour = value;
}
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
if (accentColour == null)
AccentColour = colours.PinkDarker;
}
public OsuDropDownMenu()
{
ContentContainer.CornerRadius = 4;
ContentBackground.Colour = Color4.Black.Opacity(0.5f);
DropDownItemsContainer.Padding = new MarginPadding(5);
}
protected override void AnimateOpen() => ContentContainer.FadeIn(300, EasingTypes.OutQuint);
protected override void AnimateClose() => ContentContainer.FadeOut(300, EasingTypes.OutQuint);
protected override void UpdateContentHeight()
{
var actualHeight = (RelativeSizeAxes & Axes.Y) > 0 ? 1 : ContentHeight;
ContentContainer.ResizeTo(new Vector2(1, State == DropDownMenuState.Opened ? actualHeight : 0), 300, EasingTypes.OutQuint);
}
protected override DropDownMenuItem<T> CreateDropDownItem(string key, T value) => new OsuDropDownMenuItem<T>(key, value) { AccentColour = AccentColour };
}
}

View File

@ -1,85 +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.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.Sprites;
using OpenTK.Graphics;
namespace osu.Game.Graphics.UserInterface
{
public class OsuDropDownMenuItem<U> : DropDownMenuItem<U>
{
public OsuDropDownMenuItem(string text, U value) : base(text, value)
{
Foreground.Padding = new MarginPadding(2);
Masking = true;
CornerRadius = 6;
Children = new[]
{
new FillFlowContainer
{
Direction = FillDirection.Horizontal,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
chevron = new TextAwesome
{
AlwaysPresent = true,
Icon = FontAwesome.fa_chevron_right,
UseFullGlyphHeight = false,
Colour = Color4.Black,
Alpha = 0.5f,
TextSize = 8,
Margin = new MarginPadding { Left = 3, Right = 3 },
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
},
new OsuSpriteText {
Text = text,
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
}
}
}
};
}
private Color4? accentColour;
private TextAwesome chevron;
protected override void FormatForeground(bool hover = false)
{
base.FormatForeground(hover);
chevron.Alpha = hover ? 1 : 0;
}
public Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
BackgroundColourHover = BackgroundColourSelected = value;
FormatBackground();
FormatForeground();
}
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
BackgroundColour = Color4.Transparent;
BackgroundColourHover = accentColour ?? colours.PinkDarker;
BackgroundColourSelected = Color4.Black.Opacity(0.5f);
}
}
}

View File

@ -0,0 +1,172 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Linq;
using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface
{
public class OsuDropdown<T> : Dropdown<T>
{
protected override DropdownHeader CreateHeader() => new OsuDropdownHeader { AccentColour = AccentColour };
protected override Menu CreateMenu() => new OsuMenu();
private Color4? accentColour;
public virtual Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
if (Header != null)
((OsuDropdownHeader)Header).AccentColour = value;
foreach (var item in MenuItems.OfType<OsuDropdownMenuItem>())
item.AccentColour = value;
}
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
if (accentColour == null)
AccentColour = colours.PinkDarker;
}
protected override DropdownMenuItem<T> CreateMenuItem(string text, T value) => new OsuDropdownMenuItem(text, value) { AccentColour = AccentColour };
private class OsuDropdownMenuItem : DropdownMenuItem<T>
{
public OsuDropdownMenuItem(string text, T value) : base(text, value)
{
Foreground.Padding = new MarginPadding(2);
Masking = true;
CornerRadius = 6;
Children = new[]
{
new FillFlowContainer
{
Direction = FillDirection.Horizontal,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
chevron = new TextAwesome
{
AlwaysPresent = true,
Icon = FontAwesome.fa_chevron_right,
UseFullGlyphHeight = false,
Colour = Color4.Black,
Alpha = 0.5f,
TextSize = 8,
Margin = new MarginPadding { Left = 3, Right = 3 },
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
},
new OsuSpriteText {
Text = text,
Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft,
}
}
}
};
}
private Color4? accentColour;
private readonly TextAwesome chevron;
protected override void FormatForeground(bool hover = false)
{
base.FormatForeground(hover);
chevron.Alpha = hover ? 1 : 0;
}
public Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
BackgroundColourHover = BackgroundColourSelected = value;
FormatBackground();
FormatForeground();
}
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
BackgroundColour = Color4.Transparent;
BackgroundColourHover = accentColour ?? colours.PinkDarker;
BackgroundColourSelected = Color4.Black.Opacity(0.5f);
}
}
protected class OsuDropdownHeader : DropdownHeader
{
private readonly SpriteText label;
protected override string Label
{
get { return label.Text; }
set { label.Text = value; }
}
private Color4? accentColour;
public virtual Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
BackgroundColourHover = value;
}
}
public OsuDropdownHeader()
{
Foreground.Padding = new MarginPadding(4);
AutoSizeAxes = Axes.None;
Margin = new MarginPadding { Bottom = 4 };
CornerRadius = 4;
Height = 40;
Foreground.Children = new Drawable[]
{
label = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
new TextAwesome
{
Icon = FontAwesome.fa_chevron_down,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 4 },
TextSize = 20
}
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
BackgroundColour = Color4.Black.Opacity(0.5f);
BackgroundColourHover = accentColour ?? colours.PinkDarker;
}
}
}
}

View 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;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Graphics.UserInterface;
namespace osu.Game.Graphics.UserInterface
{
public class OsuMenu : Menu
{
public OsuMenu()
{
CornerRadius = 4;
Background.Colour = Color4.Black.Opacity(0.5f);
ItemsContainer.Padding = new MarginPadding(5);
}
protected override void AnimateOpen() => FadeIn(300, EasingTypes.OutQuint);
protected override void AnimateClose() => FadeOut(300, EasingTypes.OutQuint);
protected override void UpdateContentHeight()
{
var actualHeight = (RelativeSizeAxes & Axes.Y) > 0 ? 1 : ContentHeight;
ResizeTo(new Vector2(1, State == MenuState.Opened ? actualHeight : 0), 300, EasingTypes.OutQuint);
}
}
}

View File

@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface
public class PasswordMaskChar : Container public class PasswordMaskChar : Container
{ {
private CircularContainer circle; private readonly CircularContainer circle;
public PasswordMaskChar(float size) public PasswordMaskChar(float size)
{ {
@ -28,6 +28,8 @@ namespace osu.Game.Graphics.UserInterface
circle = new CircularContainer circle = new CircularContainer
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Masking = true,
Alpha = 0, Alpha = 0,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.8f, 0), Size = new Vector2(0.8f, 0),

View File

@ -19,8 +19,9 @@ namespace osu.Game.Graphics.UserInterface
private SampleChannel sample; private SampleChannel sample;
private double lastSampleTime; private double lastSampleTime;
private Nub nub; private readonly Nub nub;
private Box leftBox, rightBox; private readonly Box leftBox;
private readonly Box rightBox;
public OsuSliderBar() public OsuSliderBar()
{ {

View File

@ -6,21 +6,25 @@ using System.Linq;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
public class OsuTabControl<T> : TabControl<T> public class OsuTabControl<T> : TabControl<T>
{ {
protected override DropDownMenu<T> CreateDropDownMenu() => new OsuTabDropDownMenu<T>(); protected override Dropdown<T> CreateDropdown() => new OsuTabDropdown();
protected override TabItem<T> CreateTabItem(T value) => new OsuTabItem<T> { Value = value }; protected override TabItem<T> CreateTabItem(T value) => new OsuTabItem { Value = value };
protected override bool InternalContains(Vector2 screenSpacePos) => base.InternalContains(screenSpacePos) || DropDown.Contains(screenSpacePos); protected override bool InternalContains(Vector2 screenSpacePos) => base.InternalContains(screenSpacePos) || Dropdown.Contains(screenSpacePos);
public OsuTabControl() public OsuTabControl()
{ {
@ -45,42 +49,146 @@ namespace osu.Game.Graphics.UserInterface
set set
{ {
accentColour = value; accentColour = value;
var dropDown = DropDown as OsuTabDropDownMenu<T>; var dropDown = Dropdown as OsuTabDropdown;
if (dropDown != null) if (dropDown != null)
dropDown.AccentColour = value; dropDown.AccentColour = value;
foreach (var item in TabContainer.Children.OfType<OsuTabItem<T>>()) foreach (var item in TabContainer.Children.OfType<OsuTabItem>())
item.AccentColour = value; item.AccentColour = value;
} }
} }
public class OsuTabDropDownMenu<T1> : OsuDropDownMenu<T1> private class OsuTabItem : TabItem<T>
{ {
protected override DropDownHeader CreateHeader() => new OsuTabDropDownHeader private readonly SpriteText text;
private readonly Box box;
private Color4? accentColour;
public Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
if (!Active)
text.Colour = value;
}
}
public new T Value
{
get { return base.Value; }
set
{
base.Value = value;
text.Text = (value as Enum)?.GetDescription();
}
}
public override bool Active
{
get { return base.Active; }
set
{
if (Active == value) return;
if (value)
fadeActive();
else
fadeInactive();
base.Active = value;
}
}
private const float transition_length = 500;
private void fadeActive()
{
box.FadeIn(transition_length, EasingTypes.OutQuint);
text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint);
}
private void fadeInactive()
{
box.FadeOut(transition_length, EasingTypes.OutQuint);
text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint);
}
protected override bool OnHover(InputState state)
{
if (!Active)
fadeActive();
return true;
}
protected override void OnHoverLost(InputState state)
{
if (!Active)
fadeInactive();
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
if (accentColour == null)
AccentColour = colours.Blue;
}
public OsuTabItem()
{
AutoSizeAxes = Axes.X;
RelativeSizeAxes = Axes.Y;
Children = new Drawable[]
{
text = new OsuSpriteText
{
Margin = new MarginPadding(5),
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
TextSize = 14,
Font = @"Exo2.0-Bold", // Font should only turn bold when active?
},
box = new Box
{
RelativeSizeAxes = Axes.X,
Height = 1,
Alpha = 0,
Colour = Color4.White,
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
}
};
}
}
private class OsuTabDropdown : OsuDropdown<T>
{
protected override DropdownHeader CreateHeader() => new OsuTabDropdownHeader
{ {
AccentColour = AccentColour, AccentColour = AccentColour,
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
}; };
protected override DropDownMenuItem<T1> CreateDropDownItem(string key, T1 value) protected override DropdownMenuItem<T> CreateMenuItem(string text, T value)
{ {
var item = base.CreateDropDownItem(key, value); var item = base.CreateMenuItem(text, value);
item.ForegroundColourHover = Color4.Black; item.ForegroundColourHover = Color4.Black;
return item; return item;
} }
public OsuTabDropDownMenu() public OsuTabDropdown()
{ {
ContentContainer.Anchor = Anchor.TopRight; DropdownMenu.Anchor = Anchor.TopRight;
ContentContainer.Origin = Anchor.TopRight; DropdownMenu.Origin = Anchor.TopRight;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
ContentBackground.Colour = Color4.Black.Opacity(0.7f); DropdownMenu.Background.Colour = Color4.Black.Opacity(0.7f);
MaxDropDownHeight = 400; DropdownMenu.MaxHeight = 400;
} }
public class OsuTabDropDownHeader : OsuDropDownHeader protected class OsuTabDropdownHeader : OsuDropdownHeader
{ {
public override Color4 AccentColour public override Color4 AccentColour
{ {
@ -104,7 +212,7 @@ namespace osu.Game.Graphics.UserInterface
base.OnHoverLost(state); base.OnHoverLost(state);
} }
public OsuTabDropDownHeader() public OsuTabDropdownHeader()
{ {
RelativeSizeAxes = Axes.None; RelativeSizeAxes = Axes.None;
AutoSizeAxes = Axes.X; AutoSizeAxes = Axes.X;

View File

@ -1,121 +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 OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface
{
public class OsuTabItem<T> : TabItem<T>
{
private SpriteText text;
private Box box;
private Color4? accentColour;
public Color4 AccentColour
{
get { return accentColour.GetValueOrDefault(); }
set
{
accentColour = value;
if (!Active)
text.Colour = value;
}
}
public new T Value
{
get { return base.Value; }
set
{
base.Value = value;
text.Text = (value as Enum)?.GetDescription();
}
}
public override bool Active
{
get { return base.Active; }
set
{
if (Active == value) return;
if (value)
fadeActive();
else
fadeInactive();
base.Active = value;
}
}
private const float transition_length = 500;
private void fadeActive()
{
box.FadeIn(transition_length, EasingTypes.OutQuint);
text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint);
}
private void fadeInactive()
{
box.FadeOut(transition_length, EasingTypes.OutQuint);
text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint);
}
protected override bool OnHover(InputState state)
{
if (!Active)
fadeActive();
return true;
}
protected override void OnHoverLost(InputState state)
{
if (!Active)
fadeInactive();
}
public OsuTabItem()
{
AutoSizeAxes = Axes.X;
RelativeSizeAxes = Axes.Y;
Children = new Drawable[]
{
text = new OsuSpriteText
{
Margin = new MarginPadding(5),
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
TextSize = 14,
Font = @"Exo2.0-Bold", // Font should only turn bold when active?
},
box = new Box
{
RelativeSizeAxes = Axes.X,
Height = 1,
Alpha = 0,
Colour = Color4.White,
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
}
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
if (accentColour == null)
AccentColour = colours.Blue;
}
}
}

View File

@ -147,7 +147,7 @@ namespace osu.Game.Graphics.UserInterface
private class Star : Container private class Star : Container
{ {
public TextAwesome Icon; public readonly TextAwesome Icon;
public Star() public Star()
{ {
Size = new Vector2(star_size); Size = new Vector2(star_size);

View File

@ -16,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface
{ {
public class TwoLayerButton : ClickableContainer public class TwoLayerButton : ClickableContainer
{ {
private TextAwesome icon; private readonly TextAwesome icon;
public Box IconLayer; public Box IconLayer;
public Box TextLayer; public Box TextLayer;
@ -29,11 +29,11 @@ namespace osu.Game.Graphics.UserInterface
public static readonly Vector2 SIZE_EXTENDED = new Vector2(140, 50); public static readonly Vector2 SIZE_EXTENDED = new Vector2(140, 50);
public static readonly Vector2 SIZE_RETRACTED = new Vector2(100, 50); public static readonly Vector2 SIZE_RETRACTED = new Vector2(100, 50);
public SampleChannel ActivationSound; public SampleChannel ActivationSound;
private SpriteText text; private readonly SpriteText text;
public Color4 HoverColour; public Color4 HoverColour;
private Container c1; private readonly Container c1;
private Container c2; private readonly Container c2;
public Color4 BackgroundColour public Color4 BackgroundColour
{ {
@ -171,7 +171,7 @@ namespace osu.Game.Graphics.UserInterface
IconLayer.FadeColour(HoverColour, transform_time, EasingTypes.OutElastic); IconLayer.FadeColour(HoverColour, transform_time, EasingTypes.OutElastic);
double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration; const double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration;
double startTime = Time.Current + offset; double startTime = Time.Current + offset;
// basic pulse // basic pulse
@ -200,7 +200,7 @@ namespace osu.Game.Graphics.UserInterface
int duration = 0; //(int)(Game.Audio.BeatLength); int duration = 0; //(int)(Game.Audio.BeatLength);
if (duration == 0) duration = pulse_length * 2; if (duration == 0) duration = pulse_length * 2;
double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration; const double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration;
double startTime = Time.Current + offset; double startTime = Time.Current + offset;
// slow pulse // slow pulse

View File

@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface.Volume
{ {
internal class VolumeControl : OverlayContainer internal class VolumeControl : OverlayContainer
{ {
private VolumeMeter volumeMeterMaster; private readonly VolumeMeter volumeMeterMaster;
protected override bool HideOnEscape => false; protected override bool HideOnEscape => false;
@ -89,8 +89,8 @@ namespace osu.Game.Graphics.UserInterface.Volume
private ScheduledDelegate popOutDelegate; private ScheduledDelegate popOutDelegate;
private VolumeMeter volumeMeterEffect; private readonly VolumeMeter volumeMeterEffect;
private VolumeMeter volumeMeterMusic; private readonly VolumeMeter volumeMeterMusic;
protected override void PopIn() protected override void PopIn()
{ {

View File

@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface.Volume
{ {
internal class VolumeMeter : Container internal class VolumeMeter : Container
{ {
private Box meterFill; private readonly Box meterFill;
public BindableDouble Bindable { get; } = new BindableDouble(); public BindableDouble Bindable { get; } = new BindableDouble();
public VolumeMeter(string meterName) public VolumeMeter(string meterName)

View File

@ -18,7 +18,7 @@ namespace osu.Game.IO.Legacy
/// handle null strings and simplify use with ISerializable. </summary> /// handle null strings and simplify use with ISerializable. </summary>
public class SerializationReader : BinaryReader public class SerializationReader : BinaryReader
{ {
private Stream stream; private readonly Stream stream;
public SerializationReader(Stream s) public SerializationReader(Stream s)
: base(s, Encoding.UTF8) : base(s, Encoding.UTF8)

View File

@ -10,7 +10,7 @@ namespace osu.Game.IPC
{ {
public class BeatmapIPCChannel : IpcChannel<BeatmapImportMessage> public class BeatmapIPCChannel : IpcChannel<BeatmapImportMessage>
{ {
private BeatmapDatabase beatmaps; private readonly BeatmapDatabase beatmaps;
public BeatmapIPCChannel(IIpcHost host, BeatmapDatabase beatmaps = null) public BeatmapIPCChannel(IIpcHost host, BeatmapDatabase beatmaps = null)
: base(host) : base(host)

View File

@ -10,7 +10,7 @@ namespace osu.Game.IPC
{ {
public class ScoreIPCChannel : IpcChannel<ScoreImportMessage> public class ScoreIPCChannel : IpcChannel<ScoreImportMessage>
{ {
private ScoreDatabase scores; private readonly ScoreDatabase scores;
public ScoreIPCChannel(IIpcHost host, ScoreDatabase scores = null) public ScoreIPCChannel(IIpcHost host, ScoreDatabase scores = null)
: base(host) : base(host)

View File

@ -8,10 +8,10 @@ namespace osu.Game.Modes.Objects
{ {
public class BezierApproximator public class BezierApproximator
{ {
private int count; private readonly int count;
private List<Vector2> controlPoints; private readonly List<Vector2> controlPoints;
private Vector2[] subdivisionBuffer1; private readonly Vector2[] subdivisionBuffer1;
private Vector2[] subdivisionBuffer2; private readonly Vector2[] subdivisionBuffer2;
private const float tolerance = 0.25f; private const float tolerance = 0.25f;
private const float tolerance_sq = tolerance * tolerance; private const float tolerance_sq = tolerance * tolerance;

View File

@ -10,9 +10,9 @@ namespace osu.Game.Modes.Objects
{ {
public class CircularArcApproximator public class CircularArcApproximator
{ {
private Vector2 a; private readonly Vector2 a;
private Vector2 b; private readonly Vector2 b;
private Vector2 c; private readonly Vector2 c;
private int amountPoints; private int amountPoints;

View File

@ -38,6 +38,9 @@ namespace osu.Game.Modes.Objects.Drawables
return; return;
state = value; state = value;
if (!IsLoaded)
return;
UpdateState(state); UpdateState(state);
if (State == ArmedState.Hit) if (State == ArmedState.Hit)

View File

@ -19,8 +19,8 @@ namespace osu.Game.Modes.Objects
public Vector2 Offset; public Vector2 Offset;
private List<Vector2> calculatedPath = new List<Vector2>(); private readonly List<Vector2> calculatedPath = new List<Vector2>();
private List<double> cumulativeLength = new List<double>(); private readonly List<double> cumulativeLength = new List<double>();
private List<Vector2> calculateSubpath(List<Vector2> subControlPoints) private List<Vector2> calculateSubpath(List<Vector2> subControlPoints)
{ {

View File

@ -21,9 +21,9 @@ namespace osu.Game.Modes
public abstract class Ruleset public abstract class Ruleset
{ {
private static ConcurrentDictionary<PlayMode, Type> availableRulesets = new ConcurrentDictionary<PlayMode, Type>(); private static readonly ConcurrentDictionary<PlayMode, Type> available_rulesets = new ConcurrentDictionary<PlayMode, Type>();
public static IEnumerable<PlayMode> PlayModes => availableRulesets.Keys; public static IEnumerable<PlayMode> PlayModes => available_rulesets.Keys;
public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { }; public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { };
@ -35,7 +35,7 @@ namespace osu.Game.Modes
public abstract ScoreProcessor CreateScoreProcessor(); public abstract ScoreProcessor CreateScoreProcessor();
public static void Register(Ruleset ruleset) => availableRulesets.TryAdd(ruleset.PlayMode, ruleset.GetType()); public static void Register(Ruleset ruleset) => available_rulesets.TryAdd(ruleset.PlayMode, ruleset.GetType());
protected abstract PlayMode PlayMode { get; } protected abstract PlayMode PlayMode { get; }
@ -49,7 +49,7 @@ namespace osu.Game.Modes
{ {
Type type; Type type;
if (!availableRulesets.TryGetValue(mode, out type)) if (!available_rulesets.TryGetValue(mode, out type))
return null; return null;
return Activator.CreateInstance(type) as Ruleset; return Activator.CreateInstance(type) as Ruleset;

View File

@ -1,19 +1,63 @@
// 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;
using Newtonsoft.Json;
using osu.Game.Users;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Modes.Mods;
namespace osu.Game.Modes namespace osu.Game.Modes
{ {
public class Score public class Score
{ {
[JsonProperty(@"rank")]
public ScoreRank Rank { get; set; }
[JsonProperty(@"score")]
public double TotalScore { get; set; } public double TotalScore { get; set; }
public double Accuracy { get; set; } public double Accuracy { get; set; }
public double Health { get; set; } public double Health { get; set; }
[JsonProperty(@"maxcombo")]
public int MaxCombo { get; set; } public int MaxCombo { get; set; }
public int Combo { get; set; } public int Combo { get; set; }
public Mod[] Mods { get; set; }
public User User { get; set; }
[JsonProperty(@"replay_data")]
public Replay Replay; public Replay Replay;
public BeatmapInfo Beatmap; public BeatmapInfo Beatmap;
[JsonProperty(@"score_id")]
public long OnlineScoreID;
[JsonProperty(@"username")]
public string Username;
[JsonProperty(@"user_id")]
public long UserID;
[JsonProperty(@"date")]
public DateTime Date;
// [JsonProperty(@"count50")] 0,
//[JsonProperty(@"count100")] 0,
//[JsonProperty(@"count300")] 100,
//[JsonProperty(@"countmiss")] 0,
//[JsonProperty(@"countkatu")] 0,
//[JsonProperty(@"countgeki")] 31,
//[JsonProperty(@"perfect")] true,
//[JsonProperty(@"enabled_mods")] [
// "DT",
// "FL",
// "HD",
// "HR"
//],
//[JsonProperty(@"rank")] "XH",
//[JsonProperty(@"pp")] 26.1816,
//[JsonProperty(@"replay")] true
} }
} }

View 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
using System.ComponentModel;
namespace osu.Game.Modes
{
public enum ScoreRank
{
[Description(@"F")]
F,
[Description(@"F")]
D,
[Description(@"C")]
C,
[Description(@"B")]
B,
[Description(@"A")]
A,
[Description(@"S")]
S,
[Description(@"SPlus")]
SH,
[Description(@"SS")]
X,
[Description(@"SSPlus")]
XH,
}
}

View File

@ -155,7 +155,7 @@ namespace osu.Game.Modes.UI
/// </summary> /// </summary>
protected Playfield<TObject, TJudgement> Playfield; protected Playfield<TObject, TJudgement> Playfield;
private Container content; private readonly Container content;
protected HitRenderer(WorkingBeatmap beatmap) protected HitRenderer(WorkingBeatmap beatmap)
: base(beatmap) : base(beatmap)

View File

@ -10,7 +10,8 @@ namespace osu.Game.Modes.UI
{ {
public class ModIcon : Container public class ModIcon : Container
{ {
private TextAwesome modIcon, background; private readonly TextAwesome modIcon;
private readonly TextAwesome background;
private float iconSize = 80; private float iconSize = 80;
public float IconSize public float IconSize
@ -66,12 +67,14 @@ namespace osu.Game.Modes.UI
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Icon = FontAwesome.fa_osu_mod_bg, Icon = FontAwesome.fa_osu_mod_bg,
Shadow = true, Shadow = true,
TextSize = 20
}, },
modIcon = new TextAwesome modIcon = new TextAwesome
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Colour = OsuColour.Gray(84), Colour = OsuColour.Gray(84),
TextSize = 20
}, },
}; };

View File

@ -7,6 +7,7 @@ using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Objects.Drawables;
using OpenTK; using OpenTK;
using osu.Game.Modes.Judgements; using osu.Game.Modes.Judgements;
using osu.Framework.Allocation;
namespace osu.Game.Modes.UI namespace osu.Game.Modes.UI
{ {
@ -22,7 +23,7 @@ namespace osu.Game.Modes.UI
internal Container<Drawable> ScaledContent; internal Container<Drawable> ScaledContent;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private Container<Drawable> content; private readonly Container<Drawable> content;
/// <summary> /// <summary>
/// A container for keeping track of DrawableHitObjects. /// A container for keeping track of DrawableHitObjects.
@ -45,10 +46,16 @@ namespace osu.Game.Modes.UI
} }
}); });
Add(HitObjects = new HitObjectContainer<DrawableHitObject<TObject, TJudgement>> HitObjects = new HitObjectContainer<DrawableHitObject<TObject, TJudgement>>
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}); };
}
[BackgroundDependencyLoader]
private void load()
{
Add(HitObjects);
} }
/// <summary> /// <summary>

View File

@ -15,7 +15,7 @@ namespace osu.Game.Modes.UI
{ {
public class StandardHealthDisplay : HealthDisplay public class StandardHealthDisplay : HealthDisplay
{ {
private Container fill; private readonly Container fill;
public StandardHealthDisplay() public StandardHealthDisplay()
{ {

View File

@ -17,7 +17,7 @@ namespace osu.Game.Online.API
{ {
public class APIAccess : IUpdateable public class APIAccess : IUpdateable
{ {
private OAuth authentication; private readonly OAuth authentication;
public string Endpoint = @"https://new.ppy.sh"; public string Endpoint = @"https://new.ppy.sh";
private const string client_id = @"5"; private const string client_id = @"5";
@ -44,9 +44,9 @@ namespace osu.Game.Online.API
protected bool HasLogin => Token != null || !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password); protected bool HasLogin => Token != null || !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable (should dispose of this or at very least keep a reference). // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable (should dispose of this or at very least keep a reference).
private Thread thread; private readonly Thread thread;
private Logger log; private readonly Logger log;
public APIAccess() public APIAccess()
{ {
@ -57,7 +57,7 @@ namespace osu.Game.Online.API
thread.Start(); thread.Start();
} }
private List<IOnlineComponent> components = new List<IOnlineComponent>(); private readonly List<IOnlineComponent> components = new List<IOnlineComponent>();
public void Register(IOnlineComponent component) public void Register(IOnlineComponent component)
{ {

View File

@ -58,13 +58,20 @@ namespace osu.Game.Online.API
public event APISuccessHandler Success; public event APISuccessHandler Success;
public event APIFailureHandler Failure; public event APIFailureHandler Failure;
private bool cancelled;
private Action pendingFailure;
public void Perform(APIAccess api) public void Perform(APIAccess api)
{ {
this.api = api;
if (checkAndProcessFailure())
return;
if (startTime == null) if (startTime == null)
startTime = DateTime.Now.TotalMilliseconds(); startTime = DateTime.Now.TotalMilliseconds();
this.api = api;
if (remainingTime <= 0) if (remainingTime <= 0)
throw new TimeoutException(@"API request timeout hit"); throw new TimeoutException(@"API request timeout hit");
@ -72,18 +79,41 @@ namespace osu.Game.Online.API
WebRequest.RetryCount = 0; WebRequest.RetryCount = 0;
WebRequest.Headers[@"Authorization"] = $@"Bearer {api.AccessToken}"; WebRequest.Headers[@"Authorization"] = $@"Bearer {api.AccessToken}";
WebRequest.BlockingPerform(); if (checkAndProcessFailure())
return;
if (!WebRequest.Aborted) //could have been aborted by a Cancel() call
WebRequest.BlockingPerform();
if (checkAndProcessFailure())
return;
api.Scheduler.Add(delegate { Success?.Invoke(); }); api.Scheduler.Add(delegate { Success?.Invoke(); });
} }
public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled"));
public void Fail(Exception e) public void Fail(Exception e)
{ {
cancelled = true;
WebRequest?.Abort(); WebRequest?.Abort();
api.Scheduler.Add(delegate
{ pendingFailure = () => Failure?.Invoke(e);
Failure?.Invoke(e); checkAndProcessFailure();
}); }
/// <summary>
/// Checked for cancellation or error. Also queues up the Failed event if we can.
/// </summary>
/// <returns>Whether we are in a failed or cancelled state.</returns>
private bool checkAndProcessFailure()
{
if (api == null || pendingFailure == null) return cancelled;
api.Scheduler.Add(pendingFailure);
pendingFailure = null;
return true;
} }
} }

View File

@ -9,7 +9,7 @@ namespace osu.Game.Online.API.Requests
{ {
public class GetMessagesRequest : APIRequest<List<Message>> public class GetMessagesRequest : APIRequest<List<Message>>
{ {
private List<Channel> channels; private readonly List<Channel> channels;
private long? since; private long? since;
public GetMessagesRequest(List<Channel> channels, long? sinceId) public GetMessagesRequest(List<Channel> channels, long? sinceId)

View File

@ -0,0 +1,40 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using Newtonsoft.Json;
using osu.Framework.IO.Network;
using osu.Game.Database;
using osu.Game.Modes;
namespace osu.Game.Online.API.Requests
{
public class GetScoresRequest : APIRequest<GetScoresResponse>
{
private readonly BeatmapInfo beatmap;
public GetScoresRequest(BeatmapInfo beatmap)
{
this.beatmap = beatmap;
}
protected override WebRequest CreateWebRequest()
{
var req = base.CreateWebRequest();
req.AddParameter(@"c", beatmap.Hash);
req.AddParameter(@"f", beatmap.Path);
return req;
}
protected override string Target => @"beatmaps/scores";
}
public class GetScoresResponse
{
[JsonProperty(@"beatmap")]
public BeatmapInfo Beatmap;
[JsonProperty(@"scores")]
public IEnumerable<Score> Scores;
}
}

View File

@ -14,8 +14,8 @@ namespace osu.Game.Online.Chat.Drawables
public class DrawableChannel : Container public class DrawableChannel : Container
{ {
private readonly Channel channel; private readonly Channel channel;
private FillFlowContainer flow; private readonly FillFlowContainer flow;
private ScrollContainer scroll; private readonly ScrollContainer scroll;
public DrawableChannel(Channel channel) public DrawableChannel(Channel channel)
{ {

View File

@ -60,7 +60,7 @@ namespace osu.Game
public Bindable<PlayMode> PlayMode; public Bindable<PlayMode> PlayMode;
private string[] args; private readonly string[] args;
private OptionsOverlay options; private OptionsOverlay options;
@ -279,6 +279,7 @@ namespace osu.Game
//central game mode change logic. //central game mode change logic.
if (!currentScreen.ShowOverlays) if (!currentScreen.ShowOverlays)
{ {
options.State = Visibility.Hidden;
Toolbar.State = Visibility.Hidden; Toolbar.State = Visibility.Hidden;
musicController.State = Visibility.Hidden; musicController.State = Visibility.Hidden;
chat.State = Visibility.Hidden; chat.State = Visibility.Hidden;

View File

@ -31,11 +31,11 @@ namespace osu.Game.Overlays
private ScheduledDelegate messageRequest; private ScheduledDelegate messageRequest;
private Container content; private readonly Container content;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private FocusedTextBox inputTextBox; private readonly FocusedTextBox inputTextBox;
private APIAccess api; private APIAccess api;

View File

@ -27,10 +27,12 @@ namespace osu.Game.Overlays.Dialog
private readonly Vector2 ringMinifiedSize = new Vector2(20f); private readonly Vector2 ringMinifiedSize = new Vector2(20f);
private readonly Vector2 buttonsEnterSpacing = new Vector2(0f, 50f); private readonly Vector2 buttonsEnterSpacing = new Vector2(0f, 50f);
private Container content, ring; private readonly Container content;
private FillFlowContainer<PopupDialogButton> buttonsContainer; private readonly Container ring;
private TextAwesome iconText; private readonly FillFlowContainer<PopupDialogButton> buttonsContainer;
private SpriteText header, body; private readonly TextAwesome iconText;
private readonly SpriteText header;
private readonly SpriteText body;
public FontAwesome Icon public FontAwesome Icon
{ {
@ -193,6 +195,7 @@ namespace osu.Game.Overlays.Dialog
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Masking = true,
BorderColour = Color4.White, BorderColour = Color4.White,
BorderThickness = 5f, BorderThickness = 5f,
Children = new Drawable[] Children = new Drawable[]

View File

@ -13,7 +13,7 @@ namespace osu.Game.Overlays
{ {
public class DialogOverlay : FocusedOverlayContainer public class DialogOverlay : FocusedOverlayContainer
{ {
private Container dialogContainer; private readonly Container dialogContainer;
private PopupDialog currentDialog; private PopupDialog currentDialog;
public void Push(PopupDialog dialog) public void Push(PopupDialog dialog)

View File

@ -11,7 +11,7 @@ namespace osu.Game.Overlays
{ {
public class DragBar : Container public class DragBar : Container
{ {
private Box fill; private readonly Box fill;
public Action<float> SeekRequested; public Action<float> SeekRequested;
private bool isDragging; private bool isDragging;

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