Merge remote-tracking branch 'upstream/master' into facade-container

This commit is contained in:
David Zhao
2019-04-02 11:28:44 +09:00
267 changed files with 1996 additions and 2130 deletions

View File

@ -1,11 +0,0 @@
osu!lazer is currently still under heavy development!
Please ensure that you are making an issue for one of the following:
- A bug with currently implemented features (not features that don't exist)
- A feature you are considering adding, so we can collaborate on feedback and design.
- Discussions about technical design decisions
If your issue qualifies, replace this text with a detailed description of your issue with as much relevant information as you can provide.
Screenshots and log files are highly welcomed.

View File

@ -1,14 +1,11 @@
--- ---
name: Bug Report name: Bug Report
about: For issues regarding encountered game bugs about: Issues regarding encountered bugs.
--- ---
**Describe the bug:**
<!-- After you fill in all information, delete all comments in the issue -->
**Describe your problem:** <!-- Provide any information you believe could be useful -->
**Screenshots or videos showing encountered issue:** **Screenshots or videos showing encountered issue:**
**osu!lazer version:** <!-- Provide the version of your osu!lazer, you can find it at the bottom of the screen --> **osu!lazer version:**
**Logs:** <!-- Attach your osu!lazer logs, you can find them under %appdata%\osu\logs in Windows, or under ~/.local/share/osu/ in Linux and macOS --> **Logs:**

View File

@ -1,16 +1,13 @@
--- ---
name: Crash Report name: Crash Report
about: For issues regarding game crashes or permanent freezes about: Issues regarding crashes or permanent freezes.
--- ---
**Describe the crash:**
<!-- After you fill in all information, delete all comments in the issue -->
**Describe your problem:** <!-- Provide any information you believe could be useful -->
**Screenshots or videos showing encountered issue:** **Screenshots or videos showing encountered issue:**
**osu!lazer version:** <!-- Provide the version of your osu!lazer, you can find it at the bottom of the screen --> **osu!lazer version:**
**Logs:** <!-- Attach your osu!lazer logs, you can find them under %appdata%\osu\logs in Windows, or under ~/.local/share/osu/ in Linux and macOS --> **Logs:**
**Computer Specifications:** <!-- Attach your computer specifications, you can find them by using System Information in Windows, System Monitor in Linux, or About This Mac in macOS --> **Computer Specifications:**

View File

@ -1,10 +1,7 @@
--- ---
name: Feature Request name: Feature Request
about: Let us know what you would like to see in the game! about: Features you would like to see in the game!
--- ---
**Describe the new feature:**
<!-- After you fill in all information, delete all comments in the issue --> **Proposal designs of the feature:**
**Describe the feature:** <!-- Describe the feature you would like to see in the game -->
**Proposal designs of the feature:** <!-- Attach screenshots of how the feature should look like according to you -->

View File

@ -1,10 +1,7 @@
--- ---
name: Missing for Live name: Missing for Live
about: Let us know the features you need which are available in osu-stable but not lazer about: Features which are available in osu!stable but not yet in osu!lazer.
--- ---
**Describe the missing feature:**
<!-- After you fill in all information, delete all comments in the issue --> **Proposal designs of the feature:**
**Describe the feature:** <!-- Describe the missing game feature -->
**Designs:** <!-- Attach screenshots of how the feature is supposed to look like. For illustrative purpose only; final designs are usually re-imagined from scratch. -->

View File

@ -14,6 +14,7 @@ using osuTK.Input;
using Microsoft.Win32; using Microsoft.Win32;
using osu.Desktop.Updater; using osu.Desktop.Updater;
using osu.Framework; using osu.Framework;
using osu.Framework.Logging;
using osu.Framework.Platform.Windows; using osu.Framework.Platform.Windows;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
@ -35,12 +36,15 @@ namespace osu.Desktop
{ {
try try
{ {
return new StableStorage(); if (Host is DesktopGameHost desktopHost)
return new StableStorage(desktopHost);
} }
catch catch (Exception e)
{ {
return null; Logger.Error(e, "Error while searching for stable install");
} }
return null;
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -139,8 +143,8 @@ namespace osu.Desktop
return null; return null;
} }
public StableStorage() public StableStorage(DesktopGameHost host)
: base(string.Empty, null) : base(string.Empty, host)
{ {
} }
} }

View File

@ -110,7 +110,7 @@ namespace osu.Desktop.Overlays
public UpdateCompleteNotification(string version, Action<string> openUrl = null) public UpdateCompleteNotification(string version, Action<string> openUrl = null)
{ {
Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; Text = $"You are now running osu!lazer {version}.\nClick to see what's new!";
Icon = FontAwesome.fa_check_square; Icon = FontAwesome.CheckSquare;
Activated = delegate Activated = delegate
{ {
openUrl?.Invoke($"https://osu.ppy.sh/home/changelog/lazer/{version}"); openUrl?.Invoke($"https://osu.ppy.sh/home/changelog/lazer/{version}");

View File

@ -7,10 +7,10 @@ using Newtonsoft.Json;
using osu.Framework; using osu.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.IO.Network; using osu.Framework.IO.Network;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game; using osu.Game;
using osu.Game.Graphics;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
@ -54,7 +54,7 @@ namespace osu.Desktop.Updater
{ {
Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n" Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n"
+ "Click here to download the new version, which can be installed over the top of your existing installation", + "Click here to download the new version, which can be installed over the top of your existing installation",
Icon = FontAwesome.fa_upload, Icon = FontAwesome.Upload,
Activated = () => Activated = () =>
{ {
host.OpenUrlExternally(getBestUrl(latest)); host.OpenUrlExternally(getBestUrl(latest));

View File

@ -9,6 +9,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Game; using osu.Game;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -158,7 +159,7 @@ namespace osu.Desktop.Updater
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Icon = FontAwesome.fa_upload, Icon = FontAwesome.Upload,
Colour = Color4.White, Colour = Color4.White,
Size = new Vector2(20), Size = new Vector2(20),
} }

View File

@ -3,8 +3,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
namespace osu.Game.Rulesets.Catch.Beatmaps namespace osu.Game.Rulesets.Catch.Beatmaps
@ -23,19 +23,19 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
{ {
Name = @"Fruit Count", Name = @"Fruit Count",
Content = fruits.ToString(), Content = fruits.ToString(),
Icon = FontAwesome.fa_circle_o Icon = FontAwesome.CircleOutline
}, },
new BeatmapStatistic new BeatmapStatistic
{ {
Name = @"Juice Stream Count", Name = @"Juice Stream Count",
Content = juiceStreams.ToString(), Content = juiceStreams.ToString(),
Icon = FontAwesome.fa_circle Icon = FontAwesome.Circle
}, },
new BeatmapStatistic new BeatmapStatistic
{ {
Name = @"Banana Shower Count", Name = @"Banana Shower Count",
Content = bananaShowers.ToString(), Content = bananaShowers.ToString(),
Icon = FontAwesome.fa_circle Icon = FontAwesome.Circle
} }
}; };
} }

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Replays;
@ -17,6 +18,7 @@ using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Difficulty; using osu.Game.Rulesets.Catch.Difficulty;
using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Catch namespace osu.Game.Rulesets.Catch
{ {
@ -114,10 +116,12 @@ namespace osu.Game.Rulesets.Catch
public override string ShortName => "fruits"; public override string ShortName => "fruits";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch };
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap); public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new CatchPerformanceCalculator(this, beatmap, score);
public override int? LegacyID => 2; public override int? LegacyID => 2;
public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new CatchReplayFrame(); public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new CatchReplayFrame();

View File

@ -0,0 +1,104 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Scoring.Legacy;
using osuTK;
namespace osu.Game.Rulesets.Catch.Difficulty
{
public class CatchPerformanceCalculator : PerformanceCalculator
{
protected new CatchDifficultyAttributes Attributes => (CatchDifficultyAttributes)base.Attributes;
private Mod[] mods;
private int fruitsHit;
private int ticksHit;
private int tinyTicksHit;
private int tinyTicksMissed;
private int misses;
public CatchPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score)
: base(ruleset, beatmap, score)
{
}
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
{
mods = Score.Mods;
var legacyScore = Score as LegacyScoreInfo;
fruitsHit = legacyScore?.Count300 ?? Score.Statistics[HitResult.Perfect];
ticksHit = legacyScore?.Count100 ?? 0;
tinyTicksHit = legacyScore?.Count50 ?? 0;
tinyTicksMissed = legacyScore?.CountKatu ?? 0;
misses = Score.Statistics[HitResult.Miss];
// Don't count scores made with supposedly unranked mods
if (mods.Any(m => !m.Ranked))
return 0;
// We are heavily relying on aim in catch the beat
double value = Math.Pow(5.0f * Math.Max(1.0f, Attributes.StarRating / 0.0049f) - 4.0f, 2.0f) / 100000.0f;
// Longer maps are worth more. "Longer" means how many hits there are which can contribute to combo
int numTotalHits = totalComboHits();
// Longer maps are worth more
float lengthBonus =
0.95f + 0.4f * Math.Min(1.0f, numTotalHits / 3000.0f) +
(numTotalHits > 3000 ? (float)Math.Log10(numTotalHits / 3000.0f) * 0.5f : 0.0f);
// Longer maps are worth more
value *= lengthBonus;
// Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available
value *= Math.Pow(0.97f, misses);
// Combo scaling
float beatmapMaxCombo = Attributes.MaxCombo;
if (beatmapMaxCombo > 0)
value *= Math.Min(Math.Pow(Attributes.MaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f);
float approachRate = (float)Attributes.ApproachRate;
float approachRateFactor = 1.0f;
if (approachRate > 9.0f)
approachRateFactor += 0.1f * (approachRate - 9.0f); // 10% for each AR above 9
else if (approachRate < 8.0f)
approachRateFactor += 0.025f * (8.0f - approachRate); // 2.5% for each AR below 8
value *= approachRateFactor;
if (mods.Any(m => m is ModHidden))
// Hiddens gives nothing on max approach rate, and more the lower it is
value *= 1.05f + 0.075f * (10.0f - Math.Min(10.0f, approachRate)); // 7.5% for each AR below 10
if (mods.Any(m => m is ModFlashlight))
// Apply length bonus again if flashlight is on simply because it becomes a lot harder on longer maps.
value *= 1.35f * lengthBonus;
// Scale the aim value with accuracy _slightly_
value *= Math.Pow(accuracy(), 5.5f);
// Custom multipliers for NoFail. SpunOut is not applicable.
if (mods.Any(m => m is ModNoFail))
value *= 0.90f;
return value;
}
private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f);
private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed;
private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit;
private int totalComboHits() => misses + ticksHit + fruitsHit;
}
}

View File

@ -13,17 +13,17 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {
private readonly Container bananaContainer; private readonly Container bananaContainer;
public DrawableBananaShower(BananaShower s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation = null) public DrawableBananaShower(BananaShower s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation = null)
: base(s) : base(s)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Origin = Anchor.BottomLeft; Origin = Anchor.BottomLeft;
X = 0; X = 0;
InternalChild = bananaContainer = new Container { RelativeSizeAxes = Axes.Both }; AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both });
foreach (var b in s.NestedHitObjects.Cast<Banana>()) foreach (var b in s.NestedHitObjects.Cast<Banana>())
AddNested(getVisualRepresentation?.Invoke(b)); AddNested(createDrawableRepresentation?.Invoke(b));
} }
protected override void AddNested(DrawableHitObject h) protected override void AddNested(DrawableHitObject h)

