Merge remote-tracking branch 'refs/remotes/ppy/master' into history-graph

This commit is contained in:
Andrei Zavatski 2020-03-09 19:16:50 +03:00
commit e8c726cf95
61 changed files with 1248 additions and 731 deletions

View File

@ -52,6 +52,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.302.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2020.305.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,35 @@
// 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 NUnit.Framework;
using osu.Framework.Utils;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public class TestSceneOsuModDoubleTime : ModTestScene
{
public TestSceneOsuModDoubleTime()
: base(new OsuRuleset())
{
}
[TestCase(0.5)]
[TestCase(1.01)]
[TestCase(1.5)]
[TestCase(2)]
[TestCase(5)]
public void TestSpeedChangeCustomisation(double rate)
{
var mod = new OsuModDoubleTime { SpeedChange = { Value = rate } };
CreateModTest(new ModTestData
{
Mod = mod,
PassCondition = () => Player.ScoreProcessor.JudgedHits >= 2 &&
Precision.AlmostEquals(Player.GameplayClockContainer.GameplayClock.Rate, mod.SpeedChange.Value)
});
}
}
}

View File

@ -0,0 +1,108 @@
// 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.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Rulesets.Osu.Tests
{
public class TestSceneHitCircleArea : ManualInputManagerTestScene
{
private HitCircle hitCircle;
private DrawableHitCircle drawableHitCircle;
private DrawableHitCircle.HitReceptor hitAreaReceptor => drawableHitCircle.HitArea;
[SetUp]
public new void SetUp()
{
base.SetUp();
Schedule(() =>
{
hitCircle = new HitCircle
{
Position = new Vector2(100, 100),
StartTime = Time.Current + 500
};
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
Child = new SkinProvidingContainer(new DefaultSkin())
{
RelativeSizeAxes = Axes.Both,
Child = drawableHitCircle = new DrawableHitCircle(hitCircle)
{
Size = new Vector2(100)
}
};
});
}
[Test]
public void TestCircleHitCentre()
{
AddStep("move mouse to centre", () => InputManager.MoveMouseTo(hitAreaReceptor.ScreenSpaceDrawQuad.Centre));
scheduleHit();
AddAssert("hit registered", () => hitAreaReceptor.HitAction == OsuAction.LeftButton);
}
[Test]
public void TestCircleHitLeftEdge()
{
AddStep("move mouse to left edge", () =>
{
var drawQuad = hitAreaReceptor.ScreenSpaceDrawQuad;
var mousePosition = new Vector2(drawQuad.TopLeft.X, drawQuad.Centre.Y);
InputManager.MoveMouseTo(mousePosition);
});
scheduleHit();
AddAssert("hit registered", () => hitAreaReceptor.HitAction == OsuAction.LeftButton);
}
[TestCase(0.95f, OsuAction.LeftButton)]
[TestCase(1.05f, null)]
public void TestHitsCloseToEdge(float relativeDistanceFromCentre, OsuAction? expectedAction)
{
AddStep("move mouse to top left circle edge", () =>
{
var drawQuad = hitAreaReceptor.ScreenSpaceDrawQuad;
// sqrt(2) / 2 = sin(45deg) = cos(45deg)
// draw width halved to get radius
float correction = relativeDistanceFromCentre * (float)Math.Sqrt(2) / 2 * (drawQuad.Width / 2);
var mousePosition = new Vector2(drawQuad.Centre.X - correction, drawQuad.Centre.Y - correction);
InputManager.MoveMouseTo(mousePosition);
});
scheduleHit();
AddAssert($"hit {(expectedAction == null ? "not " : string.Empty)}registered", () => hitAreaReceptor.HitAction == expectedAction);
}
[Test]
public void TestCircleMissBoundingBoxCorner()
{
AddStep("move mouse to top left corner of bounding box", () => InputManager.MoveMouseTo(hitAreaReceptor.ScreenSpaceDrawQuad.TopLeft));
scheduleHit();
AddAssert("hit not registered", () => hitAreaReceptor.HitAction == null);
}
private void scheduleHit() => AddStep("schedule action", () =>
{
var delay = hitCircle.StartTime - hitCircle.HitWindows.WindowFor(HitResult.Great) - Time.Current;
Scheduler.AddDelayed(() => hitAreaReceptor.OnPressed(OsuAction.LeftButton), delay);
});
}
}

View File

@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public Drawable ProxiedLayer => ApproachCircle; public Drawable ProxiedLayer => ApproachCircle;
public class HitReceptor : Drawable, IKeyBindingHandler<OsuAction> public class HitReceptor : CompositeDrawable, IKeyBindingHandler<OsuAction>
{ {
// IsHovered is used // IsHovered is used
public override bool HandlePositionalInput => true; public override bool HandlePositionalInput => true;
@ -185,6 +185,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Anchor = Anchor.Centre; Anchor = Anchor.Centre;
Origin = Anchor.Centre; Origin = Anchor.Centre;
CornerRadius = OsuHitObject.OBJECT_RADIUS;
CornerExponent = 2;
} }
public bool OnPressed(OsuAction action) public bool OnPressed(OsuAction action)

View File

@ -3,10 +3,8 @@
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osu.Game.Storyboards;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
@ -15,8 +13,6 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
protected new TestPlayer Player => (TestPlayer)base.Player; protected new TestPlayer Player => (TestPlayer)base.Player;
private ClockBackedTestWorkingBeatmap.TrackVirtualManual track;
protected override Player CreatePlayer(Ruleset ruleset) protected override Player CreatePlayer(Ruleset ruleset)
{ {
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
@ -27,17 +23,12 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0); AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0);
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2)); AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
AddStep("rewind", () => track.Seek(-10000)); AddStep("seek to break time", () => Player.GameplayClockContainer.Seek(Player.BreakOverlay.Breaks.First().StartTime));
AddUntilStep("wait for seek to complete", () =>
Player.HUDOverlay.Progress.ReferenceClock.CurrentTime >= Player.BreakOverlay.Breaks.First().StartTime);
AddAssert("test keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting);
AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000));
AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
} }
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
{
var working = base.CreateWorkingBeatmap(beatmap, storyboard);
track = (ClockBackedTestWorkingBeatmap.TrackVirtualManual)working.Track;
return working;
}
} }
} }

View File

@ -47,21 +47,22 @@ namespace osu.Game.Tests.Visual.Gameplay
Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key; Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key;
AddStep($"Press {testKey} key", () => void addPressKeyStep()
{ {
InputManager.PressKey(testKey); AddStep($"Press {testKey} key", () =>
InputManager.ReleaseKey(testKey); {
}); InputManager.PressKey(testKey);
InputManager.ReleaseKey(testKey);
});
}
addPressKeyStep();
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1);
addPressKeyStep();
AddStep($"Press {testKey} key", () =>
{
InputManager.PressKey(testKey);
InputManager.ReleaseKey(testKey);
});
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2);
AddStep("Disable counting", () => testCounter.IsCounting = false);
addPressKeyStep();
AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses == 2);
Add(kc); Add(kc);
} }

View File

@ -3,9 +3,6 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Utils;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osuTK; using osuTK;
@ -45,32 +42,12 @@ namespace osu.Game.Tests.Visual.Gameplay
}; };
Add(accuracyCounter); Add(accuracyCounter);
StarCounter stars = new StarCounter
{
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
Position = new Vector2(20, -160),
CountStars = 5,
};
Add(stars);
SpriteText starsLabel = new OsuSpriteText
{
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
Position = new Vector2(20, -190),
Text = stars.CountStars.ToString("0.00"),
};
Add(starsLabel);
AddStep(@"Reset all", delegate AddStep(@"Reset all", delegate
{ {
score.Current.Value = 0; score.Current.Value = 0;
comboCounter.Current.Value = 0; comboCounter.Current.Value = 0;
numerator = denominator = 0; numerator = denominator = 0;
accuracyCounter.SetFraction(0, 0); accuracyCounter.SetFraction(0, 0);
stars.CountStars = 0;
starsLabel.Text = stars.CountStars.ToString("0.00");
}); });
AddStep(@"Hit! :D", delegate AddStep(@"Hit! :D", delegate
@ -88,20 +65,6 @@ namespace osu.Game.Tests.Visual.Gameplay
denominator++; denominator++;
accuracyCounter.SetFraction(numerator, denominator); accuracyCounter.SetFraction(numerator, denominator);
}); });
AddStep(@"Alter stars", delegate
{
stars.CountStars = RNG.NextSingle() * (stars.StarCount + 1);
starsLabel.Text = stars.CountStars.ToString("0.00");
});
AddStep(@"Stop counters", delegate
{
score.StopRolling();
comboCounter.StopRolling();
accuracyCounter.StopRolling();
stars.StopAnimation();
});
} }
} }
} }

View File

@ -0,0 +1,57 @@
// 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 NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Utils;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osuTK;
namespace osu.Game.Tests.Visual.Gameplay
{
[TestFixture]
public class TestSceneStarCounter : OsuTestScene
{
public TestSceneStarCounter()
{
StarCounter stars = new StarCounter
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Current = 5,
};
Add(stars);
SpriteText starsLabel = new OsuSpriteText
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Scale = new Vector2(2),
Y = 50,
Text = stars.Current.ToString("0.00"),
};
Add(starsLabel);
AddRepeatStep(@"random value", delegate
{
stars.Current = RNG.NextSingle() * (stars.StarCount + 1);
starsLabel.Text = stars.Current.ToString("0.00");
}, 10);
AddStep(@"Stop animation", delegate
{
stars.StopAnimation();
});
AddStep(@"Reset", delegate
{
stars.Current = 0;
starsLabel.Text = stars.Current.ToString("0.00");
});
}
}
}