View File

@ -26,10 +26,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
InternalChild = pulp = new Pulp AddInternal(pulp = new Pulp { Size = Size });
{
Size = Size
};
} }
public override Color4 AccentColour public override Color4 AccentColour

View File

@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
// todo: this should come from the skin. // todo: this should come from the skin.
AccentColour = colourForRepresentation(HitObject.VisualRepresentation); AccentColour = colourForRepresentation(HitObject.VisualRepresentation);
InternalChildren = new[] AddRangeInternal(new[]
{ {
createPulp(HitObject.VisualRepresentation), createPulp(HitObject.VisualRepresentation),
border = new Circle border = new Circle
@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
} }
} }
}, },
}; });
if (HitObject.HyperDash) if (HitObject.HyperDash)
{ {

View File

@ -13,17 +13,17 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {
private readonly Container dropletContainer; private readonly Container dropletContainer;
public DrawableJuiceStream(JuiceStream s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation = null) public DrawableJuiceStream(JuiceStream s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation = null)
: base(s) : base(s)
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Origin = Anchor.BottomLeft; Origin = Anchor.BottomLeft;
X = 0; X = 0;
InternalChild = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, });
foreach (var o in s.NestedHitObjects.Cast<CatchHitObject>()) foreach (var o in s.NestedHitObjects.Cast<CatchHitObject>())
AddNested(getVisualRepresentation?.Invoke(o)); AddNested(createDrawableRepresentation?.Invoke(o));
} }
protected override void AddNested(DrawableHitObject h) protected override void AddNested(DrawableHitObject h)

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using osu.Framework.Input.StateChanges; using osu.Framework.Input.StateChanges;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Replays; using osu.Game.Replays;
@ -22,10 +23,14 @@ namespace osu.Game.Rulesets.Catch.Replays
{ {
get get
{ {
if (!HasFrames) var frame = CurrentFrame;
if (frame == null)
return null; return null;
return Interpolation.ValueAt(CurrentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time); Debug.Assert(CurrentTime != null);
return NextFrame != null ? Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time) : frame.Position;
} }
} }

View File

@ -10,7 +10,6 @@ using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
using osuTK;
namespace osu.Game.Rulesets.Catch.UI namespace osu.Game.Rulesets.Catch.UI
{ {
@ -20,33 +19,24 @@ namespace osu.Game.Rulesets.Catch.UI
internal readonly CatcherArea CatcherArea; internal readonly CatcherArea CatcherArea;
public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation) public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation)
{ {
Container explodingFruitContainer; Container explodingFruitContainer;
Anchor = Anchor.TopCentre; InternalChildren = new Drawable[]
Origin = Anchor.TopCentre;
Size = new Vector2(0.86f); // matches stable's vertical offset for catcher plate
InternalChild = new PlayfieldAdjustmentContainer
{ {
RelativeSizeAxes = Axes.Both, explodingFruitContainer = new Container
Children = new Drawable[]
{ {
explodingFruitContainer = new Container RelativeSizeAxes = Axes.Both,
{ },
RelativeSizeAxes = Axes.Both, CatcherArea = new CatcherArea(difficulty)
}, {
CatcherArea = new CatcherArea(difficulty) CreateDrawableRepresentation = createDrawableRepresentation,
{ ExplodingFruitTarget = explodingFruitContainer,
GetVisualRepresentation = getVisualRepresentation, Anchor = Anchor.BottomLeft,
ExplodingFruitTarget = explodingFruitContainer, Origin = Anchor.TopLeft,
Anchor = Anchor.BottomLeft, },
Origin = Anchor.TopLeft, HitObjectContainer
},
HitObjectContainer
}
}; };
} }

View File

@ -3,17 +3,23 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.UI;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Catch.UI namespace osu.Game.Rulesets.Catch.UI
{ {
public class PlayfieldAdjustmentContainer : Container public class CatchPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
{ {
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private readonly Container content; private readonly Container content;
public PlayfieldAdjustmentContainer() public CatchPlayfieldAdjustmentContainer()
{ {
Anchor = Anchor.TopCentre;
Origin = Anchor.TopCentre;
Size = new Vector2(0.86f); // matches stable's vertical offset for catcher plate
InternalChild = new Container InternalChild = new Container
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,

View File

@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.UI
protected internal readonly Catcher MovableCatcher; protected internal readonly Catcher MovableCatcher;
public Func<CatchHitObject, DrawableHitObject<CatchHitObject>> GetVisualRepresentation; public Func<CatchHitObject, DrawableHitObject<CatchHitObject>> CreateDrawableRepresentation;
public Container ExplodingFruitTarget public Container ExplodingFruitTarget
{ {
@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.UI
if (result.IsHit && fruit.CanBePlated) if (result.IsHit && fruit.CanBePlated)
{ {
var caughtFruit = (DrawableCatchHitObject)GetVisualRepresentation?.Invoke(fruit.HitObject); var caughtFruit = (DrawableCatchHitObject)CreateDrawableRepresentation?.Invoke(fruit.HitObject);
if (caughtFruit == null) return; if (caughtFruit == null) return;

View File

@ -34,11 +34,13 @@ namespace osu.Game.Rulesets.Catch.UI
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay); protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation); protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, CreateDrawableRepresentation);
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new CatchPlayfieldAdjustmentContainer();
protected override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); protected override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);
public override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h) public override DrawableHitObject<CatchHitObject> CreateDrawableRepresentation(CatchHitObject h)
{ {
switch (h) switch (h)
{ {
@ -47,9 +49,9 @@ namespace osu.Game.Rulesets.Catch.UI
case Fruit fruit: case Fruit fruit:
return new DrawableFruit(fruit); return new DrawableFruit(fruit);
case JuiceStream stream: case JuiceStream stream:
return new DrawableJuiceStream(stream, GetVisualRepresentation); return new DrawableJuiceStream(stream, CreateDrawableRepresentation);
case BananaShower shower: case BananaShower shower:
return new DrawableBananaShower(shower, GetVisualRepresentation); return new DrawableBananaShower(shower, CreateDrawableRepresentation);
case TinyDroplet tiny: case TinyDroplet tiny:
return new DrawableTinyDroplet(tiny); return new DrawableTinyDroplet(tiny);
case Droplet droplet: case Droplet droplet:

View File

@ -3,8 +3,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
@ -42,13 +42,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
{ {
Name = @"Note Count", Name = @"Note Count",
Content = notes.ToString(), Content = notes.ToString(),
Icon = FontAwesome.fa_circle_o Icon = FontAwesome.CircleOutline
}, },
new BeatmapStatistic new BeatmapStatistic
{ {
Name = @"Hold Note Count", Name = @"Hold Note Count",
Content = holdnotes.ToString(), Content = holdnotes.ToString(),
Icon = FontAwesome.fa_circle Icon = FontAwesome.Circle
}, },
}; };
} }

View File

@ -10,6 +10,7 @@ using osu.Game.Rulesets.UI;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
@ -160,7 +161,7 @@ namespace osu.Game.Rulesets.Mania
public override string ShortName => "mania"; public override string ShortName => "mania";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania };
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new ManiaDifficultyCalculator(this, beatmap); public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new ManiaDifficultyCalculator(this, beatmap);

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -12,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override string Name => "Fade In"; public override string Name => "Fade In";
public override string Acronym => "FI"; public override string Acronym => "FI";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; public override IconUsage Icon => OsuIcon.ModHidden;
public override ModType Type => ModType.DifficultyIncrease; public override ModType Type => ModType.DifficultyIncrease;
public override string Description => @"Keys appear out of nowhere!"; public override string Description => @"Keys appear out of nowhere!";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;

View File

@ -3,6 +3,7 @@
using System.Linq; using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public override string Name => "Random"; public override string Name => "Random";
public override string Acronym => "RD"; public override string Acronym => "RD";
public override ModType Type => ModType.Conversion; public override ModType Type => ModType.Conversion;
public override FontAwesome Icon => FontAwesome.fa_osu_dice; public override IconUsage Icon => OsuIcon.Dice;
public override string Description => @"Shuffle around the keys!"; public override string Description => @"Shuffle around the keys!";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;

View File

@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
InternalChildren = new Drawable[] AddRangeInternal(new Drawable[]
{ {
bodyPiece = new BodyPiece bodyPiece = new BodyPiece
{ {
@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre Origin = Anchor.TopCentre
} }
}; });
foreach (var tick in tickContainer) foreach (var tick in tickContainer)
AddNested(tick); AddNested(tick);

View File

@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Size = new Vector2(1); Size = new Vector2(1);
InternalChildren = new[] AddRangeInternal(new[]
{ {
glowContainer = new CircularContainer glowContainer = new CircularContainer
{ {
@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
} }
} }
} }
}; });
} }
public override Color4 AccentColour public override Color4 AccentColour

View File

@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
CornerRadius = 5; CornerRadius = 5;
Masking = true; Masking = true;
InternalChild = headPiece = new NotePiece(); AddInternal(headPiece = new NotePiece());
} }
protected override void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e) protected override void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e)

View File

@ -18,6 +18,6 @@ namespace osu.Game.Rulesets.Mania.Replays
protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any(); protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any();
public override List<IInput> GetPendingInputs() => new List<IInput> { new ReplayState<ManiaAction> { PressedActions = CurrentFrame.Actions } }; public override List<IInput> GetPendingInputs() => new List<IInput> { new ReplayState<ManiaAction> { PressedActions = CurrentFrame?.Actions ?? new List<ManiaAction>() } };
} }
} }

View File