View File

@ -0,0 +1,124 @@
// 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 osu.Framework.Graphics;
using osu.Game.Tests.Visual;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
using osu.Game.Tournament.Screens.Drawings.Components;
using osu.Game.Tournament.Screens.Gameplay.Components;
using osu.Game.Tournament.Screens.Ladder.Components;
using osu.Game.Users;
namespace osu.Game.Tournament.Tests.Components
{
public class TestSceneDrawableTournamentTeam : OsuGridTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(DrawableTeamFlag),
typeof(DrawableTeamTitle),
typeof(DrawableTeamTitleWithHeader),
typeof(DrawableMatchTeam),
typeof(DrawableTeamWithPlayers),
typeof(GroupTeam),
typeof(TeamDisplay),
};
public TestSceneDrawableTournamentTeam()
: base(4, 3)
{
var team = new TournamentTeam
{
FlagName = { Value = "AU" },
FullName = { Value = "Australia" },
Players =
{
new User { Username = "ASecretBox" },
new User { Username = "Dereban" },
new User { Username = "mReKk" },
new User { Username = "uyghti" },
new User { Username = "Parkes" },
new User { Username = "Shiroha" },
new User { Username = "Jordan The Bear" },
}
};
var match = new TournamentMatch { Team1 = { Value = team } };
int i = 0;
Cell(i++).AddRange(new Drawable[]
{
new TournamentSpriteText { Text = "DrawableTeamFlag" },
new DrawableTeamFlag(team)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
});
Cell(i++).AddRange(new Drawable[]
{
new TournamentSpriteText { Text = "DrawableTeamTitle" },
new DrawableTeamTitle(team)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
});
Cell(i++).AddRange(new Drawable[]
{
new TournamentSpriteText { Text = "DrawableTeamTitleWithHeader" },
new DrawableTeamTitleWithHeader(team, TeamColour.Red)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
});
Cell(i++).AddRange(new Drawable[]
{
new TournamentSpriteText { Text = "DrawableMatchTeam" },
new DrawableMatchTeam(team, match, false)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
});
Cell(i++).AddRange(new Drawable[]
{
new TournamentSpriteText { Text = "TeamWithPlayers" },
new DrawableTeamWithPlayers(team, TeamColour.Blue)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
});
Cell(i++).AddRange(new Drawable[]
{
new TournamentSpriteText { Text = "GroupTeam" },
new GroupTeam(team)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
});
Cell(i).AddRange(new Drawable[]
{
new TournamentSpriteText { Text = "TeamDisplay" },
new TeamDisplay(team, TournamentGame.COLOUR_RED, false)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
});
}
}
}

View File

@ -0,0 +1,33 @@
// 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 JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Tournament.Models;
namespace osu.Game.Tournament.Components
{
public class DrawableTeamFlag : Sprite
{
private readonly TournamentTeam team;
[UsedImplicitly]
private Bindable<string> flag;
public DrawableTeamFlag(TournamentTeam team)
{
this.team = team;
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
if (team == null) return;
(flag = team.FlagName.GetBoundCopy()).BindValueChanged(acronym => Texture = textures.Get($@"Flags/{team.FlagName}"), true);
}
}
}

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.Game.Tournament.Models;
using osuTK;
namespace osu.Game.Tournament.Components
{
public class DrawableTeamHeader : TournamentSpriteTextWithBackground
{
public DrawableTeamHeader(TeamColour colour)
{
Background.Colour = TournamentGame.GetTeamColour(colour);
Text.Colour = TournamentGame.TEXT_COLOUR;
Text.Text = $"Team {colour}".ToUpperInvariant();
Text.Scale = new Vector2(0.6f);
}
}
}

View File

@ -0,0 +1,32 @@
// 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 JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Textures;
using osu.Game.Tournament.Models;
namespace osu.Game.Tournament.Components
{
public class DrawableTeamTitle : TournamentSpriteTextWithBackground
{
private readonly TournamentTeam team;
[UsedImplicitly]
private Bindable<string> acronym;
public DrawableTeamTitle(TournamentTeam team)
{
this.team = team;
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
if (team == null) return;
(acronym = team.Acronym.GetBoundCopy()).BindValueChanged(acronym => Text.Text = team?.FullName.Value ?? string.Empty, true);
}
}
}

View File

@ -0,0 +1,30 @@
// 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.Game.Tournament.Models;
using osuTK;
namespace osu.Game.Tournament.Components
{
public class DrawableTeamTitleWithHeader : CompositeDrawable
{
public DrawableTeamTitleWithHeader(TournamentTeam team, TeamColour colour)
{
AutoSizeAxes = Axes.Both;
InternalChild = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
new DrawableTeamHeader(colour),
new DrawableTeamTitle(team),
}
};
}
}
}

View File

@ -0,0 +1,66 @@
// 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.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Tournament.Models;
using osu.Game.Users;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tournament.Components
{
public class DrawableTeamWithPlayers : CompositeDrawable
{
public DrawableTeamWithPlayers(TournamentTeam team, TeamColour colour)
{
AutoSizeAxes = Axes.Both;
InternalChildren = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(30),
Children = new Drawable[]
{
new DrawableTeamTitleWithHeader(team, colour),
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Padding = new MarginPadding { Left = 10 },
Spacing = new Vector2(30),
Children = new Drawable[]
{
new FillFlowContainer
{
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Both,
ChildrenEnumerable = team?.Players.Select(createPlayerText).Take(5) ?? Enumerable.Empty<Drawable>()
},
new FillFlowContainer
{
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Both,
ChildrenEnumerable = team?.Players.Select(createPlayerText).Skip(5) ?? Enumerable.Empty<Drawable>()
},
}
},
}
},
};
TournamentSpriteText createPlayerText(User p) =>
new TournamentSpriteText
{
Text = p.Username,
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.SemiBold),
Colour = Color4.White,
};
}
}
}

View File

@ -23,14 +23,11 @@ namespace osu.Game.Tournament.Components
[UsedImplicitly] [UsedImplicitly]
private Bindable<string> acronym; private Bindable<string> acronym;
[UsedImplicitly]
private Bindable<string> flag;
protected DrawableTournamentTeam(TournamentTeam team) protected DrawableTournamentTeam(TournamentTeam team)
{ {
Team = team; Team = team;
Flag = new Sprite Flag = new DrawableTeamFlag(team)
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit FillMode = FillMode.Fit
@ -48,7 +45,6 @@ namespace osu.Game.Tournament.Components
if (Team == null) return; if (Team == null) return;
(acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(acronym => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true); (acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(acronym => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true);
(flag = Team.FlagName.GetBoundCopy()).BindValueChanged(acronym => Flag.Texture = textures.Get($@"Flags/{Team.FlagName}"), true);
} }
} }
} }

View File

@ -0,0 +1,16 @@
// 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.Game.Graphics;
namespace osu.Game.Tournament.Components
{
public class DrawableTournamentTitleText : TournamentSpriteText
{
public DrawableTournamentTitleText()
{
Text = "osu!taiko world cup 2020";
Font = OsuFont.Torus.With(size: 26, weight: FontWeight.SemiBold);
}
}
}

View File

@ -0,0 +1,36 @@
// 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.Game.Graphics;
using osu.Game.Tournament.Models;
namespace osu.Game.Tournament.Components
{
public class RoundDisplay : CompositeDrawable
{
public RoundDisplay(TournamentMatch match)
{
AutoSizeAxes = Axes.Both;
InternalChildren = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new DrawableTournamentTitleText(),
new TournamentSpriteText
{
Text = match.Round.Value?.Name.Value ?? "Unknown Round",
Font = OsuFont.Torus.With(size: 26, weight: FontWeight.SemiBold)
},
}
}
};
}
}
}

View File