@ -6,7 +6,6 @@ using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -89,11 +88,9 @@ namespace osu.Game.Rulesets.Mania.UI
/// <returns>The column which intersects with <paramref name="screenSpacePosition"/>.</returns> /// <returns>The column which intersects with <paramref name="screenSpacePosition"/>.</returns>
public Column GetColumnByPosition(Vector2 screenSpacePosition) => Playfield.GetColumnByPosition(screenSpacePosition); public Column GetColumnByPosition(Vector2 screenSpacePosition) => Playfield.GetColumnByPosition(screenSpacePosition);
protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new ManiaPlayfieldAdjustmentContainer();
{
Anchor = Anchor.Centre, protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages);
Origin = Anchor.Centre,
};
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this);
@ -101,7 +98,7 @@ namespace osu.Game.Rulesets.Mania.UI
protected override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant); protected override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant);
public override DrawableHitObject<ManiaHitObject> GetVisualRepresentation(ManiaHitObject h) public override DrawableHitObject<ManiaHitObject> CreateDrawableRepresentation(ManiaHitObject h)
{ {
switch (h) switch (h)
{ {

View File

@ -28,8 +28,6 @@ namespace osu.Game.Rulesets.Mania.UI
if (stageDefinitions.Count <= 0) if (stageDefinitions.Count <= 0)
throw new ArgumentException("Can't have zero or fewer stages."); throw new ArgumentException("Can't have zero or fewer stages.");
Size = new Vector2(1, 0.8f);
GridContainer playfieldGrid; GridContainer playfieldGrid;
AddInternal(playfieldGrid = new GridContainer AddInternal(playfieldGrid = new GridContainer
{ {

View File

@ -0,0 +1,20 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using osu.Game.Rulesets.UI;
using osuTK;
namespace osu.Game.Rulesets.Mania.UI
{
public class ManiaPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
{
public ManiaPlayfieldAdjustmentContainer()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Size = new Vector2(1, 0.8f);
}
}
}

View File

@ -9,6 +9,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Cursor;
using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Rulesets.Osu.UI.Cursor;
using osu.Game.Rulesets.UI;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
@ -27,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Tests
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Add(cursorContainer = new GameplayCursorContainer { RelativeSizeAxes = Axes.Both }); Add(cursorContainer = new OsuCursorContainer { RelativeSizeAxes = Axes.Both });
} }
} }
} }

View File

@ -297,11 +297,6 @@ namespace osu.Game.Rulesets.Osu.Tests
private void performTest(List<ReplayFrame> frames) private void performTest(List<ReplayFrame> frames)
{ {
// Empty frame to be added as a workaround for first frame behavior.
// If an input exists on the first frame, the input would apply to the entire intro lead-in
// Likely requires some discussion regarding how first frame inputs should be handled.
frames.Insert(0, new OsuReplayFrame());
AddStep("load player", () => AddStep("load player", () =>
{ {
Beatmap.Value = new TestWorkingBeatmap(new Beatmap<OsuHitObject> Beatmap.Value = new TestWorkingBeatmap(new Beatmap<OsuHitObject>
@ -330,12 +325,7 @@ namespace osu.Game.Rulesets.Osu.Tests
}, },
}, Clock); }, Clock);
var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } });
{
AllowPause = false,
AllowLeadIn = false,
AllowResults = false
};
p.OnLoadComplete += _ => p.OnLoadComplete += _ =>
{ {
@ -364,7 +354,7 @@ namespace osu.Game.Rulesets.Osu.Tests
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
public ScoreAccessibleReplayPlayer(Score score) public ScoreAccessibleReplayPlayer(Score score)
: base(score) : base(score, false, false)
{ {
} }
} }

View File

@ -3,8 +3,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Beatmaps namespace osu.Game.Rulesets.Osu.Beatmaps
@ -23,19 +23,19 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
{ {
Name = @"Circle Count", Name = @"Circle Count",
Content = circles.ToString(), Content = circles.ToString(),
Icon = FontAwesome.fa_circle_o Icon = FontAwesome.CircleOutline
}, },
new BeatmapStatistic new BeatmapStatistic
{ {
Name = @"Slider Count", Name = @"Slider Count",
Content = sliders.ToString(), Content = sliders.ToString(),
Icon = FontAwesome.fa_circle Icon = FontAwesome.Circle
}, },
new BeatmapStatistic new BeatmapStatistic
{ {
Name = @"Spinner Count", Name = @"Spinner Count",
Content = spinners.ToString(), Content = spinners.ToString(),
Icon = FontAwesome.fa_circle Icon = FontAwesome.Circle
} }
}; };
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics.Cursor;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
@ -16,11 +15,13 @@ namespace osu.Game.Rulesets.Osu.Edit
{ {
} }
protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor { Size = Vector2.One }; protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor();
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer { Size = Vector2.One };
private class OsuPlayfieldNoCursor : OsuPlayfield private class OsuPlayfieldNoCursor : OsuPlayfield
{ {
protected override CursorContainer CreateCursor() => null; protected override GameplayCursorContainer CreateCursor() => null;
} }
} }
} }

View File

@ -2,8 +2,6 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Edit.Tools;
@ -13,7 +11,6 @@ using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components;
@ -38,8 +35,6 @@ namespace osu.Game.Rulesets.Osu.Edit
public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler();
protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both };
public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
{ {
switch (hitObject) switch (hitObject)

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public override string Name => "Autopilot"; public override string Name => "Autopilot";
public override string Acronym => "AP"; public override string Acronym => "AP";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot; public override IconUsage Icon => OsuIcon.ModAutopilot;
public override ModType Type => ModType.Automation; public override ModType Type => ModType.Automation;
public override string Description => @"Automatic cursor movement - just follow the rhythm."; public override string Description => @"Automatic cursor movement - just follow the rhythm.";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;

View File

@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -24,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public override string Description => "Play with blinds on your screen."; public override string Description => "Play with blinds on your screen.";
public override string Acronym => "BL"; public override string Acronym => "BL";
public override FontAwesome Icon => FontAwesome.fa_adjust; public override IconUsage Icon => FontAwesome.Adjust;
public override ModType Type => ModType.DifficultyIncrease; public override ModType Type => ModType.DifficultyIncrease;
public override bool Ranked => false; public override bool Ranked => false;

View File

@ -3,7 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public override string Acronym => "GR"; public override string Acronym => "GR";
public override FontAwesome Icon => FontAwesome.fa_arrows_v; public override IconUsage Icon => FontAwesome.ArrowsV;
public override ModType Type => ModType.Fun; public override ModType Type => ModType.Fun;

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public override string Name => "Spun Out"; public override string Name => "Spun Out";
public override string Acronym => "SO"; public override string Acronym => "SO";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout; public override IconUsage Icon => OsuIcon.ModSpunout;
public override ModType Type => ModType.DifficultyReduction; public override ModType Type => ModType.DifficultyReduction;
public override string Description => @"Spinners will be automatically completed."; public override string Description => @"Spinners will be automatically completed.";
public override double ScoreMultiplier => 0.9; public override double ScoreMultiplier => 0.9;

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public override string Name => "Target"; public override string Name => "Target";
public override string Acronym => "TP"; public override string Acronym => "TP";
public override ModType Type => ModType.Conversion; public override ModType Type => ModType.Conversion;
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target; public override IconUsage Icon => OsuIcon.ModTarget;
public override string Description => @"Practice keeping up with the beat of the song."; public override string Description => @"Practice keeping up with the beat of the song.";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
} }

View File

@ -4,7 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public override string Name => "Transform"; public override string Name => "Transform";
public override string Acronym => "TR"; public override string Acronym => "TR";
public override FontAwesome Icon => FontAwesome.fa_arrows; public override IconUsage Icon => FontAwesome.Arrows;
public override ModType Type => ModType.Fun; public override ModType Type => ModType.Fun;
public override string Description => "Everything rotates. EVERYTHING."; public override string Description => "Everything rotates. EVERYTHING.";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;

View File

@ -4,7 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public override string Name => "Wiggle"; public override string Name => "Wiggle";
public override string Acronym => "WG"; public override string Acronym => "WG";
public override FontAwesome Icon => FontAwesome.fa_certificate; public override IconUsage Icon => FontAwesome.Certificate;
public override ModType Type => ModType.Fun; public override ModType Type => ModType.Fun;
public override string Description => "They just won't stay still..."; public override string Description => "They just won't stay still...";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;

View File

@ -4,10 +4,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osuTK; using osuTK;
using osu.Game.Graphics;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning; using osu.Game.Skinning;
@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Icon = FontAwesome.fa_chevron_right Icon = FontAwesome.ChevronRight
}, restrictSize: false) }, restrictSize: false)
}; };
} }

View File

@ -12,6 +12,7 @@ using osu.Game.Graphics;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -76,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(48), Size = new Vector2(48),
Icon = FontAwesome.fa_asterisk, Icon = FontAwesome.Asterisk,
Shadow = false, Shadow = false,
}, },
} }

View File

@ -6,6 +6,7 @@ using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osuTK.Graphics; using osuTK.Graphics;
@ -14,7 +15,7 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
public class SliderBall : CircularContainer, ISliderProgress public class SliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition
{ {
private const float width = 128; private const float width = 128;
@ -107,18 +108,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
private Vector2? lastScreenSpaceMousePosition; private Vector2? lastScreenSpaceMousePosition;
protected override bool OnMouseDown(MouseDownEvent e)
{
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;
return base.OnMouseDown(e);
}
protected override bool OnMouseUp(MouseUpEvent e)
{
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;
return base.OnMouseUp(e);
}
protected override bool OnMouseMove(MouseMoveEvent e) protected override bool OnMouseMove(MouseMoveEvent e)
{ {
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition; lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit;
@ -137,7 +138,7 @@ namespace osu.Game.Rulesets.Osu
} }
} }
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetOsu };
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap); public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap);

View File

@ -292,7 +292,6 @@ namespace osu.Game.Rulesets.Osu.Replays
{ {
// We add intermediate frames for spinning / following a slider here. // We add intermediate frames for spinning / following a slider here.
case Spinner spinner: case Spinner spinner:
{
Vector2 difference = startPosition - SPINNER_CENTRE; Vector2 difference = startPosition - SPINNER_CENTRE;
float radius = difference.Length; float radius = difference.Length;
@ -315,9 +314,7 @@ namespace osu.Game.Rulesets.Osu.Replays
endFrame.Position = endPosition; endFrame.Position = endPosition;
break; break;
}
case Slider slider: case Slider slider:
{
for (double j = FrameDelay; j < slider.Duration; j += FrameDelay) for (double j = FrameDelay; j < slider.Duration; j += FrameDelay)
{ {
Vector2 pos = slider.StackedPositionAt(j / slider.Duration); Vector2 pos = slider.StackedPositionAt(j / slider.Duration);
@ -326,7 +323,6 @@ namespace osu.Game.Rulesets.Osu.Replays
AddFrameToReplay(new OsuReplayFrame(slider.EndTime, new Vector2(slider.StackedEndPosition.X, slider.StackedEndPosition.Y), action)); AddFrameToReplay(new OsuReplayFrame(slider.EndTime, new Vector2(slider.StackedEndPosition.X, slider.StackedEndPosition.Y), action));
break; break;
}
} }
// We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed! // We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed!

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using osu.Framework.Input.StateChanges; using osu.Framework.Input.StateChanges;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
@ -24,10 +25,14 @@ namespace osu.Game.Rulesets.Osu.Replays
{ {
get get
{ {
if (!HasFrames) var frame = CurrentFrame;
if (frame == null)
return null; return null;
return Interpolation.ValueAt(CurrentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time); Debug.Assert(CurrentTime != null);
return NextFrame != null ? Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time) : frame.Position;
} }
} }
@ -41,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Replays
}, },
new ReplayState<OsuAction> new ReplayState<OsuAction>
{ {
PressedActions = CurrentFrame.Actions PressedActions = CurrentFrame?.Actions ?? new List<OsuAction>()
} }
}; };
} }

View File

@ -6,7 +6,6 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -14,10 +13,11 @@ using osu.Game.Configuration;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Osu.UI.Cursor namespace osu.Game.Rulesets.Osu.UI.Cursor
{ {
public class GameplayCursorContainer : CursorContainer, IKeyBindingHandler<OsuAction> public class OsuCursorContainer : GameplayCursorContainer, IKeyBindingHandler<OsuAction>
{ {
protected override Drawable CreateCursor() => new OsuCursor(); protected override Drawable CreateCursor() => new OsuCursor();
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private readonly Container<Drawable> fadeContainer; private readonly Container<Drawable> fadeContainer;
public GameplayCursorContainer() public OsuCursorContainer()
{ {
InternalChild = fadeContainer = new Container InternalChild = fadeContainer = new Container
{ {

View File

@ -32,7 +32,9 @@ namespace osu.Game.Rulesets.Osu.UI
protected override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo); protected override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo);
public override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h) public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer();
public override DrawableHitObject<OsuHitObject> CreateDrawableRepresentation(OsuHitObject h)
{ {
switch (h) switch (h)
{ {

View File

@ -10,7 +10,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Cursor;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Rulesets.Osu.UI.Cursor;
@ -24,41 +23,28 @@ namespace osu.Game.Rulesets.Osu.UI
public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); public static readonly Vector2 BASE_SIZE = new Vector2(512, 384);
private readonly PlayfieldAdjustmentContainer adjustmentContainer; protected override GameplayCursorContainer CreateCursor() => new OsuCursorContainer();
protected override Container CursorTargetContainer => adjustmentContainer;
protected override CursorContainer CreateCursor() => new GameplayCursorContainer();
public OsuPlayfield() public OsuPlayfield()
{ {
Anchor = Anchor.Centre; InternalChildren = new Drawable[]
Origin = Anchor.Centre;
Size = new Vector2(0.75f);
InternalChild = adjustmentContainer = new PlayfieldAdjustmentContainer
{ {
RelativeSizeAxes = Axes.Both, connectionLayer = new FollowPointRenderer
Children = new Drawable[]
{ {
connectionLayer = new FollowPointRenderer RelativeSizeAxes = Axes.Both,
{ Depth = 2,
RelativeSizeAxes = Axes.Both, },
Depth = 2, judgementLayer = new JudgementContainer<DrawableOsuJudgement>
}, {
judgementLayer = new JudgementContainer<DrawableOsuJudgement> RelativeSizeAxes = Axes.Both,
{ Depth = 1,
RelativeSizeAxes = Axes.Both, },
Depth = 1, HitObjectContainer,
}, approachCircles = new ApproachCircleProxyContainer
HitObjectContainer, {
approachCircles = new ApproachCircleProxyContainer RelativeSizeAxes = Axes.Both,
{ Depth = -1,
RelativeSizeAxes = Axes.Both, },
Depth = -1,
},
}
}; };
} }

View File

@ -3,17 +3,23 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.UI;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Osu.UI namespace osu.Game.Rulesets.Osu.UI
{ {
public class PlayfieldAdjustmentContainer : Container public class OsuPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
{ {
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private readonly Container content; private readonly Container content;
public PlayfieldAdjustmentContainer() public OsuPlayfieldAdjustmentContainer()
{ {
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Size = new Vector2(0.75f);
InternalChild = new Container InternalChild = new Container
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,

View File

@ -3,8 +3,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
namespace osu.Game.Rulesets.Taiko.Beatmaps namespace osu.Game.Rulesets.Taiko.Beatmaps
@ -23,19 +23,19 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
{ {
Name = @"Hit Count", Name = @"Hit Count",
Content = hits.ToString(), Content = hits.ToString(),
Icon = FontAwesome.fa_circle_o Icon = FontAwesome.CircleOutline
}, },
new BeatmapStatistic new BeatmapStatistic
{ {
Name = @"Drumroll Count", Name = @"Drumroll Count",
Content = drumrolls.ToString(), Content = drumrolls.ToString(),
Icon = FontAwesome.fa_circle Icon = FontAwesome.Circle
}, },
new BeatmapStatistic new BeatmapStatistic
{ {
Name = @"Swell Count", Name = @"Swell Count",
Content = swells.ToString(), Content = swells.ToString(),
Icon = FontAwesome.fa_circle Icon = FontAwesome.Circle
} }
}; };
} }

View File

@ -44,17 +44,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
RelativeSizeAxes = Axes.Y; RelativeSizeAxes = Axes.Y;
Width = tracker_width; Width = tracker_width;
InternalChildren = new[] AddInternal(Tracker = new Box
{ {
Tracker = new Box Anchor = Anchor.Centre,
{ Origin = Anchor.Centre,
Anchor = Anchor.Centre, RelativeSizeAxes = Axes.Both,
Origin = Anchor.Centre, EdgeSmoothness = new Vector2(0.5f, 0),
RelativeSizeAxes = Axes.Both, Alpha = 0.75f
EdgeSmoothness = new Vector2(0.5f, 0), });
Alpha = 0.75f
}
};
} }
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)

View File

@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
protected DrawableTaikoHitObject(TaikoHitObject hitObject) protected DrawableTaikoHitObject(TaikoHitObject hitObject)
: base(hitObject) : base(hitObject)
{ {
InternalChildren = new[] AddRangeInternal(new[]
{ {
nonProxiedContent = new Container nonProxiedContent = new Container
{ {
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
Child = Content = new Container { RelativeSizeAxes = Axes.Both } Child = Content = new Container { RelativeSizeAxes = Axes.Both }
}, },
proxiedContent = new ProxiedContentContainer { RelativeSizeAxes = Axes.Both } proxiedContent = new ProxiedContentContainer { RelativeSizeAxes = Axes.Both }
}; });
} }
/// <summary> /// <summary>

View File

@ -4,7 +4,7 @@
using osuTK; using osuTK;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
{ {
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
new SpriteIcon new SpriteIcon
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Icon = FontAwesome.fa_asterisk, Icon = FontAwesome.Asterisk,
Shadow = false Shadow = false
} }
}; };

View File

@ -18,6 +18,6 @@ namespace osu.Game.Rulesets.Taiko.Replays
protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any(); protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any();
public override List<IInput> GetPendingInputs() => new List<IInput> { new ReplayState<TaikoAction> { PressedActions = CurrentFrame.Actions } }; public override List<IInput> GetPendingInputs() => new List<IInput> { new ReplayState<TaikoAction> { PressedActions = CurrentFrame?.Actions ?? new List<TaikoAction>() } };
} }
} }

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Taiko.UI;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
@ -114,7 +115,7 @@ namespace osu.Game.Rulesets.Taiko
public override string ShortName => "taiko"; public override string ShortName => "taiko";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetTaiko };
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap); public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap);

View File

@ -81,11 +81,13 @@ namespace osu.Game.Rulesets.Taiko.UI
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer();
protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo);
protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo); protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo);
public override DrawableHitObject<TaikoHitObject> GetVisualRepresentation(TaikoHitObject h) public override DrawableHitObject<TaikoHitObject> CreateDrawableRepresentation(TaikoHitObject h)
{ {
switch (h) switch (h)
{ {

View File

@ -55,143 +55,137 @@ namespace osu.Game.Rulesets.Taiko.UI
public TaikoPlayfield(ControlPointInfo controlPoints) public TaikoPlayfield(ControlPointInfo controlPoints)
{ {
InternalChild = new PlayfieldAdjustmentContainer InternalChildren = new Drawable[]
{ {
Anchor = Anchor.CentreLeft, backgroundContainer = new Container
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{ {
backgroundContainer = new Container Name = "Transparent playfield background",
RelativeSizeAxes = Axes.Both,
Masking = true,
EdgeEffect = new EdgeEffectParameters
{ {
Name = "Transparent playfield background", Type = EdgeEffectType.Shadow,
RelativeSizeAxes = Axes.Both, Colour = Color4.Black.Opacity(0.2f),
Masking = true, Radius = 5,
EdgeEffect = new EdgeEffectParameters },
Children = new Drawable[]
{
background = new Box
{ {
Type = EdgeEffectType.Shadow, RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(0.2f), Alpha = 0.6f
Radius = 5,
}, },
Children = new Drawable[]
{
background = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.6f
},
}
},
new Container
{
Name = "Right area",
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = left_area_size },
Children = new Drawable[]
{
new Container
{
Name = "Masked elements before hit objects",
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
Masking = true,
Children = new Drawable[]
{
hitExplosionContainer = new Container<HitExplosion>
{
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
Blending = BlendingMode.Additive,
},
HitTarget = new HitTarget
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit
}
}
},
barlineContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }
},
new Container
{
Name = "Hit objects",
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
Masking = true,
Child = HitObjectContainer
},
kiaiExplosionContainer = new Container<KiaiHitExplosion>
{
Name = "Kiai hit explosions",
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
Blending = BlendingMode.Additive
},
judgementContainer = new JudgementContainer<DrawableTaikoJudgement>
{
Name = "Judgements",
RelativeSizeAxes = Axes.Y,
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
Blending = BlendingMode.Additive
},
}
},
overlayBackgroundContainer = new Container
{
Name = "Left overlay",
RelativeSizeAxes = Axes.Y,
Size = new Vector2(left_area_size, 1),
Children = new Drawable[]
{
overlayBackground = new Box
{
RelativeSizeAxes = Axes.Both,
},
new InputDrum(controlPoints)
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Scale = new Vector2(0.9f),
Margin = new MarginPadding { Right = 20 }
},
new Box
{
Anchor = Anchor.TopRight,
RelativeSizeAxes = Axes.Y,
Width = 10,
Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)),
},
}
},
new Container
{
Name = "Border",
RelativeSizeAxes = Axes.Both,
Masking = true,
MaskingSmoothness = 0,
BorderThickness = 2,
AlwaysPresent = true,
Children = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true
}
}
},
topLevelHitContainer = new Container
{
Name = "Top level hit objects",
RelativeSizeAxes = Axes.Both,
} }
},
new Container
{
Name = "Right area",
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = left_area_size },
Children = new Drawable[]
{
new Container
{
Name = "Masked elements before hit objects",
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
Masking = true,
Children = new Drawable[]
{
hitExplosionContainer = new Container<HitExplosion>
{
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
Blending = BlendingMode.Additive,
},
HitTarget = new HitTarget
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit
}
}
},
barlineContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }
},
new Container
{
Name = "Hit objects",
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
Masking = true,
Child = HitObjectContainer
},
kiaiExplosionContainer = new Container<KiaiHitExplosion>
{
Name = "Kiai hit explosions",
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
Blending = BlendingMode.Additive
},
judgementContainer = new JudgementContainer<DrawableTaikoJudgement>
{
Name = "Judgements",
RelativeSizeAxes = Axes.Y,
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
Blending = BlendingMode.Additive
},
}
},
overlayBackgroundContainer = new Container
{
Name = "Left overlay",
RelativeSizeAxes = Axes.Y,
Size = new Vector2(left_area_size, 1),
Children = new Drawable[]
{
overlayBackground = new Box
{
RelativeSizeAxes = Axes.Both,
},
new InputDrum(controlPoints)
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Scale = new Vector2(0.9f),
Margin = new MarginPadding { Right = 20 }
},
new Box
{
Anchor = Anchor.TopRight,
RelativeSizeAxes = Axes.Y,
Width = 10,
Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)),
},
}
},
new Container
{
Name = "Border",
RelativeSizeAxes = Axes.Both,
Masking = true,
MaskingSmoothness = 0,
BorderThickness = 2,
AlwaysPresent = true,
Children = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true
}
}
},
topLevelHitContainer = new Container
{
Name = "Top level hit objects",
RelativeSizeAxes = Axes.Both,
} }
}; };
} }