@ -27,7 +27,7 @@ namespace osu.Game.Tournament.Components
private readonly string mods; private readonly string mods;
private const float horizontal_padding = 10; private const float horizontal_padding = 10;
private const float vertical_padding = 5; private const float vertical_padding = 10;
public const float HEIGHT = 50; public const float HEIGHT = 50;
@ -50,8 +50,6 @@ namespace osu.Game.Tournament.Components
currentMatch.BindValueChanged(matchChanged); currentMatch.BindValueChanged(matchChanged);
currentMatch.BindTo(ladder.CurrentMatch); currentMatch.BindTo(ladder.CurrentMatch);
CornerRadius = HEIGHT / 2;
CornerExponent = 2;
Masking = true; Masking = true;
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
@ -70,16 +68,12 @@ namespace osu.Game.Tournament.Components
new FillFlowContainer new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Padding = new MarginPadding(vertical_padding), Padding = new MarginPadding(vertical_padding),
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Children = new Drawable[] Children = new Drawable[]
{ {
new TournamentSpriteText new TournamentSpriteText
{ {
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Text = new LocalisedString(( Text = new LocalisedString((
$"{Beatmap.Metadata.ArtistUnicode ?? Beatmap.Metadata.Artist} - {Beatmap.Metadata.TitleUnicode ?? Beatmap.Metadata.Title}", $"{Beatmap.Metadata.ArtistUnicode ?? Beatmap.Metadata.Artist} - {Beatmap.Metadata.TitleUnicode ?? Beatmap.Metadata.Title}",
$"{Beatmap.Metadata.Artist} - {Beatmap.Metadata.Title}")), $"{Beatmap.Metadata.Artist} - {Beatmap.Metadata.Title}")),
@ -88,9 +82,6 @@ namespace osu.Game.Tournament.Components
new FillFlowContainer new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Padding = new MarginPadding(vertical_padding),
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
Children = new Drawable[] Children = new Drawable[]
{ {
@ -170,16 +161,7 @@ namespace osu.Game.Tournament.Components
BorderThickness = 6; BorderThickness = 6;
switch (found.Team) BorderColour = TournamentGame.GetTeamColour(found.Team);
{
case TeamColour.Red:
BorderColour = Color4.Red;
break;
case TeamColour.Blue:
BorderColour = Color4.Blue;
break;
}
switch (found.Type) switch (found.Type)
{ {

View File

@ -66,6 +66,10 @@ namespace osu.Game.Tournament.Components
} }
} }
public void Expand() => this.FadeIn(300);
public void Contract() => this.FadeOut(200);
protected override ChatLine CreateMessage(Message message) => new MatchMessage(message); protected override ChatLine CreateMessage(Message message) => new MatchMessage(message);
protected class MatchMessage : StandAloneMessage protected class MatchMessage : StandAloneMessage

View File

@ -0,0 +1,37 @@
// 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.Shapes;
using osu.Game.Graphics;
namespace osu.Game.Tournament.Components
{
public class TournamentSpriteTextWithBackground : CompositeDrawable
{
protected readonly TournamentSpriteText Text;
protected readonly Box Background;
public TournamentSpriteTextWithBackground(string text = "")
{
AutoSizeAxes = Axes.Both;
InternalChildren = new Drawable[]
{
Background = new Box
{
Colour = TournamentGame.ELEMENT_BACKGROUND_COLOUR,
RelativeSizeAxes = Axes.Both,
},
Text = new TournamentSpriteText
{
Colour = TournamentGame.ELEMENT_FOREGROUND_COLOUR,
Font = OsuFont.Torus.With(weight: FontWeight.SemiBold, size: 50),
Padding = new MarginPadding { Left = 10, Right = 20 },
Text = text
}
};
}
}
}

View File

@ -1,12 +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 System.IO; 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.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Video; using osu.Framework.Graphics.Video;
using osu.Framework.Platform;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -14,13 +15,34 @@ namespace osu.Game.Tournament.Components
{ {
public class TourneyVideo : CompositeDrawable public class TourneyVideo : CompositeDrawable
{ {
private readonly VideoSprite video; private readonly string filename;
private readonly bool drawFallbackGradient;
private VideoSprite video;
private readonly ManualClock manualClock; private ManualClock manualClock;
public TourneyVideo(Stream stream) public TourneyVideo(string filename, bool drawFallbackGradient = false)
{ {
if (stream == null) this.filename = filename;
this.drawFallbackGradient = drawFallbackGradient;
}
[BackgroundDependencyLoader]
private void load(Storage storage)
{
var stream = storage.GetStream($@"videos/{filename}.m4v");
if (stream != null)
{
InternalChild = video = new VideoSprite(stream)
{
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
Clock = new FramedClock(manualClock = new ManualClock()),
Loop = loop,
};
}
else if (drawFallbackGradient)
{ {
InternalChild = new Box InternalChild = new Box
{ {
@ -28,26 +50,26 @@ namespace osu.Game.Tournament.Components
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}; };
} }
else
{
InternalChild = video = new VideoSprite(stream)
{
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
Clock = new FramedClock(manualClock = new ManualClock())
};
}
} }
private bool loop;
public bool Loop public bool Loop
{ {
set set
{ {
loop = value;
if (video != null) if (video != null)
video.Loop = value; video.Loop = value;
} }
} }
public void Reset()
{
if (manualClock != null)
manualClock.CurrentTime = 0;
}
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();

View File

@ -90,6 +90,8 @@ namespace osu.Game.Tournament.Models
[JsonIgnore] [JsonIgnore]
public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value; public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value;
public TeamColour WinnerColour => Winner == Team1.Value ? TeamColour.Red : TeamColour.Blue;
public int PointsToWin => Round.Value?.BestOf.Value / 2 + 1 ?? 0; public int PointsToWin => Round.Value?.BestOf.Value / 2 + 1 ?? 0;
/// <summary> /// <summary>

View File

@ -8,7 +8,6 @@ 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.Game.Graphics;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -116,53 +115,5 @@ namespace osu.Game.Tournament.Screens.Drawings.Components
sb.AppendLine(gt.Team.FullName.Value); sb.AppendLine(gt.Team.FullName.Value);
return sb.ToString(); return sb.ToString();
} }
private class GroupTeam : DrawableTournamentTeam
{
private readonly FillFlowContainer innerContainer;
public GroupTeam(TournamentTeam team)
: base(team)
{
Width = 36;
AutoSizeAxes = Axes.Y;
Flag.Anchor = Anchor.TopCentre;
Flag.Origin = Anchor.TopCentre;
AcronymText.Anchor = Anchor.TopCentre;
AcronymText.Origin = Anchor.TopCentre;
AcronymText.Text = team.Acronym.Value.ToUpperInvariant();
AcronymText.Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 10);
InternalChildren = new Drawable[]
{
innerContainer = new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5f),
Children = new Drawable[]
{
Flag,
AcronymText
}
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
innerContainer.ScaleTo(1.5f);
innerContainer.ScaleTo(1f, 200);
}
}
} }
} }

View File

@ -0,0 +1,60 @@
// 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.Game.Graphics;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
using osuTK;
namespace osu.Game.Tournament.Screens.Drawings.Components
{
public class GroupTeam : DrawableTournamentTeam
{
private readonly FillFlowContainer innerContainer;
public GroupTeam(TournamentTeam team)
: base(team)
{
Width = 36;
AutoSizeAxes = Axes.Y;
Flag.Anchor = Anchor.TopCentre;
Flag.Origin = Anchor.TopCentre;
AcronymText.Anchor = Anchor.TopCentre;
AcronymText.Origin = Anchor.TopCentre;
AcronymText.Text = team.Acronym.Value.ToUpperInvariant();
AcronymText.Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 10);
InternalChildren = new Drawable[]
{
innerContainer = new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5f),
Children = new Drawable[]
{
Flag,
AcronymText
}
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
innerContainer.ScaleTo(1.5f);
innerContainer.ScaleTo(1f, 200);
}
}
}

View File

@ -129,8 +129,6 @@ namespace osu.Game.Tournament.Screens.Editors
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
LayoutDuration = 200,
LayoutEasing = Easing.OutQuint,
ChildrenEnumerable = round.Beatmaps.Select(p => new RoundBeatmapRow(round, p)) ChildrenEnumerable = round.Beatmaps.Select(p => new RoundBeatmapRow(round, p))
}; };
} }

View File

@ -124,8 +124,6 @@ namespace osu.Game.Tournament.Screens.Editors
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
LayoutDuration = 200,
LayoutEasing = Easing.OutQuint,
ChildrenEnumerable = round.Beatmaps.Select(p => new SeedingBeatmapRow(round, p)) ChildrenEnumerable = round.Beatmaps.Select(p => new SeedingBeatmapRow(round, p))
}; };
} }

View File

@ -172,19 +172,6 @@ namespace osu.Game.Tournament.Screens.Editors
drawableContainer.Child = new DrawableTeamFlag(Model); drawableContainer.Child = new DrawableTeamFlag(Model);
} }
private class DrawableTeamFlag : DrawableTournamentTeam
{
public DrawableTeamFlag(TournamentTeam team)
: base(team)
{
InternalChild = Flag;
RelativeSizeAxes = Axes.Both;
Flag.Anchor = Anchor.Centre;
Flag.Origin = Anchor.Centre;
}
}
public class PlayerEditor : CompositeDrawable public class PlayerEditor : CompositeDrawable
{ {
private readonly TournamentTeam team; private readonly TournamentTeam team;
@ -202,8 +189,6 @@ namespace osu.Game.Tournament.Screens.Editors
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
LayoutDuration = 200,
LayoutEasing = Easing.OutQuint,
ChildrenEnumerable = team.Players.Select(p => new PlayerRow(team, p)) ChildrenEnumerable = team.Players.Select(p => new PlayerRow(team, p))
}; };
} }

View File

@ -40,7 +40,6 @@ namespace osu.Game.Tournament.Screens.Editors
new OsuScrollContainer new OsuScrollContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Width = 0.9f,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Child = flow = new FillFlowContainer<TDrawable> Child = flow = new FillFlowContainer<TDrawable>
@ -48,8 +47,6 @@ namespace osu.Game.Tournament.Screens.Editors
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
LayoutDuration = 200,
LayoutEasing = Easing.OutQuint,
Spacing = new Vector2(20) Spacing = new Vector2(20)
}, },
}, },

View File

@ -5,15 +5,9 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
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.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.Showcase;
using osuTK;
using osuTK.Graphics;
using osuTK.Input; using osuTK.Input;
namespace osu.Game.Tournament.Screens.Gameplay.Components namespace osu.Game.Tournament.Screens.Gameplay.Components
@ -46,181 +40,75 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
}, },
}; };
} }
}
private class TeamScoreDisplay : CompositeDrawable public class TeamScoreDisplay : CompositeDrawable
{
private readonly TeamColour teamColour;
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
private readonly Bindable<TournamentTeam> currentTeam = new Bindable<TournamentTeam>();
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>();
public TeamScoreDisplay(TeamColour teamColour)
{ {
private readonly TeamColour teamColour; this.teamColour = teamColour;
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>(); RelativeSizeAxes = Axes.Y;
private readonly Bindable<TournamentTeam> currentTeam = new Bindable<TournamentTeam>(); Width = 300;
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>(); }
public TeamScoreDisplay(TeamColour teamColour) [BackgroundDependencyLoader]
private void load(LadderInfo ladder)
{
currentMatch.BindValueChanged(matchChanged);
currentMatch.BindTo(ladder.CurrentMatch);
}
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
{
currentTeamScore.UnbindBindings();
currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1Score : match.NewValue.Team2Score);
currentTeam.UnbindBindings();
currentTeam.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1 : match.NewValue.Team2);
// team may change to same team, which means score is not in a good state.
// thus we handle this manually.
teamChanged(currentTeam.Value);
}
protected override bool OnMouseDown(MouseDownEvent e)
{
switch (e.Button)
{ {
this.teamColour = teamColour; case MouseButton.Left:
if (currentTeamScore.Value < currentMatch.Value.PointsToWin)
currentTeamScore.Value++;
return true;
RelativeSizeAxes = Axes.Y; case MouseButton.Right:
Width = 300; if (currentTeamScore.Value > 0)
currentTeamScore.Value--;
return true;
} }
[BackgroundDependencyLoader] return base.OnMouseDown(e);
private void load(LadderInfo ladder) }
private void teamChanged(TournamentTeam team)
{
var colour = teamColour == TeamColour.Red ? TournamentGame.COLOUR_RED : TournamentGame.COLOUR_BLUE;
var flip = teamColour == TeamColour.Red;
InternalChildren = new Drawable[]
{ {
currentMatch.BindValueChanged(matchChanged); new TeamDisplay(team, colour, flip),
currentMatch.BindTo(ladder.CurrentMatch); new TeamScore(currentTeamScore, flip, currentMatch.Value.PointsToWin)
}
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
{
currentTeamScore.UnbindBindings();
currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1Score : match.NewValue.Team2Score);
currentTeam.UnbindBindings();
currentTeam.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1 : match.NewValue.Team2);
// team may change to same team, which means score is not in a good state.
// thus we handle this manually.
teamChanged(currentTeam.Value);
}
protected override bool OnMouseDown(MouseDownEvent e)
{
switch (e.Button)
{ {
case MouseButton.Left: Colour = colour
if (currentTeamScore.Value < currentMatch.Value.PointsToWin)
currentTeamScore.Value++;
return true;
case MouseButton.Right:
if (currentTeamScore.Value > 0)
currentTeamScore.Value--;
return true;
} }
};
return base.OnMouseDown(e);
}
private void teamChanged(TournamentTeam team)
{
var colour = teamColour == TeamColour.Red ? TournamentGame.COLOUR_RED : TournamentGame.COLOUR_BLUE;
var flip = teamColour != TeamColour.Red;
InternalChildren = new Drawable[]
{
new TeamDisplay(team, colour, flip),
new TeamScore(currentTeamScore, flip, currentMatch.Value.PointsToWin)
{
Colour = colour
}
};
}
}
private class TeamScore : CompositeDrawable
{
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>();
private readonly StarCounter counter;
public TeamScore(Bindable<int?> score, bool flip, int count)
{
var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft;
Anchor = anchor;
Origin = anchor;
InternalChild = counter = new StarCounter(count)
{
Anchor = anchor,
X = (flip ? -1 : 1) * 90,
Y = 5,
Scale = flip ? new Vector2(-1, 1) : Vector2.One,
};
currentTeamScore.BindValueChanged(scoreChanged);
currentTeamScore.BindTo(score);
}
private void scoreChanged(ValueChangedEvent<int?> score) => counter.CountStars = score.NewValue ?? 0;
}
private class TeamDisplay : DrawableTournamentTeam
{
public TeamDisplay(TournamentTeam team, Color4 colour, bool flip)
: base(team)
{
RelativeSizeAxes = Axes.Both;
var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft;
Anchor = Origin = anchor;
Flag.Anchor = Flag.Origin = anchor;
Flag.RelativeSizeAxes = Axes.None;
Flag.Size = new Vector2(60, 40);
Flag.Margin = new MarginPadding(20);
InternalChild = new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
Flag,
new TournamentSpriteText
{
Text = team?.FullName.Value.ToUpper() ?? "???",
X = (flip ? -1 : 1) * 90,
Y = -10,
Colour = colour,
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 20),
Origin = anchor,
Anchor = anchor,
},
}
};
}
}
private class RoundDisplay : CompositeDrawable
{
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
private readonly TournamentSpriteText text;
public RoundDisplay()
{
Width = 200;
Height = 20;
Masking = true;
CornerRadius = 10;
InternalChildren = new Drawable[]
{
new Box
{
Colour = OsuColour.Gray(0.18f),
RelativeSizeAxes = Axes.Both,
},
text = new TournamentSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Colour = Color4.White,
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 16),
},
};
}
[BackgroundDependencyLoader]
private void load(LadderInfo ladder)
{
currentMatch.BindValueChanged(matchChanged);
currentMatch.BindTo(ladder.CurrentMatch);
}
private void matchChanged(ValueChangedEvent<TournamentMatch> match) =>
text.Text = match.NewValue.Round.Value?.Name.Value ?? "Unknown Round";
} }
} }
} }

View File

@ -0,0 +1,56 @@
// 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.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Tournament.Models;
using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.Gameplay.Components
{
public class RoundDisplay : CompositeDrawable
{
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
private readonly TournamentSpriteText text;
public RoundDisplay()
{
Width = 200;
Height = 20;
Masking = true;
CornerRadius = 10;
InternalChildren = new Drawable[]
{
new Box
{
Colour = OsuColour.Gray(0.18f),
RelativeSizeAxes = Axes.Both,
},
text = new TournamentSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Colour = Color4.White,
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 16),
},
};
}
[BackgroundDependencyLoader]
private void load(LadderInfo ladder)
{
currentMatch.BindValueChanged(matchChanged);
currentMatch.BindTo(ladder.CurrentMatch);
}
private void matchChanged(ValueChangedEvent<TournamentMatch> match) =>
text.Text = match.NewValue.Round.Value?.Name.Value ?? "Unknown Round";
}
}

View File

@ -0,0 +1,50 @@
// 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.Game.Graphics;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.Gameplay.Components
{
public class TeamDisplay : DrawableTournamentTeam
{
public TeamDisplay(TournamentTeam team, Color4 colour, bool flip)
: base(team)
{
RelativeSizeAxes = Axes.Both;
var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft;
Anchor = Origin = anchor;
Flag.Anchor = Flag.Origin = anchor;
Flag.RelativeSizeAxes = Axes.None;
Flag.Size = new Vector2(60, 40);
Flag.Margin = new MarginPadding(20);
InternalChild = new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
Flag,
new TournamentSpriteText
{
Text = team?.FullName.Value.ToUpper() ?? "???",
X = (flip ? -1 : 1) * 90,
Y = -10,
Colour = colour,
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 20),
Origin = anchor,
Anchor = anchor,
},
}
};
}
}
}

View File

@ -0,0 +1,38 @@
// 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.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osuTK;
namespace osu.Game.Tournament.Screens.Gameplay.Components
{
public class TeamScore : CompositeDrawable
{
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>();
private readonly StarCounter counter;
public TeamScore(Bindable<int?> score, bool flip, int count)
{
var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft;
Anchor = anchor;
Origin = anchor;
InternalChild = counter = new StarCounter(count)
{
Anchor = anchor,
X = (flip ? -1 : 1) * 90,
Y = 5,
Scale = flip ? new Vector2(-1, 1) : Vector2.One,
};
currentTeamScore.BindValueChanged(scoreChanged);
currentTeamScore.BindTo(score);
}
private void scoreChanged(ValueChangedEvent<int?> score) => counter.Current = score.NewValue ?? 0;
}
}

View File