View File

@ -1,16 +1,23 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics;
using osu.Game.Rulesets.UI;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
{ {
public class PlayfieldAdjustmentContainer : Container public class TaikoPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
{ {
private const float default_relative_height = TaikoPlayfield.DEFAULT_HEIGHT / 768; private const float default_relative_height = TaikoPlayfield.DEFAULT_HEIGHT / 768;
private const float default_aspect = 16f / 9f; private const float default_aspect = 16f / 9f;
public TaikoPlayfieldAdjustmentContainer()
{
Anchor = Anchor.CentreLeft;
Origin = Anchor.CentreLeft;
}
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();

View File

@ -29,28 +29,28 @@ namespace osu.Game.Tests.Beatmaps.Formats
StoryboardLayer background = storyboard.Layers.FirstOrDefault(l => l.Depth == 3); StoryboardLayer background = storyboard.Layers.FirstOrDefault(l => l.Depth == 3);
Assert.IsNotNull(background); Assert.IsNotNull(background);
Assert.AreEqual(16, background.Elements.Count()); Assert.AreEqual(16, background.Elements.Count);
Assert.IsTrue(background.EnabledWhenFailing); Assert.IsTrue(background.EnabledWhenFailing);
Assert.IsTrue(background.EnabledWhenPassing); Assert.IsTrue(background.EnabledWhenPassing);
Assert.AreEqual("Background", background.Name); Assert.AreEqual("Background", background.Name);
StoryboardLayer fail = storyboard.Layers.FirstOrDefault(l => l.Depth == 2); StoryboardLayer fail = storyboard.Layers.FirstOrDefault(l => l.Depth == 2);
Assert.IsNotNull(fail); Assert.IsNotNull(fail);
Assert.AreEqual(0, fail.Elements.Count()); Assert.AreEqual(0, fail.Elements.Count);
Assert.IsTrue(fail.EnabledWhenFailing); Assert.IsTrue(fail.EnabledWhenFailing);
Assert.IsFalse(fail.EnabledWhenPassing); Assert.IsFalse(fail.EnabledWhenPassing);
Assert.AreEqual("Fail", fail.Name); Assert.AreEqual("Fail", fail.Name);
StoryboardLayer pass = storyboard.Layers.FirstOrDefault(l => l.Depth == 1); StoryboardLayer pass = storyboard.Layers.FirstOrDefault(l => l.Depth == 1);
Assert.IsNotNull(pass); Assert.IsNotNull(pass);
Assert.AreEqual(0, pass.Elements.Count()); Assert.AreEqual(0, pass.Elements.Count);
Assert.IsFalse(pass.EnabledWhenFailing); Assert.IsFalse(pass.EnabledWhenFailing);
Assert.IsTrue(pass.EnabledWhenPassing); Assert.IsTrue(pass.EnabledWhenPassing);
Assert.AreEqual("Pass", pass.Name); Assert.AreEqual("Pass", pass.Name);
StoryboardLayer foreground = storyboard.Layers.FirstOrDefault(l => l.Depth == 0); StoryboardLayer foreground = storyboard.Layers.FirstOrDefault(l => l.Depth == 0);
Assert.IsNotNull(foreground); Assert.IsNotNull(foreground);
Assert.AreEqual(151, foreground.Elements.Count()); Assert.AreEqual(151, foreground.Elements.Count);
Assert.IsTrue(foreground.EnabledWhenFailing); Assert.IsTrue(foreground.EnabledWhenFailing);
Assert.IsTrue(foreground.EnabledWhenPassing); Assert.IsTrue(foreground.EnabledWhenPassing);
Assert.AreEqual("Foreground", foreground.Name); Assert.AreEqual("Foreground", foreground.Name);
@ -62,7 +62,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
Assert.AreEqual(15, spriteCount); Assert.AreEqual(15, spriteCount);
Assert.AreEqual(1, animationCount); Assert.AreEqual(1, animationCount);
Assert.AreEqual(0, sampleCount); Assert.AreEqual(0, sampleCount);
Assert.AreEqual(background.Elements.Count(), spriteCount + animationCount + sampleCount); Assert.AreEqual(background.Elements.Count, spriteCount + animationCount + sampleCount);
var sprite = background.Elements.ElementAt(0) as StoryboardSprite; var sprite = background.Elements.ElementAt(0) as StoryboardSprite;
Assert.NotNull(sprite); Assert.NotNull(sprite);
@ -70,9 +70,9 @@ namespace osu.Game.Tests.Beatmaps.Formats
Assert.AreEqual(new Vector2(320, 240), sprite.InitialPosition); Assert.AreEqual(new Vector2(320, 240), sprite.InitialPosition);
Assert.IsTrue(sprite.IsDrawable); Assert.IsTrue(sprite.IsDrawable);
Assert.AreEqual(Anchor.Centre, sprite.Origin); Assert.AreEqual(Anchor.Centre, sprite.Origin);
Assert.AreEqual("SB/lyric/ja-21.png", sprite.Path); Assert.AreEqual("SB/black.jpg", sprite.Path);
var animation = background.Elements.ElementAt(12) as StoryboardAnimation; var animation = background.Elements.OfType<StoryboardAnimation>().First();
Assert.NotNull(animation); Assert.NotNull(animation);
Assert.AreEqual(141175, animation.EndTime); Assert.AreEqual(141175, animation.EndTime);
Assert.AreEqual(10, animation.FrameCount); Assert.AreEqual(10, animation.FrameCount);

View File

@ -0,0 +1,284 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using NUnit.Framework;
using osu.Game.Replays;
using osu.Game.Rulesets.Replays;
namespace osu.Game.Tests.NonVisual
{
[TestFixture]
public class FramedReplayinputHandlerTest
{
private Replay replay;
private TestInputHandler handler;
[SetUp]
public void SetUp()
{
handler = new TestInputHandler(replay = new Replay
{
Frames = new List<ReplayFrame>
{
new TestReplayFrame(0),
new TestReplayFrame(1000),
new TestReplayFrame(2000),
new TestReplayFrame(3000, true),
new TestReplayFrame(4000, true),
new TestReplayFrame(5000, true),
new TestReplayFrame(7000, true),
new TestReplayFrame(8000),
}
});
}
[Test]
public void TestNormalPlayback()
{
Assert.IsNull(handler.CurrentFrame);
confirmCurrentFrame(null);
confirmNextFrame(0);
setTime(0, 0);
confirmCurrentFrame(0);
confirmNextFrame(1);
//if we hit the first frame perfectly, time should progress to it.
setTime(1000, 1000);
confirmCurrentFrame(1);
confirmNextFrame(2);
//in between non-important frames should progress based on input.
setTime(1200, 1200);
confirmCurrentFrame(1);
setTime(1400, 1400);
confirmCurrentFrame(1);
// progressing beyond the next frame should force time to that frame once.
setTime(2200, 2000);
confirmCurrentFrame(2);
// second attempt should progress to input time
setTime(2200, 2200);
confirmCurrentFrame(2);
// entering important section
setTime(3000, 3000);
confirmCurrentFrame(3);
// cannot progress within
setTime(3500, null);
confirmCurrentFrame(3);
setTime(4000, 4000);
confirmCurrentFrame(4);
// still cannot progress
setTime(4500, null);
confirmCurrentFrame(4);
setTime(5200, 5000);
confirmCurrentFrame(5);
// important section AllowedImportantTimeSpan allowance
setTime(5200, 5200);
confirmCurrentFrame(5);
setTime(7200, 7000);
confirmCurrentFrame(6);
setTime(7200, null);
confirmCurrentFrame(6);
// exited important section
setTime(8200, 8000);
confirmCurrentFrame(7);
confirmNextFrame(null);
setTime(8200, 8200);
confirmCurrentFrame(7);
confirmNextFrame(null);
}
[Test]
public void TestIntroTime()
{
setTime(-1000, -1000);
confirmCurrentFrame(null);
confirmNextFrame(0);
setTime(-500, -500);
confirmCurrentFrame(null);
confirmNextFrame(0);
setTime(0, 0);
confirmCurrentFrame(0);
confirmNextFrame(1);
}
[Test]
public void TestBasicRewind()
{
setTime(2800, 0);
setTime(2800, 1000);
setTime(2800, 2000);
setTime(2800, 2800);
confirmCurrentFrame(2);
confirmNextFrame(3);
// pivot without crossing a frame boundary
setTime(2700, 2700);
confirmCurrentFrame(2);
confirmNextFrame(1);
// cross current frame boundary; should not yet update frame
setTime(1980, 1980);
confirmCurrentFrame(2);
confirmNextFrame(1);
setTime(1200, 1200);
confirmCurrentFrame(2);
confirmNextFrame(1);
//ensure each frame plays out until start
setTime(-500, 1000);
confirmCurrentFrame(1);
confirmNextFrame(0);
setTime(-500, 0);
confirmCurrentFrame(0);
confirmNextFrame(null);
setTime(-500, -500);
confirmCurrentFrame(0);
confirmNextFrame(null);
}
[Test]
public void TestRewindInsideImportantSection()
{
// fast forward to important section
while (handler.SetFrameFromTime(3000) != null)
{
}
setTime(4000, 4000);
confirmCurrentFrame(4);
confirmNextFrame(5);
setTime(3500, null);
confirmCurrentFrame(4);
confirmNextFrame(3);
setTime(3000, 3000);
confirmCurrentFrame(3);
confirmNextFrame(2);
setTime(3500, null);
confirmCurrentFrame(3);
confirmNextFrame(4);
setTime(4000, 4000);
confirmCurrentFrame(4);
confirmNextFrame(5);
setTime(4500, null);
confirmCurrentFrame(4);
confirmNextFrame(5);
setTime(4000, null);
confirmCurrentFrame(4);
confirmNextFrame(5);
setTime(3500, null);
confirmCurrentFrame(4);
confirmNextFrame(3);
setTime(3000, 3000);
confirmCurrentFrame(3);
confirmNextFrame(2);
}
[Test]
public void TestRewindOutOfImportantSection()
{
// fast forward to important section
while (handler.SetFrameFromTime(3500) != null)
{
}
confirmCurrentFrame(3);
confirmNextFrame(4);
setTime(3200, null);
// next frame doesn't change even though direction reversed, because of important section.
confirmCurrentFrame(3);
confirmNextFrame(4);
setTime(3000, null);
confirmCurrentFrame(3);
confirmNextFrame(4);
setTime(2800, 2800);
confirmCurrentFrame(3);
confirmNextFrame(2);
}
private void setTime(double set, double? expect)
{
Assert.AreEqual(expect, handler.SetFrameFromTime(set));
}
private void confirmCurrentFrame(int? frame)
{
if (frame.HasValue)
{
Assert.IsNotNull(handler.CurrentFrame);
Assert.AreEqual(replay.Frames[frame.Value].Time, handler.CurrentFrame.Time);
}
else
{
Assert.IsNull(handler.CurrentFrame);
}
}
private void confirmNextFrame(int? frame)
{
if (frame.HasValue)
{
Assert.IsNotNull(handler.NextFrame);
Assert.AreEqual(replay.Frames[frame.Value].Time, handler.NextFrame.Time);
}
else
{
Assert.IsNull(handler.NextFrame);
}
}
private class TestReplayFrame : ReplayFrame
{
public readonly bool IsImportant;
public TestReplayFrame(double time, bool isImportant = false)
: base(time)
{
IsImportant = isImportant;
}
}
private class TestInputHandler : FramedReplayInputHandler<TestReplayFrame>
{
public TestInputHandler(Replay replay)
: base(replay)
{
}
protected override double AllowedImportantTimeSpan => 1000;
protected override bool IsImportant(TestReplayFrame frame) => frame.IsImportant;
}
}
}

View File

@ -92,7 +92,7 @@ namespace osu.Game.Tests.Visual.Background
public void PlayerLoaderSettingsHoverTest() public void PlayerLoaderSettingsHoverTest()
{ {
setupUserSettings(); setupUserSettings();
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer()))); AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer { BlockLoad = true })));
AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false); AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false);
AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent()); AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent());
AddStep("Trigger background preview", () => AddStep("Trigger background preview", () =>
@ -255,14 +255,8 @@ namespace osu.Game.Tests.Visual.Background
{ {
setupUserSettings(); setupUserSettings();
AddStep("Start player loader", () => AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer(allowPause))));
{
songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer
{
AllowPause = allowPause,
Ready = true,
}));
});
AddUntilStep("Wait for Player Loader to load", () => playerLoader.IsLoaded); AddUntilStep("Wait for Player Loader to load", () => playerLoader.IsLoaded);
AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos)); AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
AddUntilStep("Wait for player to load", () => player.IsLoaded); AddUntilStep("Wait for player to load", () => player.IsLoaded);
@ -351,21 +345,27 @@ namespace osu.Game.Tests.Visual.Background
public UserDimContainer CurrentStoryboardContainer => StoryboardContainer; public UserDimContainer CurrentStoryboardContainer => StoryboardContainer;
// Whether or not the player should be allowed to load. // Whether or not the player should be allowed to load.
public bool Ready; public bool BlockLoad;
public Bindable<bool> StoryboardEnabled; public Bindable<bool> StoryboardEnabled;
public readonly Bindable<bool> ReplacesBackground = new Bindable<bool>(); public readonly Bindable<bool> ReplacesBackground = new Bindable<bool>();
public readonly Bindable<bool> IsPaused = new Bindable<bool>(); public readonly Bindable<bool> IsPaused = new Bindable<bool>();
public TestPlayer(bool allowPause = true)
: base(allowPause)
{
}
public bool IsStoryboardVisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha == 1; public bool IsStoryboardVisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha == 1;
public bool IsStoryboardInvisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha <= 1; public bool IsStoryboardInvisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha <= 1;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config, CancellationToken token)
{ {
while (!Ready) while (BlockLoad && !token.IsCancellationRequested)
Thread.Sleep(1); Thread.Sleep(1);
StoryboardEnabled = config.GetBindable<bool>(OsuSetting.ShowStoryboard); StoryboardEnabled = config.GetBindable<bool>(OsuSetting.ShowStoryboard);
ReplacesBackground.BindTo(Background.StoryboardReplacesBackground); ReplacesBackground.BindTo(Background.StoryboardReplacesBackground);
DrawableRuleset.IsPaused.BindTo(IsPaused); DrawableRuleset.IsPaused.BindTo(IsPaused);

View File

@ -15,12 +15,7 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override Player CreatePlayer(Ruleset ruleset) protected override Player CreatePlayer(Ruleset ruleset)
{ {
Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
return new ScoreAccessiblePlayer return new ScoreAccessiblePlayer();
{
AllowPause = false,
AllowLeadIn = false,
AllowResults = false,
};
} }
protected override void AddCheckSteps() protected override void AddCheckSteps()
@ -33,6 +28,11 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
public new HUDOverlay HUDOverlay => base.HUDOverlay; public new HUDOverlay HUDOverlay => base.HUDOverlay;
public ScoreAccessiblePlayer()
: base(false, false)
{
}
} }
} }
} }

View File

@ -20,13 +20,13 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
typeof(KeyCounterKeyboard), typeof(KeyCounterKeyboard),
typeof(KeyCounterMouse), typeof(KeyCounterMouse),
typeof(KeyCounterCollection) typeof(KeyCounterDisplay)
}; };
public TestCaseKeyCounter() public TestCaseKeyCounter()
{ {
KeyCounterKeyboard rewindTestKeyCounterKeyboard; KeyCounterKeyboard rewindTestKeyCounterKeyboard;
KeyCounterCollection kc = new KeyCounterCollection KeyCounterDisplay kc = new KeyCounterDisplay
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,

View File

@ -26,12 +26,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
Beatmap.Value = new DummyWorkingBeatmap(game); Beatmap.Value = new DummyWorkingBeatmap(game);
AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player(false, false))));
{
AllowPause = false,
AllowLeadIn = false,
AllowResults = false,
})));
AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddUntilStep("wait for current", () => loader.IsCurrentScreen());
@ -47,12 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
SlowLoadPlayer slow = null; SlowLoadPlayer slow = null;
stack.Push(loader = new PlayerLoader(() => slow = new SlowLoadPlayer stack.Push(loader = new PlayerLoader(() => slow = new SlowLoadPlayer(false, false)));
{
AllowPause = false,
AllowLeadIn = false,
AllowResults = false,
}));
Scheduler.AddDelayed(() => slow.Ready = true, 5000); Scheduler.AddDelayed(() => slow.Ready = true, 5000);
}); });
@ -64,6 +54,11 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
public bool Ready; public bool Ready;
public SlowLoadPlayer(bool allowPause = true, bool showResults = true)
: base(allowPause, showResults)
{
}
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {

View File

@ -170,12 +170,12 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
InternalChild = new Box AddInternal(new Box
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both RelativeSizeAxes = Axes.Both
}; });
switch (direction) switch (direction)
{ {
@ -205,7 +205,7 @@ namespace osu.Game.Tests.Visual.Gameplay
Origin = Anchor.Centre; Origin = Anchor.Centre;
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
InternalChild = new Box { Size = new Vector2(75) }; AddInternal(new Box { Size = new Vector2(75) });
} }
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)

View File

@ -1,7 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Threading;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Screens; using osu.Framework.Screens;
@ -12,59 +14,85 @@ using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Menus namespace osu.Game.Tests.Visual.Menus
{ {
[TestFixture] [TestFixture]
public class TestCaseLoaderAnimation : OsuTestCase public class TestCaseLoaderAnimation : ScreenTestCase
{ {
private TestLoader loader; private TestLoader loader;
protected override void LoadComplete() [Cached]
private OsuLogo logo;
public TestCaseLoaderAnimation()
{ {
base.LoadComplete(); Child = logo = new OsuLogo { Depth = float.MinValue };
}
// required to preload the logo in a headless run (so it doesn't delay the loading itself).
Add(new OsuLogo());
[Test]
public void TestInstantLoad()
{
bool logoVisible = false; bool logoVisible = false;
AddStep("almost instant display", () => Child = loader = new TestLoader(250));
AddUntilStep("loaded", () =>
{
logoVisible = loader.Logo?.Alpha > 0;
return loader.Logo != null && loader.ScreenLoaded;
});
AddAssert("logo not visible", () => !logoVisible);
AddStep("short load", () => Child = loader = new TestLoader(800)); AddStep("begin loading", () =>
AddUntilStep("loaded", () => {
loader = new TestLoader();
loader.AllowLoad.Set();
LoadScreen(loader);
});
AddAssert("loaded", () =>
{ {
logoVisible = loader.Logo?.Alpha > 0; logoVisible = loader.Logo?.Alpha > 0;
return loader.Logo != null && loader.ScreenLoaded; return loader.Logo != null && loader.ScreenLoaded;
}); });
AddAssert("logo visible", () => logoVisible);
AddAssert("logo was not visible", () => !logoVisible);
}
[Test]
public void TestShortLoad()
{
bool logoVisible = false;
AddStep("begin loading", () => LoadScreen(loader = new TestLoader()));
AddWaitStep("wait", 2);
AddStep("finish loading", () =>
{
logoVisible = loader.Logo?.Alpha > 0;
loader.AllowLoad.Set();
});
AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded);
AddAssert("logo was visible", () => logoVisible);
AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0);
}
AddStep("longer load", () => Child = loader = new TestLoader(1400)); [Test]
AddUntilStep("loaded", () => public void TestLongLoad()
{
bool logoVisible = false;
AddStep("begin loading", () => LoadScreen(loader = new TestLoader()));
AddWaitStep("wait", 10);
AddStep("finish loading", () =>
{ {
logoVisible = loader.Logo?.Alpha > 0; logoVisible = loader.Logo?.Alpha > 0;
return loader.Logo != null && loader.ScreenLoaded; loader.AllowLoad.Set();
}); });
AddAssert("logo visible", () => logoVisible);
AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded);
AddAssert("logo was visible", () => logoVisible);
AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0);
} }
private class TestLoader : Loader private class TestLoader : Loader
{ {
private readonly double delay; public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim();
public OsuLogo Logo; public OsuLogo Logo;
private TestScreen screen; private TestScreen screen;
public bool ScreenLoaded => screen.IsCurrentScreen(); public bool ScreenLoaded => screen.IsCurrentScreen();
public TestLoader(double delay)
{
this.delay = delay;
}
protected override void LogoArriving(OsuLogo logo, bool resuming) protected override void LogoArriving(OsuLogo logo, bool resuming)
{ {
Logo = logo; Logo = logo;
@ -72,25 +100,18 @@ namespace osu.Game.Tests.Visual.Menus
} }
protected override OsuScreen CreateLoadableScreen() => screen = new TestScreen(); protected override OsuScreen CreateLoadableScreen() => screen = new TestScreen();
protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(delay); protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(AllowLoad);
private class TestShaderPrecompiler : ShaderPrecompiler private class TestShaderPrecompiler : ShaderPrecompiler
{ {
private readonly double delay; private readonly ManualResetEventSlim allowLoad;
private double startTime;
public TestShaderPrecompiler(double delay) public TestShaderPrecompiler(ManualResetEventSlim allowLoad)
{ {
this.delay = delay; this.allowLoad = allowLoad;
} }
protected override void LoadComplete() protected override bool AllLoaded => allowLoad.IsSet;
{
base.LoadComplete();
startTime = Time.Current;
}
protected override bool AllLoaded => Time.Current > startTime + delay;
} }
private class TestScreen : OsuScreen private class TestScreen : OsuScreen

View File

@ -27,7 +27,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Cached(Type = typeof(IRoomManager))] [Cached(Type = typeof(IRoomManager))]
private TestRoomManager roomManager = new TestRoomManager(); private TestRoomManager roomManager = new TestRoomManager();
public TestCaseLoungeRoomsContainer() [BackgroundDependencyLoader]
private void load()
{ {
RoomsContainer container; RoomsContainer container;

View File

@ -2,7 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.ComponentModel; using System.ComponentModel;
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
using osu.Game.Screens.Select.Options; using osu.Game.Screens.Select.Options;
using osuTK.Graphics; using osuTK.Graphics;
using osuTK.Input; using osuTK.Input;
@ -16,10 +16,10 @@ namespace osu.Game.Tests.Visual.SongSelect
{ {
var overlay = new BeatmapOptionsOverlay(); var overlay = new BeatmapOptionsOverlay();
overlay.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, Color4.Purple, null, Key.Number1); overlay.AddButton(@"Remove", @"from unplayed", FontAwesome.TimesCircleOutline, Color4.Purple, null, Key.Number1);
overlay.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, Color4.Purple, null, Key.Number2); overlay.AddButton(@"Clear", @"local scores", FontAwesome.Eraser, Color4.Purple, null, Key.Number2);
overlay.AddButton(@"Edit", @"Beatmap", FontAwesome.fa_pencil, Color4.Yellow, null, Key.Number3); overlay.AddButton(@"Edit", @"Beatmap", FontAwesome.Pencil, Color4.Yellow, null, Key.Number3);
overlay.AddButton(@"Delete", @"Beatmap", FontAwesome.fa_trash, Color4.Pink, null, Key.Number4, float.MaxValue); overlay.AddButton(@"Delete", @"Beatmap", FontAwesome.Trash, Color4.Pink, null, Key.Number4, float.MaxValue);
Add(overlay); Add(overlay);

View File

@ -9,7 +9,6 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Overlays.BeatmapSet.Scores;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
@ -44,9 +43,9 @@ namespace osu.Game.Tests.Visual.SongSelect
} }
}; };
IEnumerable<APIScoreInfo> scores = new[] IEnumerable<ScoreInfo> scores = new[]
{ {
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -69,7 +68,7 @@ namespace osu.Game.Tests.Visual.SongSelect
TotalScore = 1234567890, TotalScore = 1234567890,
Accuracy = 1, Accuracy = 1,
}, },
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -91,7 +90,7 @@ namespace osu.Game.Tests.Visual.SongSelect
TotalScore = 1234789, TotalScore = 1234789,
Accuracy = 0.9997, Accuracy = 0.9997,
}, },
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -112,7 +111,7 @@ namespace osu.Game.Tests.Visual.SongSelect
TotalScore = 12345678, TotalScore = 12345678,
Accuracy = 0.9854, Accuracy = 0.9854,
}, },
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -132,7 +131,7 @@ namespace osu.Game.Tests.Visual.SongSelect
TotalScore = 1234567, TotalScore = 1234567,
Accuracy = 0.8765, Accuracy = 0.8765,
}, },
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -157,9 +156,9 @@ namespace osu.Game.Tests.Visual.SongSelect
s.Statistics.Add(HitResult.Meh, RNG.Next(2000)); s.Statistics.Add(HitResult.Meh, RNG.Next(2000));
} }
IEnumerable<APIScoreInfo> anotherScores = new[] IEnumerable<ScoreInfo> anotherScores = new[]
{ {
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -181,7 +180,7 @@ namespace osu.Game.Tests.Visual.SongSelect
TotalScore = 1234789, TotalScore = 1234789,
Accuracy = 0.9997, Accuracy = 0.9997,
}, },
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -204,7 +203,7 @@ namespace osu.Game.Tests.Visual.SongSelect
TotalScore = 1234567890, TotalScore = 1234567890,
Accuracy = 1, Accuracy = 1,
}, },
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -220,7 +219,7 @@ namespace osu.Game.Tests.Visual.SongSelect
TotalScore = 123456, TotalScore = 123456,
Accuracy = 0.6543, Accuracy = 0.6543,
}, },
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -241,7 +240,7 @@ namespace osu.Game.Tests.Visual.SongSelect
TotalScore = 12345678, TotalScore = 12345678,
Accuracy = 0.9854, Accuracy = 0.9854,
}, },
new APIScoreInfo new ScoreInfo
{ {
User = new User User = new User
{ {
@ -269,7 +268,7 @@ namespace osu.Game.Tests.Visual.SongSelect
s.Statistics.Add(HitResult.Meh, RNG.Next(2000)); s.Statistics.Add(HitResult.Meh, RNG.Next(2000));
} }
var topScoreInfo = new APIScoreInfo var topScoreInfo = new ScoreInfo
{ {
User = new User User = new User
{ {

View File

@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Allocation;
using osu.Game.Screens.Tournament; using osu.Game.Screens.Tournament;
using osu.Game.Screens.Tournament.Teams; using osu.Game.Screens.Tournament.Teams;
@ -11,7 +12,8 @@ namespace osu.Game.Tests.Visual.Tournament
[Description("for tournament use")] [Description("for tournament use")]
public class TestCaseDrawings : ScreenTestCase public class TestCaseDrawings : ScreenTestCase
{ {
public TestCaseDrawings() [BackgroundDependencyLoader]
private void load()
{ {
LoadScreen(new Drawings LoadScreen(new Drawings
{ {

View File

@ -2,7 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Dialog; using osu.Game.Overlays.Dialog;
@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("dialog #1", () => overlay.Push(new PopupDialog AddStep("dialog #1", () => overlay.Push(new PopupDialog
{ {
Icon = FontAwesome.fa_trash_o, Icon = FontAwesome.TrashOutline,
HeaderText = @"Confirm deletion of", HeaderText = @"Confirm deletion of",
BodyText = @"Ayase Rie - Yuima-ru*World TVver.", BodyText = @"Ayase Rie - Yuima-ru*World TVver.",
Buttons = new PopupDialogButton[] Buttons = new PopupDialogButton[]
@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("dialog #2", () => overlay.Push(new PopupDialog AddStep("dialog #2", () => overlay.Push(new PopupDialog
{ {
Icon = FontAwesome.fa_gear, Icon = FontAwesome.Gear,
HeaderText = @"What do you want to do with", HeaderText = @"What do you want to do with",
BodyText = "Camellia as \"Bang Riot\" - Blastix Riotz", BodyText = "Camellia as \"Bang Riot\" - Blastix Riotz",
Buttons = new PopupDialogButton[] Buttons = new PopupDialogButton[]

View File

@ -111,7 +111,7 @@ namespace osu.Game.Tests.Visual.UserInterface
button.Anchor = Anchor.Centre; button.Anchor = Anchor.Centre;
button.Origin = Anchor.Centre; button.Origin = Anchor.Centre;
button.Icon = FontAwesome.fa_osu_osu_o; button.Icon = OsuIcon.RulesetOsu;
} }
} }
} }

View File

@ -0,0 +1,73 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Reflection;
using NUnit.Framework;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Testing;
using osu.Game.Graphics;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.UserInterface
{
[TestFixture]
public class TestCaseOsuIcon : TestCase
{
public TestCaseOsuIcon()
{
FillFlowContainer<Icon> flow;
AddRange(new Drawable[]
{
new Box
{
Colour = Color4.Teal,
RelativeSizeAxes = Axes.Both,
},
new ScrollContainer
{
RelativeSizeAxes = Axes.Both,
Child = flow = new FillFlowContainer<Icon>
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Full,
},
}
});
foreach (var p in typeof(OsuIcon).GetProperties(BindingFlags.Public | BindingFlags.Static))
flow.Add(new Icon($"{nameof(OsuIcon)}.{p.Name}", (IconUsage)p.GetValue(null)));
AddStep("toggle shadows", () => flow.Children.ForEach(i => i.SpriteIcon.Shadow = !i.SpriteIcon.Shadow));
AddStep("change icons", () => flow.Children.ForEach(i => i.SpriteIcon.Icon = new IconUsage((char)(i.SpriteIcon.Icon.Icon + 1))));
}
private class Icon : Container, IHasTooltip
{
public string TooltipText { get; }
public SpriteIcon SpriteIcon { get; }
public Icon(string name, IconUsage icon)
{
TooltipText = name;
AutoSizeAxes = Axes.Both;
Child = SpriteIcon = new SpriteIcon
{
Icon = icon,
Size = new Vector2(60),
};
}
}
}
}

View File

@ -3,7 +3,7 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
using osu.Game.Overlays.Dialog; using osu.Game.Overlays.Dialog;
namespace osu.Game.Tests.Visual.UserInterface namespace osu.Game.Tests.Visual.UserInterface
@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.UserInterface
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
State = Framework.Graphics.Containers.Visibility.Visible, State = Framework.Graphics.Containers.Visibility.Visible,
Icon = FontAwesome.fa_assistive_listening_systems, Icon = FontAwesome.AssistiveListeningSystems,
HeaderText = @"This is a test popup", HeaderText = @"This is a test popup",
BodyText = "I can say lots of stuff and even wrap my words!", BodyText = "I can say lots of stuff and even wrap my words!",
Buttons = new PopupDialogButton[] Buttons = new PopupDialogButton[]

View File

@ -1,55 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Game.Graphics;
using osuTK;
namespace osu.Game.Tests.Visual.UserInterface
{
[TestFixture]
public class TestCaseTextAwesome : OsuTestCase
{
public TestCaseTextAwesome()
{
FillFlowContainer flow;
Add(new ScrollContainer
{
RelativeSizeAxes = Axes.Both,
Child = flow = new FillFlowContainer
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Full,
},
});
foreach (FontAwesome fa in Enum.GetValues(typeof(FontAwesome)))
flow.Add(new Icon(fa));
}
private class Icon : Container, IHasTooltip
{
public string TooltipText { get; }
public Icon(FontAwesome fa)
{
TooltipText = fa.ToString();
AutoSizeAxes = Axes.Both;
Child = new SpriteIcon
{
Icon = fa,
Size = new Vector2(60),
};
}
}
}
}

View File

@ -1,13 +1,13 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
public class BeatmapStatistic public class BeatmapStatistic
{ {
public FontAwesome Icon; public IconUsage Icon;
public string Content; public string Content;
public string Name; public string Name;
} }

View File

@ -7,7 +7,7 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics; using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osuTK; using osuTK;
@ -60,7 +60,7 @@ namespace osu.Game.Beatmaps.Drawables
Origin = Anchor.Centre, Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
// the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment)
Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.fa_question_circle_o } Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.QuestionCircleOutline }
} }
}; };
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -38,6 +39,10 @@ namespace osu.Game.Beatmaps.Formats
{ {
this.storyboard = storyboard; this.storyboard = storyboard;
base.ParseStreamInto(stream, storyboard); base.ParseStreamInto(stream, storyboard);
// OrderBy is used to guarantee that the parsing order of elements with equal start times is maintained (stably-sorted)
foreach (StoryboardLayer layer in storyboard.Layers)
layer.Elements = layer.Elements.OrderBy(h => h.StartTime).ToList();
} }
protected override void ParseLine(Storyboard storyboard, Section section, string line) protected override void ParseLine(Storyboard storyboard, Section section, string line)

View File

@ -55,7 +55,7 @@ namespace osu.Game.Configuration
// Input // Input
Set(OsuSetting.MenuCursorSize, 1.0, 0.5f, 2, 0.01); Set(OsuSetting.MenuCursorSize, 1.0, 0.5f, 2, 0.01);
Set(OsuSetting.GameplayCursorSize, 1.0, 0.5f, 2, 0.01); Set(OsuSetting.GameplayCursorSize, 1.0, 0.1f, 2, 0.01);
Set(OsuSetting.AutoCursorSize, false); Set(OsuSetting.AutoCursorSize, false);
Set(OsuSetting.MouseDisableButtons, false); Set(OsuSetting.MouseDisableButtons, false);

View File

@ -35,7 +35,7 @@ namespace osu.Game.Graphics.Containers
showNotImplementedError = () => notifications?.Post(new SimpleNotification showNotImplementedError = () => notifications?.Post(new SimpleNotification
{ {
Text = @"This link type is not yet supported!", Text = @"This link type is not yet supported!",
Icon = FontAwesome.fa_life_saver, Icon = FontAwesome.LifeSaver,
}); });
} }

View File

@ -21,6 +21,6 @@ namespace osu.Game.Graphics.Containers
public void AddArbitraryDrawable(Drawable drawable) => AddInternal(drawable); public void AddArbitraryDrawable(Drawable drawable) => AddInternal(drawable);
public IEnumerable<Drawable> AddIcon(FontAwesome icon, Action<SpriteText> creationParameters = null) => AddText(((char)icon).ToString(), creationParameters); public IEnumerable<Drawable> AddIcon(IconUsage icon, Action<SpriteText> creationParameters = null) => AddText(icon.Icon.ToString(), creationParameters);
} }
} }

View File

@ -8,6 +8,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Backgrounds;
using osu.Game.Screens.Play;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;

View File

@ -5,7 +5,7 @@ using osu.Framework.Graphics.Sprites;
namespace osu.Game.Graphics namespace osu.Game.Graphics
{ {
public struct OsuFont public static class OsuFont
{ {
/// <summary> /// <summary>
/// The default font size. /// The default font size.

View File

@ -0,0 +1,94 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics.Sprites;
namespace osu.Game.Graphics
{
public static class OsuIcon
{
public static IconUsage Get(int icon) => new IconUsage((char)icon, "OsuFont");
// ruleset icons in circles
public static IconUsage RulesetOsu => Get(0xe000);
public static IconUsage RulesetMania => Get(0xe001);
public static IconUsage RulesetCatch => Get(0xe002);
public static IconUsage RulesetTaiko => Get(0xe003);
// ruleset icons without circles
public static IconUsage FilledCircle => Get(0xe004);
public static IconUsage CrossCircle => Get(0xe005);
public static IconUsage Logo => Get(0xe006);
public static IconUsage ChevronDownCircle => Get(0xe007);
public static IconUsage EditCircle => Get(0xe033);
public static IconUsage LeftCircle => Get(0xe034);
public static IconUsage RightCircle => Get(0xe035);
public static IconUsage Charts => Get(0xe036);
public static IconUsage Solo => Get(0xe037);
public static IconUsage Multi => Get(0xe038);
public static IconUsage Gear => Get(0xe039);
// misc icons
public static IconUsage Bat => Get(0xe008);
public static IconUsage Bubble => Get(0xe009);
public static IconUsage BubblePop => Get(0xe02e);
public static IconUsage Dice => Get(0xe011);
public static IconUsage Heart => Get(0xe02f);
public static IconUsage HeartBreak => Get(0xe030);
public static IconUsage Hot => Get(0xe031);
public static IconUsage ListSearch => Get(0xe032);
//osu! playstyles
public static IconUsage PlaystyleTablet => Get(0xe02a);
public static IconUsage PlaystyleMouse => Get(0xe029);
public static IconUsage PlaystyleKeyboard => Get(0xe02b);
public static IconUsage PlaystyleTouch => Get(0xe02c);
// osu! difficulties
public static IconUsage EasyOsu => Get(0xe015);
public static IconUsage NormalOsu => Get(0xe016);
public static IconUsage HardOsu => Get(0xe017);
public static IconUsage InsaneOsu => Get(0xe018);
public static IconUsage ExpertOsu => Get(0xe019);
// taiko difficulties
public static IconUsage EasyTaiko => Get(0xe01a);
public static IconUsage NormalTaiko => Get(0xe01b);
public static IconUsage HardTaiko => Get(0xe01c);
public static IconUsage InsaneTaiko => Get(0xe01d);
public static IconUsage ExpertTaiko => Get(0xe01e);
// fruits difficulties
public static IconUsage EasyFruits => Get(0xe01f);
public static IconUsage NormalFruits => Get(0xe020);
public static IconUsage HardFruits => Get(0xe021);
public static IconUsage InsaneFruits => Get(0xe022);
public static IconUsage ExpertFruits => Get(0xe023);
// mania difficulties
public static IconUsage EasyMania => Get(0xe024);
public static IconUsage NormalMania => Get(0xe025);
public static IconUsage HardMania => Get(0xe026);
public static IconUsage InsaneMania => Get(0xe027);
public static IconUsage ExpertMania => Get(0xe028);
// mod icons
public static IconUsage ModPerfect => Get(0xe049);
public static IconUsage ModAutopilot => Get(0xe03a);
public static IconUsage ModAuto => Get(0xe03b);
public static IconUsage ModCinema => Get(0xe03c);
public static IconUsage ModDoubletime => Get(0xe03d);
public static IconUsage ModEasy => Get(0xe03e);
public static IconUsage ModFlashlight => Get(0xe03f);
public static IconUsage ModHalftime => Get(0xe040);
public static IconUsage ModHardrock => Get(0xe041);
public static IconUsage ModHidden => Get(0xe042);
public static IconUsage ModNightcore => Get(0xe043);
public static IconUsage ModNofail => Get(0xe044);
public static IconUsage ModRelax => Get(0xe045);
public static IconUsage ModSpunout => Get(0xe046);
public static IconUsage ModSuddendeath => Get(0xe047);
public static IconUsage ModTarget => Get(0xe048);
public static IconUsage ModBg => Get(0xe04a);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@ namespace osu.Game.Graphics.UserInterface
public BackButton() public BackButton()
{ {
Text = @"back"; Text = @"back";
Icon = FontAwesome.fa_osu_left_o; Icon = OsuIcon.LeftCircle;
Anchor = Anchor.BottomLeft; Anchor = Anchor.BottomLeft;
Origin = Anchor.BottomLeft; Origin = Anchor.BottomLeft;
} }

View File

@ -8,6 +8,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
@ -92,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Size = new Vector2(item_chevron_size), Size = new Vector2(item_chevron_size),
Icon = FontAwesome.fa_chevron_right, Icon = FontAwesome.ChevronRight,
Margin = new MarginPadding { Left = padding }, Margin = new MarginPadding { Left = padding },
Alpha = 0f, Alpha = 0f,
}); });

View File

@ -5,6 +5,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Platform; using osu.Framework.Platform;
using osuTK; using osuTK;
@ -25,7 +26,7 @@ namespace osu.Game.Graphics.UserInterface
Size = new Vector2(12); Size = new Vector2(12);
InternalChild = new SpriteIcon InternalChild = new SpriteIcon
{ {
Icon = FontAwesome.fa_external_link, Icon = FontAwesome.ExternalLink,
RelativeSizeAxes = Axes.Both RelativeSizeAxes = Axes.Both
}; };
} }

View File

@ -4,6 +4,7 @@
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
@ -41,7 +42,7 @@ namespace osu.Game.Graphics.UserInterface
/// <summary> /// <summary>
/// The icon. /// The icon.
/// </summary> /// </summary>
public FontAwesome Icon public IconUsage Icon
{ {
get => icon.Icon; get => icon.Icon;
set => icon.Icon = value; set => icon.Icon = value;

View File

@ -3,6 +3,7 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -36,14 +37,14 @@ namespace osu.Game.Graphics.UserInterface
Position = new Vector2(1, 1), Position = new Vector2(1, 1),
Colour = Color4.Black, Colour = Color4.Black,
Alpha = 0.4f, Alpha = 0.4f,
Icon = FontAwesome.fa_circle_o_notch Icon = FontAwesome.CircleONotch
}, },
spinner = new SpriteIcon spinner = new SpriteIcon
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Icon = FontAwesome.fa_circle_o_notch Icon = FontAwesome.CircleONotch
} }
}; };
} }

View File

@ -179,7 +179,7 @@ namespace osu.Game.Graphics.UserInterface
Chevron = new SpriteIcon Chevron = new SpriteIcon
{ {
AlwaysPresent = true, AlwaysPresent = true,
Icon = FontAwesome.fa_chevron_right, Icon = FontAwesome.ChevronRight,
Colour = Color4.Black, Colour = Color4.Black,
Alpha = 0.5f, Alpha = 0.5f,
Size = new Vector2(8), Size = new Vector2(8),
@ -244,7 +244,7 @@ namespace osu.Game.Graphics.UserInterface
}, },
Icon = new SpriteIcon Icon = new SpriteIcon
{ {
Icon = FontAwesome.fa_chevron_down, Icon = FontAwesome.ChevronDown,
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 4 }, Margin = new MarginPadding { Right = 4 },

View File

@ -9,6 +9,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Platform; using osu.Framework.Platform;
@ -107,7 +108,7 @@ namespace osu.Game.Graphics.UserInterface
public CapsWarning() public CapsWarning()
{ {
Icon = FontAwesome.fa_warning; Icon = FontAwesome.Warning;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -254,7 +254,7 @@ namespace osu.Game.Graphics.UserInterface
{ {
new SpriteIcon new SpriteIcon
{ {
Icon = FontAwesome.fa_ellipsis_h, Icon = FontAwesome.EllipsisH,
Size = new Vector2(14), Size = new Vector2(14),
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,

View File

@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface
icon = new SpriteIcon icon = new SpriteIcon
{ {
Size = new Vector2(14), Size = new Vector2(14),
Icon = FontAwesome.fa_circle_o, Icon = FontAwesome.CircleOutline,
Shadow = true, Shadow = true,
}, },
}, },
@ -120,12 +120,12 @@ namespace osu.Game.Graphics.UserInterface
if (selected.NewValue) if (selected.NewValue)
{ {
fadeIn(); fadeIn();
icon.Icon = FontAwesome.fa_check_circle_o; icon.Icon = FontAwesome.CheckCircleOutline;
} }
else else
{ {
fadeOut(); fadeOut();
icon.Icon = FontAwesome.fa_circle_o; icon.Icon = FontAwesome.CircleOutline;
} }
}; };
} }

View File

@ -0,0 +1,80 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics.Sprites;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Graphics.UserInterface
{
public abstract class ScreenTitle : CompositeDrawable, IHasAccentColour
{
private readonly SpriteIcon iconSprite;
private readonly OsuSpriteText titleText, pageText;
protected IconUsage Icon
{
get => iconSprite.Icon;
set => iconSprite.Icon = value;
}
protected string Title
{
get => titleText.Text;
set => titleText.Text = value;
}
protected string Section
{
get => pageText.Text;
set => pageText.Text = value;
}
public Color4 AccentColour
{
get => pageText.Colour;
set => pageText.Colour = value;
}
protected ScreenTitle()
{
AutoSizeAxes = Axes.Both;
InternalChildren = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(10, 0),
Children = new Drawable[]
{
iconSprite = new SpriteIcon
{
Size = new Vector2(25),
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(6, 0),
Children = new[]
{
titleText = new OsuSpriteText
{
Font = OsuFont.GetFont(size: 25),
},
pageText = new OsuSpriteText
{
Font = OsuFont.GetFont(size: 25),
}
}
}
}
},
};
}
}
}

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