@ -6,6 +6,7 @@ using osu.Framework.Bindables;
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.Platform;
using osu.Framework.Threading; using osu.Framework.Threading;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Tournament.Components; using osu.Game.Tournament.Components;
@ -19,7 +20,7 @@ using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.Gameplay namespace osu.Game.Tournament.Screens.Gameplay
{ {
public class GameplayScreen : BeatmapInfoScreen public class GameplayScreen : BeatmapInfoScreen, IProvideVideo
{ {
private readonly BindableBool warmup = new BindableBool(); private readonly BindableBool warmup = new BindableBool();
@ -39,12 +40,17 @@ namespace osu.Game.Tournament.Screens.Gameplay
private TournamentMatchChatDisplay chat { get; set; } private TournamentMatchChatDisplay chat { get; set; }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(LadderInfo ladder, MatchIPCInfo ipc) private void load(LadderInfo ladder, MatchIPCInfo ipc, Storage storage)
{ {
this.ipc = ipc; this.ipc = ipc;
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
{ {
new TourneyVideo("gameplay")
{
Loop = true,
RelativeSizeAxes = Axes.Both,
},
new MatchHeader(), new MatchHeader(),
new Container new Container
{ {
@ -156,7 +162,7 @@ namespace osu.Game.Tournament.Screens.Gameplay
void expand() void expand()
{ {
chat?.Expand(); chat?.Contract();
using (BeginDelayedSequence(300, true)) using (BeginDelayedSequence(300, true))
{ {
@ -170,7 +176,7 @@ namespace osu.Game.Tournament.Screens.Gameplay
SongBar.Expanded = false; SongBar.Expanded = false;
scoreDisplay.FadeOut(100); scoreDisplay.FadeOut(100);
using (chat?.BeginDelayedSequence(500)) using (chat?.BeginDelayedSequence(500))
chat?.Contract(); chat?.Expand();
} }
switch (state.NewValue) switch (state.NewValue)
@ -197,7 +203,7 @@ namespace osu.Game.Tournament.Screens.Gameplay
break; break;
default: default:
chat.Expand(); chat.Contract();
expand(); expand();
break; break;
} }

View File

@ -27,21 +27,23 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
private readonly bool losers; private readonly bool losers;
private TournamentSpriteText scoreText; private TournamentSpriteText scoreText;
private Box background; private Box background;
private Box backgroundRight;
private readonly Bindable<int?> score = new Bindable<int?>(); private readonly Bindable<int?> score = new Bindable<int?>();
private readonly BindableBool completed = new BindableBool(); private readonly BindableBool completed = new BindableBool();
private Color4 colourWinner; private Color4 colourWinner;
private Color4 colourNormal;
private readonly Func<bool> isWinner; private readonly Func<bool> isWinner;
private LadderEditorScreen ladderEditor; private LadderEditorScreen ladderEditor;
[Resolved] [Resolved(canBeNull: true)]
private LadderInfo ladderInfo { get; set; } private LadderInfo ladderInfo { get; set; }
private void setCurrent() private void setCurrent()
{ {
if (ladderInfo == null) return;
//todo: tournamentgamebase? //todo: tournamentgamebase?
if (ladderInfo.CurrentMatch.Value != null) if (ladderInfo.CurrentMatch.Value != null)
ladderInfo.CurrentMatch.Value.Current.Value = false; ladderInfo.CurrentMatch.Value.Current.Value = false;
@ -60,15 +62,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
this.losers = losers; this.losers = losers;
Size = new Vector2(150, 40); Size = new Vector2(150, 40);
Masking = true;
CornerRadius = 5;
Flag.Scale = new Vector2(0.9f); Flag.Scale = new Vector2(0.9f);
Flag.Anchor = Flag.Origin = Anchor.CentreLeft; Flag.Anchor = Flag.Origin = Anchor.CentreLeft;
AcronymText.Anchor = AcronymText.Origin = Anchor.CentreLeft; AcronymText.Anchor = AcronymText.Origin = Anchor.CentreLeft;
AcronymText.Padding = new MarginPadding { Left = 50 }; AcronymText.Padding = new MarginPadding { Left = 50 };
AcronymText.Font = OsuFont.Torus.With(size: 24); AcronymText.Font = OsuFont.Torus.With(size: 22, weight: FontWeight.Bold);
if (match != null) if (match != null)
{ {
@ -85,8 +84,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{ {
this.ladderEditor = ladderEditor; this.ladderEditor = ladderEditor;
colourWinner = losers ? colours.YellowDarker : colours.BlueDarker; colourWinner = losers
colourNormal = OsuColour.Gray(0.2f); ? OsuColour.FromHex("#8E7F48")
: OsuColour.FromHex("#1462AA");
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
@ -102,29 +102,28 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{ {
AcronymText, AcronymText,
Flag, Flag,
new Container }
},
new Container
{
Masking = true,
Width = 0.3f,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
backgroundRight = new Box
{ {
Masking = true, Colour = OsuColour.Gray(0.1f),
CornerRadius = 5, Alpha = 0.8f,
Width = 0.3f,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Children = new Drawable[] },
{ scoreText = new TournamentSpriteText
new Box {
{ Anchor = Anchor.Centre,
Colour = OsuColour.Gray(0.1f), Origin = Anchor.Centre,
Alpha = 0.8f, Font = OsuFont.Torus.With(size: 22),
RelativeSizeAxes = Axes.Both,
},
scoreText = new TournamentSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.Torus.With(size: 20),
}
}
} }
} }
} }
@ -181,9 +180,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{ {
bool winner = completed.Value && isWinner?.Invoke() == true; bool winner = completed.Value && isWinner?.Invoke() == true;
background.FadeColour(winner ? colourWinner : colourNormal, winner ? 500 : 0, Easing.OutQuint); background.FadeColour(winner ? Color4.White : OsuColour.FromHex("#444"), winner ? 500 : 0, Easing.OutQuint);
backgroundRight.FadeColour(winner ? colourWinner : OsuColour.FromHex("#333"), winner ? 500 : 0, Easing.OutQuint);
scoreText.Font = AcronymText.Font = OsuFont.Torus.With(weight: winner ? FontWeight.Bold : FontWeight.Regular); AcronymText.Colour = winner ? Color4.Black : Color4.White;
scoreText.Font = scoreText.Font.With(weight: winner ? FontWeight.Bold : FontWeight.Regular);
} }
public MenuItem[] ContextMenuItems public MenuItem[] ContextMenuItems

View File

@ -9,6 +9,7 @@ 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.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -45,9 +46,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{ {
selectionBox = new Container selectionBox = new Container
{ {
CornerRadius = 5, Scale = new Vector2(1.1f),
Masking = true,
Scale = new Vector2(1.05f),
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
@ -57,14 +56,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
}, },
currentMatchSelectionBox = new Container currentMatchSelectionBox = new Container
{ {
CornerRadius = 5, Scale = new Vector2(1.1f),
Masking = true,
Scale = new Vector2(1.05f),
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Alpha = 0, Alpha = 0,
Colour = Color4.OrangeRed, Colour = OsuColour.FromHex("#D24747"),
Child = new Box { RelativeSizeAxes = Axes.Both } Child = new Box { RelativeSizeAxes = Axes.Both }
}, },
Flow = new FillFlowContainer<DrawableMatchTeam> Flow = new FillFlowContainer<DrawableMatchTeam>

View File

@ -7,7 +7,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.Ladder.Components namespace osu.Game.Tournament.Screens.Ladder.Components
{ {
@ -33,14 +32,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{ {
textDescription = new TournamentSpriteText textDescription = new TournamentSpriteText
{ {
Colour = Color4.Black, Colour = TournamentGame.TEXT_COLOUR,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre Anchor = Anchor.TopCentre
}, },
textName = new TournamentSpriteText textName = new TournamentSpriteText
{ {
Font = OsuFont.Torus.With(weight: FontWeight.Bold), Font = OsuFont.Torus.With(weight: FontWeight.Bold),
Colour = Color4.Black, Colour = TournamentGame.TEXT_COLOUR,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre Anchor = Anchor.TopCentre
}, },

View File

@ -32,8 +32,8 @@ namespace osu.Game.Tournament.Screens.Ladder
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours, Storage storage) private void load(OsuColour colours, Storage storage)
{ {
normalPathColour = colours.BlueDarker.Darken(2); normalPathColour = OsuColour.FromHex("#66D1FF");
losersPathColour = colours.YellowDarker.Darken(2); losersPathColour = OsuColour.FromHex("#FFC700");
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
@ -42,11 +42,17 @@ namespace osu.Game.Tournament.Screens.Ladder
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Children = new Drawable[] Children = new Drawable[]
{ {
new TourneyVideo(storage.GetStream(@"videos/ladder.m4v")) new TourneyVideo("ladder")
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Loop = true, Loop = true,
}, },
new DrawableTournamentTitleText
{
Y = 100,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
},
ScrollContent = new LadderDragContainer ScrollContent = new LadderDragContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,

View File

@ -42,6 +42,11 @@ namespace osu.Game.Tournament.Screens.MapPool
{ {
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new TourneyVideo("gameplay")
{
Loop = true,
RelativeSizeAxes = Axes.Both,
},
new MatchHeader(), new MatchHeader(),
mapFlows = new FillFlowContainer<FillFlowContainer<TournamentBeatmapPanel>> mapFlows = new FillFlowContainer<FillFlowContainer<TournamentBeatmapPanel>>
{ {

View File

@ -18,7 +18,7 @@ using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.Schedule namespace osu.Game.Tournament.Screens.Schedule
{ {
public class ScheduleScreen : TournamentScreen, IProvideVideo public class ScheduleScreen : TournamentScreen
{ {
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>(); private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
private Container mainContainer; private Container mainContainer;
@ -33,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Schedule
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new TourneyVideo(storage.GetStream(@"videos/schedule.m4v")) new TourneyVideo("schedule")
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Loop = true, Loop = true,

View File

@ -34,7 +34,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new TourneyVideo(storage.GetStream(@"videos/seeding.m4v")) new TourneyVideo("seeding")
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Loop = true, Loop = true,

View File

@ -6,7 +6,6 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Graphics;
using osu.Game.Tournament.Components; using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osuTK; using osuTK;
@ -26,7 +25,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new TourneyVideo(storage.GetStream(@"videos/teamintro.m4v")) new TourneyVideo("teamintro")
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Loop = true, Loop = true,
@ -49,141 +48,33 @@ namespace osu.Game.Tournament.Screens.TeamIntro
return; return;
} }
const float y_flag_offset = 292;
const float y_offset = 460;
mainContainer.Children = new Drawable[] mainContainer.Children = new Drawable[]
{ {
new TeamWithPlayers(match.NewValue.Team1.Value, true)
{
RelativeSizeAxes = Axes.Both,
Width = 0.5f,
Height = 0.6f,
Anchor = Anchor.Centre,
Origin = Anchor.CentreRight
},
new TeamWithPlayers(match.NewValue.Team2.Value)
{
RelativeSizeAxes = Axes.Both,
Width = 0.5f,
Height = 0.6f,
Anchor = Anchor.Centre,
Origin = Anchor.CentreLeft
},
new RoundDisplay(match.NewValue) new RoundDisplay(match.NewValue)
{ {
RelativeSizeAxes = Axes.Both, Position = new Vector2(100, 100)
Height = 0.25f, },
Anchor = Anchor.TopCentre, new DrawableTeamFlag(match.NewValue.Team1.Value)
Origin = Anchor.TopCentre, {
Y = 180, Position = new Vector2(165, y_flag_offset),
} },
new DrawableTeamWithPlayers(match.NewValue.Team1.Value, TeamColour.Red)
{
Position = new Vector2(165, y_offset),
},
new DrawableTeamFlag(match.NewValue.Team2.Value)
{
Position = new Vector2(740, y_flag_offset),
},
new DrawableTeamWithPlayers(match.NewValue.Team2.Value, TeamColour.Blue)
{
Position = new Vector2(740, y_offset),
},
}; };
} }
private class RoundDisplay : CompositeDrawable
{
public RoundDisplay(TournamentMatch match)
{
InternalChildren = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
new TournamentSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Colour = OsuColour.Gray(0.33f),
Text = match.Round.Value?.Name.Value ?? "Unknown Round",
Font = OsuFont.Torus.With(size: 26, weight: FontWeight.Light)
},
}
}
};
}
}
private class TeamWithPlayers : CompositeDrawable
{
public TeamWithPlayers(TournamentTeam team, bool left = false)
{
FillFlowContainer players;
var colour = left ? TournamentGame.COLOUR_RED : TournamentGame.COLOUR_BLUE;
InternalChildren = new Drawable[]
{
new TeamDisplay(team)
{
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
Origin = Anchor.TopCentre,
RelativePositionAxes = Axes.Both,
X = (left ? -1 : 1) * 0.3145f,
Y = -0.077f,
},
players = new FillFlowContainer
{
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(0, 5),
Padding = new MarginPadding(20),
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
Origin = left ? Anchor.CentreRight : Anchor.CentreLeft,
RelativePositionAxes = Axes.Both,
X = (left ? -1 : 1) * 0.58f,
},
};
if (team != null)
{
foreach (var p in team.Players)
{
players.Add(new TournamentSpriteText
{
Text = p.Username,
Font = OsuFont.Torus.With(size: 24),
Colour = colour,
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
Origin = left ? Anchor.CentreRight : Anchor.CentreLeft,
});
}
}
}
private class TeamDisplay : DrawableTournamentTeam
{
public TeamDisplay(TournamentTeam team)
: base(team)
{
AutoSizeAxes = Axes.Both;
Flag.Anchor = Flag.Origin = Anchor.TopCentre;
Flag.RelativeSizeAxes = Axes.None;
Flag.Size = new Vector2(300, 200);
Flag.Scale = new Vector2(0.32f);
InternalChild = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(160),
Children = new Drawable[]
{
Flag,
new TournamentSpriteText
{
Text = team?.FullName.Value ?? "???",
Font = OsuFont.Torus.With(size: 20, weight: FontWeight.Regular),
Colour = OsuColour.Gray(0.2f),
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
},
}
};
}
}
}
} }
} }

View File

@ -10,7 +10,6 @@ using osu.Game.Graphics;
using osu.Game.Tournament.Components; using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osuTK; using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.TeamWin namespace osu.Game.Tournament.Screens.TeamWin
{ {
@ -31,13 +30,13 @@ namespace osu.Game.Tournament.Screens.TeamWin
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
blueWinVideo = new TourneyVideo(storage.GetStream(@"videos/teamwin-blue.m4v")) blueWinVideo = new TourneyVideo("teamwin-blue")
{ {
Alpha = 1, Alpha = 1,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Loop = true, Loop = true,
}, },
redWinVideo = new TourneyVideo(storage.GetStream(@"videos/teamwin-red.m4v")) redWinVideo = new TourneyVideo("teamwin-red")
{ {
Alpha = 0, Alpha = 0,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -63,7 +62,9 @@ namespace osu.Game.Tournament.Screens.TeamWin
update(); update();
} }
private void update() private bool firstDisplay = true;
private void update() => Schedule(() =>
{ {
var match = currentMatch.Value; var match = currentMatch.Value;
@ -73,105 +74,53 @@ namespace osu.Game.Tournament.Screens.TeamWin
return; return;
} }
bool redWin = match.Winner == match.Team1.Value; redWinVideo.Alpha = match.WinnerColour == TeamColour.Red ? 1 : 0;
redWinVideo.Alpha = redWin ? 1 : 0; blueWinVideo.Alpha = match.WinnerColour == TeamColour.Blue ? 1 : 0;
blueWinVideo.Alpha = redWin ? 0 : 1;
if (firstDisplay)
{
if (match.WinnerColour == TeamColour.Red)
redWinVideo.Reset();
else
blueWinVideo.Reset();
firstDisplay = false;
}
mainContainer.Children = new Drawable[] mainContainer.Children = new Drawable[]
{ {
new TeamFlagDisplay(match.Winner) new DrawableTeamFlag(match.Winner)
{ {
Size = new Vector2(300, 200), Size = new Vector2(300, 200),
Scale = new Vector2(0.5f), Scale = new Vector2(0.5f),
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
X = -387, Position = new Vector2(-300, 10),
}, },
new TournamentSpriteText new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.TopLeft, Origin = Anchor.Centre,
Position = new Vector2(78, -70), X = 260,
Colour = OsuColour.Gray(0.33f), Children = new Drawable[]
Text = match.Round.Value?.Name.Value ?? "Unknown Round", {
Font = OsuFont.Torus.With(size: 30, weight: FontWeight.Regular) new RoundDisplay(match)
}, {
new TeamWithPlayers(match.Winner, redWin) Margin = new MarginPadding { Bottom = 30 },
{ },
RelativeSizeAxes = Axes.Both, new TournamentSpriteText
Width = 0.5f, {
Height = 0.6f, Text = "WINNER",
Anchor = Anchor.Centre, Font = OsuFont.Torus.With(size: 100, weight: FontWeight.Bold),
Origin = Anchor.TopLeft, Margin = new MarginPadding { Bottom = 50 },
Position = new Vector2(78, 0), },
new DrawableTeamWithPlayers(match.Winner, match.WinnerColour)
}
}, },
}; };
} mainContainer.FadeOut();
mainContainer.Delay(2000).FadeIn(1600, Easing.OutQuint);
private class TeamWithPlayers : CompositeDrawable });
{
public TeamWithPlayers(TournamentTeam team, bool left = false)
{
FillFlowContainer players;
var colour = left ? TournamentGame.COLOUR_RED : TournamentGame.COLOUR_BLUE;
InternalChildren = new Drawable[]
{
new FillFlowContainer
{
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new TournamentSpriteText
{
Text = "WINNER",
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.SemiBold),
Colour = Color4.Black,
},
new TournamentSpriteText
{
Text = team?.FullName.Value ?? "???",
Font = OsuFont.Torus.With(size: 30, weight: FontWeight.SemiBold),
Colour = Color4.Black,
},
players = new FillFlowContainer
{
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = 10 },
},
}
},
};
if (team != null)
{
foreach (var p in team.Players)
{
players.Add(new TournamentSpriteText
{
Text = p.Username,
Font = OsuFont.Torus.With(size: 24),
Colour = colour,
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
Origin = left ? Anchor.CentreRight : Anchor.CentreLeft,
});
}
}
}
}
private class TeamFlagDisplay : DrawableTournamentTeam
{
public TeamFlagDisplay(TournamentTeam team)
: base(team)
{
InternalChildren = new Drawable[]
{
Flag
};
}
}
} }
} }

View File

@ -18,6 +18,9 @@ namespace osu.Game.Tournament.Screens
protected TournamentScreen() protected TournamentScreen()
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
FillMode = FillMode.Fit;
FillAspectRatio = 16 / 9f;
} }
public override void Hide() => this.FadeOut(FADE_DELAY); public override void Hide() => this.FadeOut(FADE_DELAY);

View File

@ -2,15 +2,25 @@
// 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; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Game.Graphics;
using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Cursor;
using osu.Game.Tournament.Models;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Tournament namespace osu.Game.Tournament
{ {
public class TournamentGame : TournamentGameBase public class TournamentGame : TournamentGameBase
{ {
public static readonly Color4 COLOUR_RED = new Color4(144, 0, 0, 255); public static ColourInfo GetTeamColour(TeamColour teamColour) => teamColour == TeamColour.Red ? COLOUR_RED : COLOUR_BLUE;
public static readonly Color4 COLOUR_BLUE = new Color4(0, 84, 144, 255);
public static readonly Color4 COLOUR_RED = OsuColour.FromHex("#AA1414");
public static readonly Color4 COLOUR_BLUE = OsuColour.FromHex("#1462AA");
public static readonly Color4 ELEMENT_BACKGROUND_COLOUR = OsuColour.FromHex("#fff");
public static readonly Color4 ELEMENT_FOREGROUND_COLOUR = OsuColour.FromHex("#000");
public static readonly Color4 TEXT_COLOUR = OsuColour.FromHex("#fff");
protected override void LoadComplete() protected override void LoadComplete()
{ {

View File

@ -22,6 +22,7 @@ using osu.Game.Online.API.Requests;
using osu.Game.Tournament.IPC; using osu.Game.Tournament.IPC;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osu.Game.Users; using osu.Game.Users;
using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osuTK.Input; using osuTK.Input;
@ -74,16 +75,40 @@ namespace osu.Game.Tournament
AddRange(new[] AddRange(new[]
{ {
new TourneyButton new Container
{ {
Text = "Save Changes", CornerRadius = 10,
Width = 140,
Height = 50,
Depth = float.MinValue, Depth = float.MinValue,
Position = new Vector2(5),
Masking = true,
AutoSizeAxes = Axes.Both,
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
Padding = new MarginPadding(10), Children = new Drawable[]
Action = SaveChanges, {
new Box
{
Colour = OsuColour.Gray(0.2f),
RelativeSizeAxes = Axes.Both,
},
new TourneyButton
{
Text = "Save Changes",
Width = 140,
Height = 50,
Padding = new MarginPadding
{
Top = 10,
Left = 10,
},
Margin = new MarginPadding
{
Right = 10,
Bottom = 10,
},
Action = SaveChanges,
},
}
}, },
heightWarning = new Container heightWarning = new Container
{ {

View File

@ -61,7 +61,7 @@ namespace osu.Game.Tournament
//Masking = true, //Masking = true,
Children = new Drawable[] Children = new Drawable[]
{ {
video = new TourneyVideo(storage.GetStream("videos/main.m4v")) video = new TourneyVideo("main", true)
{ {
Loop = true, Loop = true,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,

View File

@ -18,7 +18,11 @@ namespace osu.Game.Graphics.UserInterface
{ {
public class OsuPasswordTextBox : OsuTextBox, ISuppressKeyEventLogging public class OsuPasswordTextBox : OsuTextBox, ISuppressKeyEventLogging
{ {
protected override Drawable GetDrawableCharacter(char c) => new PasswordMaskChar(CalculatedTextSize); protected override Drawable GetDrawableCharacter(char c) => new FallingDownContainer
{
AutoSizeAxes = Axes.Both,
Child = new PasswordMaskChar(CalculatedTextSize),
};
protected override bool AllowClipboardExport => false; protected override bool AllowClipboardExport => false;

View File

@ -63,7 +63,11 @@ namespace osu.Game.Graphics.UserInterface
base.OnFocusLost(e); base.OnFocusLost(e);
} }
protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) }; protected override Drawable GetDrawableCharacter(char c) => new FallingDownContainer
{
AutoSizeAxes = Axes.Both,
Child = new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) },
};
protected override Caret CreateCaret() => new OsuCaret protected override Caret CreateCaret() => new OsuCaret
{ {

View File

@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterface
{ {
public class StarCounter : Container public class StarCounter : Container
{ {
private readonly Container<Star> stars; private readonly FillFlowContainer<Star> stars;
/// <summary> /// <summary>
/// Maximum amount of stars displayed. /// Maximum amount of stars displayed.
@ -23,34 +23,29 @@ namespace osu.Game.Graphics.UserInterface
/// </remarks> /// </remarks>
public int StarCount { get; } public int StarCount { get; }
private double animationDelay => 80; /// <summary>
/// The added delay for each subsequent star to be animated.
/// </summary>
protected virtual double AnimationDelay => 80;
private double scalingDuration => 1000;
private Easing scalingEasing => Easing.OutElasticHalf;
private float minStarScale => 0.4f;
private double fadingDuration => 100;
private float minStarAlpha => 0.5f;
private const float star_size = 20;
private const float star_spacing = 4; private const float star_spacing = 4;
private float countStars; private float current;
/// <summary> /// <summary>
/// Amount of stars represented. /// Amount of stars represented.
/// </summary> /// </summary>
public float CountStars public float Current
{ {
get => countStars; get => current;
set set
{ {
if (countStars == value) return; if (current == value) return;
if (IsLoaded) if (IsLoaded)
transformCount(value); animate(value);
countStars = value; current = value;
} }
} }
@ -71,11 +66,13 @@ namespace osu.Game.Graphics.UserInterface
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
Spacing = new Vector2(star_spacing), Spacing = new Vector2(star_spacing),
ChildrenEnumerable = Enumerable.Range(0, StarCount).Select(i => new Star { Alpha = minStarAlpha }) ChildrenEnumerable = Enumerable.Range(0, StarCount).Select(i => CreateStar())
} }
}; };
} }
public virtual Star CreateStar() => new DefaultStar();
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
@ -86,63 +83,60 @@ namespace osu.Game.Graphics.UserInterface
public void ResetCount() public void ResetCount()
{ {
countStars = 0; current = 0;
StopAnimation(); StopAnimation();
} }
public void ReplayAnimation() public void ReplayAnimation()
{ {
var t = countStars; var t = current;
ResetCount(); ResetCount();
CountStars = t; Current = t;
} }
public void StopAnimation() public void StopAnimation()
{ {
int i = 0; animate(current);
foreach (var star in stars.Children) foreach (var star in stars.Children)
star.FinishTransforms(true);
}
private float getStarScale(int i, float value) => i + 1 <= value ? 1.0f : Interpolation.ValueAt(value, 0, 1.0f, i, i + 1);
private void animate(float newValue)
{
for (var i = 0; i < stars.Children.Count; i++)
{ {
var star = stars.Children[i];
star.ClearTransforms(true); star.ClearTransforms(true);
star.FadeTo(i < countStars ? 1.0f : minStarAlpha);
star.Icon.ScaleTo(getStarScale(i, countStars)); double delay = (current <= newValue ? Math.Max(i - current, 0) : Math.Max(current - 1 - i, 0)) * AnimationDelay;
i++;
using (star.BeginDelayedSequence(delay, true))
star.DisplayAt(getStarScale(i, newValue));
} }
} }
private float getStarScale(int i, float value) public class DefaultStar : Star
{ {
if (value <= i) private const double scaling_duration = 1000;
return minStarScale;
return i + 1 <= value ? 1.0f : Interpolation.ValueAt(value, minStarScale, 1.0f, i, i + 1); private const double fading_duration = 100;
}
private void transformCount(float newValue) private const Easing scaling_easing = Easing.OutElasticHalf;
{
int i = 0;
foreach (var star in stars.Children) private const float min_star_scale = 0.4f;
{
star.ClearTransforms(true);
var delay = (countStars <= newValue ? Math.Max(i - countStars, 0) : Math.Max(countStars - 1 - i, 0)) * animationDelay; private const float star_size = 20;
star.Delay(delay).FadeTo(i < newValue ? 1.0f : minStarAlpha, fadingDuration);
star.Icon.Delay(delay).ScaleTo(getStarScale(i, newValue), scalingDuration, scalingEasing);
i++;
}
}
private class Star : Container
{
public readonly SpriteIcon Icon; public readonly SpriteIcon Icon;
public Star() public DefaultStar()
{ {
Size = new Vector2(star_size); Size = new Vector2(star_size);
Child = Icon = new SpriteIcon InternalChild = Icon = new SpriteIcon
{ {
Size = new Vector2(star_size), Size = new Vector2(star_size),
Icon = FontAwesome.Solid.Star, Icon = FontAwesome.Solid.Star,
@ -150,6 +144,19 @@ namespace osu.Game.Graphics.UserInterface
Origin = Anchor.Centre, Origin = Anchor.Centre,
}; };
} }
public override void DisplayAt(float scale)
{
scale = Math.Clamp(scale, min_star_scale, 1);
this.FadeTo(scale, fading_duration);
Icon.ScaleTo(scale, scaling_duration, scaling_easing);
}
}
public abstract class Star : CompositeDrawable
{
public abstract void DisplayAt(float scale);
} }
} }
} }

View File

@ -92,18 +92,6 @@ namespace osu.Game.Online.Chat
textbox.Text = string.Empty; textbox.Text = string.Empty;
} }
public void Contract()
{
this.FadeIn(300);
this.MoveToY(0, 500, Easing.OutQuint);
}
public void Expand()
{
this.FadeOut(200);
this.MoveToY(100, 500, Easing.In);
}
protected virtual ChatLine CreateMessage(Message message) => new StandAloneMessage(message); protected virtual ChatLine CreateMessage(Message message) => new StandAloneMessage(message);
private void channelChanged(ValueChangedEvent<Channel> e) private void channelChanged(ValueChangedEvent<Channel> e)

View File

@ -158,7 +158,11 @@ namespace osu.Game.Overlays.Comments
Font = OsuFont.GetFont(weight: FontWeight.Regular), Font = OsuFont.GetFont(weight: FontWeight.Regular),
}; };
protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) }; protected override Drawable GetDrawableCharacter(char c) => new FallingDownContainer
{
AutoSizeAxes = Axes.Both,
Child = new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) },
};
} }
private class CommitButton : LoadingButton private class CommitButton : LoadingButton

View File

@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OverlayColourProvider colourProvider)
{ {
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
{ {
@ -61,7 +61,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
CornerRadius = corner_radius, CornerRadius = corner_radius,
Children = new Drawable[] Children = new Drawable[]
{ {
new ProfileItemContainer new MostPlayedBeatmapContainer
{ {
Child = new Container Child = new Container
{ {
@ -78,11 +78,14 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
Children = new Drawable[] Children = new Drawable[]
{ {
new MostPlayedBeatmapMetadataContainer(beatmap), new MostPlayedBeatmapMetadataContainer(beatmap),
new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular)) new LinkFlowContainer(t =>
{
t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular);
t.Colour = colourProvider.Foreground1;
})
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
Colour = colours.GreySeafoamLighter
}.With(d => }.With(d =>
{ {
d.AddText("mapped by "); d.AddText("mapped by ");
@ -105,6 +108,16 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
}); });
} }
private class MostPlayedBeatmapContainer : ProfileItemContainer
{
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
IdleColour = colourProvider.Background4;
HoverColour = colourProvider.Background3;
}
}
private class MostPlayedBeatmapMetadataContainer : BeatmapMetadataContainer private class MostPlayedBeatmapMetadataContainer : BeatmapMetadataContainer
{ {
public MostPlayedBeatmapMetadataContainer(BeatmapInfo beatmap) public MostPlayedBeatmapMetadataContainer(BeatmapInfo beatmap)

View File

@ -16,12 +16,33 @@ namespace osu.Game.Overlays.Profile.Sections
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private Color4 idleColour;
private Color4 hoverColour;
private readonly Box background; private readonly Box background;
private readonly Container content; private readonly Container content;
private Color4 idleColour;
protected Color4 IdleColour
{
get => idleColour;
set
{
idleColour = value;
fadeBackgroundColour();
}
}
private Color4 hoverColour;
protected Color4 HoverColour
{
get => hoverColour;
set
{
hoverColour = value;
fadeBackgroundColour();
}
}
public ProfileItemContainer() public ProfileItemContainer()
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
@ -44,20 +65,25 @@ namespace osu.Game.Overlays.Profile.Sections
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider) private void load(OverlayColourProvider colourProvider)
{ {
background.Colour = idleColour = colourProvider.Background3; IdleColour = colourProvider.Background3;
hoverColour = colourProvider.Background2; HoverColour = colourProvider.Background2;
} }
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)
{ {
background.FadeColour(hoverColour, hover_duration, Easing.OutQuint); fadeBackgroundColour(hover_duration);
return base.OnHover(e); return true;
} }
protected override void OnHoverLost(HoverLostEvent e) protected override void OnHoverLost(HoverLostEvent e)
{ {
base.OnHoverLost(e); base.OnHoverLost(e);
background.FadeColour(idleColour, hover_duration, Easing.OutQuint); fadeBackgroundColour(hover_duration);
}
private void fadeBackgroundColour(double fadeDuration = 0)
{
background.FadeColour(IsHovered ? HoverColour : IdleColour, fadeDuration, Easing.OutQuint);
} }
} }
} }

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 System;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
@ -240,7 +241,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
, arrow_move_duration, Easing.Out); , arrow_move_duration, Easing.Out);
} }
private float getRelativeJudgementPosition(double value) => (float)((value / maxHitWindow) + 1) / 2; private float getRelativeJudgementPosition(double value) => Math.Clamp((float)((value / maxHitWindow) + 1) / 2, 0, 1);
private class JudgementLine : CompositeDrawable private class JudgementLine : CompositeDrawable
{ {

View File

@ -184,7 +184,7 @@ namespace osu.Game.Screens.Play
foreach (var mod in Mods.Value.OfType<IApplicableToHealthProcessor>()) foreach (var mod in Mods.Value.OfType<IApplicableToHealthProcessor>())
mod.ApplyToHealthProcessor(HealthProcessor); mod.ApplyToHealthProcessor(HealthProcessor);
BreakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState(); BreakOverlay.IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
} }
private void addUnderlayComponents(Container target) private void addUnderlayComponents(Container target)
@ -229,7 +229,11 @@ namespace osu.Game.Screens.Play
IsPaused = { BindTarget = GameplayClockContainer.IsPaused } IsPaused = { BindTarget = GameplayClockContainer.IsPaused }
}, },
PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } },
KeyCounter = { AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded } }, KeyCounter =
{
AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded },
IsCounting = false
},
RequestSeek = GameplayClockContainer.Seek, RequestSeek = GameplayClockContainer.Seek,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre Origin = Anchor.Centre
@ -286,6 +290,12 @@ namespace osu.Game.Screens.Play
HealthProcessor.IsBreakTime.BindTo(BreakOverlay.IsBreakTime); HealthProcessor.IsBreakTime.BindTo(BreakOverlay.IsBreakTime);
} }
private void onBreakTimeChanged(ValueChangedEvent<bool> isBreakTime)
{
updatePauseOnFocusLostState();
HUDOverlay.KeyCounter.IsCounting = !isBreakTime.NewValue;
}
private void updatePauseOnFocusLostState() => private void updatePauseOnFocusLostState() =>
HUDOverlay.HoldToQuit.PauseOnFocusLost = PauseOnFocusLost HUDOverlay.HoldToQuit.PauseOnFocusLost = PauseOnFocusLost
&& !DrawableRuleset.HasReplayLoaded.Value && !DrawableRuleset.HasReplayLoaded.Value

View File

@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play
{ {
base.Update(); base.Update();
var progress = Math.Max(0, 1 - (gameplayClock.CurrentTime - displayTime) / (fadeOutBeginTime - displayTime)); var progress = fadeOutBeginTime <= displayTime ? 1 : Math.Max(0, 1 - (gameplayClock.CurrentTime - displayTime) / (fadeOutBeginTime - displayTime));
remainingTimeBox.Width = (float)Interpolation.Lerp(remainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1)); remainingTimeBox.Width = (float)Interpolation.Lerp(remainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1));

View File

@ -123,7 +123,7 @@ namespace osu.Game.Screens.Select.Carousel
}, },
starCounter = new StarCounter starCounter = new StarCounter
{ {
CountStars = (float)beatmap.StarDifficulty, Current = (float)beatmap.StarDifficulty,
Scale = new Vector2(0.8f), Scale = new Vector2(0.8f),
} }
} }

View File

@ -231,15 +231,8 @@ namespace osu.Game.Tests.Visual
{ {
private readonly IFrameBasedClock referenceClock; private readonly IFrameBasedClock referenceClock;
private readonly ManualClock clock = new ManualClock();
private bool running; private bool running;
/// <summary>
/// Local offset added to the reference clock to resolve correct time.
/// </summary>
private double offset;
public TrackVirtualManual(IFrameBasedClock referenceClock) public TrackVirtualManual(IFrameBasedClock referenceClock)
{ {
this.referenceClock = referenceClock; this.referenceClock = referenceClock;
@ -248,10 +241,10 @@ namespace osu.Game.Tests.Visual
public override bool Seek(double seek) public override bool Seek(double seek)
{ {
offset = Math.Clamp(seek, 0, Length); accumulated = Math.Clamp(seek, 0, Length);
lastReferenceTime = null; lastReferenceTime = null;
return offset == seek; return accumulated == seek;
} }
public override void Start() public override void Start()
@ -270,9 +263,6 @@ namespace osu.Game.Tests.Visual
if (running) if (running)
{ {
running = false; running = false;
// on stopping, the current value should be transferred out of the clock, as we can no longer rely on
// the referenceClock (which will still be counting time).
offset = clock.CurrentTime;
lastReferenceTime = null; lastReferenceTime = null;
} }
} }
@ -281,7 +271,9 @@ namespace osu.Game.Tests.Visual
private double? lastReferenceTime; private double? lastReferenceTime;
public override double CurrentTime => clock.CurrentTime; private double accumulated;
public override double CurrentTime => Math.Min(accumulated, Length);
protected override void UpdateState() protected override void UpdateState()
{ {
@ -291,18 +283,12 @@ namespace osu.Game.Tests.Visual
{ {
double refTime = referenceClock.CurrentTime; double refTime = referenceClock.CurrentTime;
if (!lastReferenceTime.HasValue) if (lastReferenceTime.HasValue)
{ accumulated += (refTime - lastReferenceTime.Value) * Rate;
// if the clock just started running, the current value should be transferred to the offset
// (to zero the progression of time).
offset -= refTime;
}
lastReferenceTime = refTime; lastReferenceTime = refTime;
} }
clock.CurrentTime = Math.Min((lastReferenceTime ?? 0) + offset, Length);
if (CurrentTime >= Length) if (CurrentTime >= Length)
{ {
Stop(); Stop();

View File

@ -43,6 +43,8 @@ namespace osu.Game.Users.Drawables
set => base.EdgeEffect = value; set => base.EdgeEffect = value;
} }
protected override double LoadDelay => 200;
/// <summary> /// <summary>
/// Whether to show a default guest representation on null user (as opposed to nothing). /// Whether to show a default guest representation on null user (as opposed to nothing).
/// </summary> /// </summary>

View File

@ -23,7 +23,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" />
<PackageReference Include="ppy.osu.Framework" Version="2020.302.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.305.0" />
<PackageReference Include="Sentry" Version="2.1.0" /> <PackageReference Include="Sentry" Version="2.1.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />

View File

@ -71,7 +71,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.302.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2020.305.0" />
</ItemGroup> </ItemGroup>
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. --> <!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
<ItemGroup Label="Transitive Dependencies"> <ItemGroup Label="Transitive Dependencies">
@ -79,7 +79,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2020.302.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.305.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />