1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 08:27:49 +08:00

Merge branch 'master' into fix-perfect-judgements

This commit is contained in:
Dean Herbert 2020-03-10 23:50:57 +09:00 committed by GitHub
commit 66a0f3334d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 1650 additions and 949 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.305.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2020.310.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

View File

@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
typeof(CatcherArea), typeof(CatcherArea),
typeof(CatcherSprite)
}; };
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -1,9 +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;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
@ -22,8 +26,17 @@ namespace osu.Game.Rulesets.Catch.Tests
public void TestHyperDash() public void TestHyperDash()
{ {
AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash); AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash);
AddUntilStep("wait for left hyperdash", () => getCatcher().Scale.X < 0 && getCatcher().HyperDashing);
for (int i = 0; i < 2; i++)
{
AddUntilStep("wait for right hyperdash", () => getCatcher().Scale.X > 0 && getCatcher().HyperDashing);
AddUntilStep("wait for left hyperdash", () => getCatcher().Scale.X < 0 && getCatcher().HyperDashing);
}
} }
private CatcherArea.Catcher getCatcher() => Player.ChildrenOfType<CatcherArea>().First().MovableCatcher;
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap
@ -35,17 +48,40 @@ namespace osu.Game.Rulesets.Catch.Tests
} }
}; };
// Should produce a hyper-dash // Should produce a hyper-dash (edge case test)
beatmap.HitObjects.Add(new Fruit { StartTime = 816, X = 308 / 512f, NewCombo = true }); beatmap.HitObjects.Add(new Fruit { StartTime = 1816, X = 308 / 512f, NewCombo = true });
beatmap.HitObjects.Add(new Fruit { StartTime = 1008, X = 56 / 512f, }); beatmap.HitObjects.Add(new JuiceStream { StartTime = 2008, X = 56 / 512f, });
for (int i = 0; i < 512; i++) double startTime = 3000;
{
if (i % 5 < 3) const float left_x = 0.02f;
beatmap.HitObjects.Add(new Fruit { X = i % 10 < 5 ? 0.02f : 0.98f, StartTime = 2000 + i * 100, NewCombo = i % 8 == 0 }); const float right_x = 0.98f;
}
createObjects(() => new Fruit(), left_x);
createObjects(() => new JuiceStream(), right_x);
createObjects(() => new JuiceStream(), left_x);
createObjects(() => new Fruit(), right_x);
createObjects(() => new Fruit(), left_x);
createObjects(() => new Fruit(), right_x);
createObjects(() => new JuiceStream(), left_x);
return beatmap; return beatmap;
void createObjects(Func<CatchHitObject> createObject, float x)
{
const float spacing = 140;
for (int i = 0; i < 3; i++)
{
var hitObject = createObject();
hitObject.X = x;
hitObject.StartTime = startTime + i * spacing;
beatmap.HitObjects.Add(hitObject);
}
startTime += 700;
}
} }
} }
} }

View File

@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Catch
FruitGrapes, FruitGrapes,
FruitOrange, FruitOrange,
FruitPear, FruitPear,
Droplet Droplet,
CatcherIdle
} }
} }

View File

@ -44,6 +44,10 @@ namespace osu.Game.Rulesets.Catch.Skinning
return new LegacyFruitPiece("fruit-drop") { Scale = new Vector2(0.8f) }; return new LegacyFruitPiece("fruit-drop") { Scale = new Vector2(0.8f) };
break; break;
case CatchSkinComponents.CatcherIdle:
return this.GetAnimation("fruit-catcher-idle", true, true, true) ??
this.GetAnimation("fruit-ryuuta", true, true, true);
} }
return null; return null;

View File

@ -155,7 +155,10 @@ namespace osu.Game.Rulesets.Catch.UI
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
}, },
createCatcherSprite(), createCatcherSprite().With(c =>
{
c.Anchor = Anchor.TopCentre;
})
}; };
} }
@ -205,12 +208,11 @@ namespace osu.Game.Rulesets.Catch.UI
var additive = createCatcherSprite(); var additive = createCatcherSprite();
additive.Anchor = Anchor; additive.Anchor = Anchor;
additive.OriginPosition += new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly.
additive.Position = Position;
additive.Scale = Scale; additive.Scale = Scale;
additive.Colour = HyperDashing ? Color4.Red : Color4.White; additive.Colour = HyperDashing ? Color4.Red : Color4.White;
additive.RelativePositionAxes = RelativePositionAxes;
additive.Blending = BlendingParameters.Additive; additive.Blending = BlendingParameters.Additive;
additive.RelativePositionAxes = RelativePositionAxes;
additive.Position = Position;
AdditiveTarget.Add(additive); AdditiveTarget.Add(additive);
@ -270,6 +272,10 @@ namespace osu.Game.Rulesets.Catch.UI
catchObjectPosition >= catcherPosition - halfCatchWidth && catchObjectPosition >= catcherPosition - halfCatchWidth &&
catchObjectPosition <= catcherPosition + halfCatchWidth; catchObjectPosition <= catcherPosition + halfCatchWidth;
// only update hyperdash state if we are catching a fruit.
// exceptions are Droplets and JuiceStreams.
if (!(fruit is Fruit)) return validCatch;
if (validCatch && fruit.HyperDash) if (validCatch && fruit.HyperDash)
{ {
var target = fruit.HyperDashTarget; var target = fruit.HyperDashTarget;

View File

@ -3,31 +3,35 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Catch.UI namespace osu.Game.Rulesets.Catch.UI
{ {
public class CatcherSprite : CompositeDrawable public class CatcherSprite : SkinnableDrawable
{ {
protected override bool ApplySizeRestrictionsToDefault => true;
public CatcherSprite() public CatcherSprite()
: base(new CatchSkinComponent(CatchSkinComponents.CatcherIdle), _ =>
new DefaultCatcherSprite(), confineMode: ConfineMode.ScaleDownToFit)
{ {
RelativeSizeAxes = Axes.None;
Size = new Vector2(CatcherArea.CATCHER_SIZE); Size = new Vector2(CatcherArea.CATCHER_SIZE);
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling. // Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
OriginPosition = new Vector2(-0.02f, 0.06f) * CatcherArea.CATCHER_SIZE; OriginPosition = new Vector2(0.5f, 0.06f) * CatcherArea.CATCHER_SIZE;
} }
[BackgroundDependencyLoader] private class DefaultCatcherSprite : Sprite
private void load()
{ {
InternalChild = new SkinnableSprite("Gameplay/catch/fruit-catcher-idle", confineMode: ConfineMode.ScaleDownToFit) [BackgroundDependencyLoader]
private void load(TextureStore textures)
{ {
RelativeSizeAxes = Axes.Both, Texture = textures.Get("Gameplay/catch/fruit-catcher-idle");
Anchor = Anchor.TopCentre, }
Origin = Anchor.TopCentre,
};
} }
} }
} }

View File

@ -0,0 +1,101 @@
// 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.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Replays;
using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Tests.Visual;
using osu.Game.Users;
using osuTK;
namespace osu.Game.Rulesets.Osu.Tests
{
public class TestSceneMissHitWindowJudgements : ModTestScene
{
public TestSceneMissHitWindowJudgements()
: base(new OsuRuleset())
{
}
[Test]
public void TestMissViaEarlyHit()
{
var beatmap = new Beatmap
{
HitObjects = { new HitCircle { Position = new Vector2(256, 192) } }
};
var hitWindows = new OsuHitWindows();
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
CreateModTest(new ModTestData
{
Autoplay = false,
Mod = new TestAutoMod(),
Beatmap = new Beatmap
{
HitObjects = { new HitCircle { Position = new Vector2(256, 192) } }
},
PassCondition = () => Player.Results.Count > 0 && Player.Results[0].TimeOffset < -hitWindows.WindowFor(HitResult.Meh) && Player.Results[0].Type == HitResult.Miss
});
}
[Test]
public void TestMissViaNotHitting()
{
var beatmap = new Beatmap
{
HitObjects = { new HitCircle { Position = new Vector2(256, 192) } }
};
var hitWindows = new OsuHitWindows();
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
CreateModTest(new ModTestData
{
Autoplay = false,
Beatmap = beatmap,
PassCondition = () => Player.Results.Count > 0 && Player.Results[0].TimeOffset >= hitWindows.WindowFor(HitResult.Meh) && Player.Results[0].Type == HitResult.Miss
});
}
private class TestAutoMod : OsuModAutoplay
{
public override Score CreateReplayScore(IBeatmap beatmap) => new Score
{
ScoreInfo = new ScoreInfo { User = new User { Username = "Autoplay" } },
Replay = new MissingAutoGenerator(beatmap).Generate()
};
}
private class MissingAutoGenerator : OsuAutoGeneratorBase
{
public new OsuBeatmap Beatmap => (OsuBeatmap)base.Beatmap;
public MissingAutoGenerator(IBeatmap beatmap)
: base(beatmap)
{
}
public override Replay Generate()
{
AddFrameToReplay(new OsuReplayFrame(-100000, new Vector2(256, 500)));
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 1500, new Vector2(256, 500)));
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 1500, new Vector2(256, 500)));
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 450, Beatmap.HitObjects[0].StackedPosition));
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 350, Beatmap.HitObjects[0].StackedPosition, OsuAction.LeftButton));
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 325, Beatmap.HitObjects[0].StackedPosition));
return Replay;
}
}
}
}

View File

@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
new DifficultyRange(HitResult.Great, 80, 50, 20), new DifficultyRange(HitResult.Great, 80, 50, 20),
new DifficultyRange(HitResult.Good, 140, 100, 60), new DifficultyRange(HitResult.Good, 140, 100, 60),
new DifficultyRange(HitResult.Meh, 200, 150, 100), new DifficultyRange(HitResult.Meh, 200, 150, 100),
new DifficultyRange(HitResult.Miss, 200, 200, 200), new DifficultyRange(HitResult.Miss, 400, 400, 400),
}; };
public override bool IsHitResultAllowed(HitResult result) public override bool IsHitResultAllowed(HitResult result)

View File

@ -99,7 +99,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
var storyboard = decoder.Decode(stream); var storyboard = decoder.Decode(stream);
StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3); StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3);
Assert.AreEqual(123456, ((StoryboardSprite)background.Elements.Single()).InitialPosition.X); Assert.AreEqual(3456, ((StoryboardSprite)background.Elements.Single()).InitialPosition.X);
} }
} }
} }

View File

@ -1,5 +1,5 @@
[Variables] [Variables]
$var=1234 $var=34
[Events] [Events]
Sprite,Background,TopCentre,"img.jpg",$var56,240 Sprite,Background,TopCentre,"img.jpg",$var56,240

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,125 @@
// 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.Bindables;
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, TeamColour.Red, new Bindable<int?>(2), 6)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
});
}
}
}

View File

@ -1,16 +1,31 @@
// 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.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Tournament.Components; using osu.Game.Tournament.Components;
using osu.Game.Tournament.Screens;
using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Gameplay;
using osu.Game.Tournament.Screens.Gameplay.Components;
namespace osu.Game.Tournament.Tests.Screens namespace osu.Game.Tournament.Tests.Screens
{ {
public class TestSceneGameplayScreen : TournamentTestScene public class TestSceneGameplayScreen : TournamentTestScene
{ {
[Cached] [Cached]
private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay(); private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay { Width = 0.5f };
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(TeamScore),
typeof(TeamScoreDisplay),
typeof(TeamDisplay),
typeof(MatchHeader),
typeof(MatchScoreDisplay),
typeof(BeatmapInfoScreen),
typeof(SongBar),
};
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()

View File

@ -2,6 +2,8 @@
// 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.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Screens.Schedule; using osu.Game.Tournament.Screens.Schedule;
namespace osu.Game.Tournament.Tests.Screens namespace osu.Game.Tournament.Tests.Screens
@ -11,6 +13,7 @@ namespace osu.Game.Tournament.Tests.Screens
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Add(new TourneyVideo("main") { RelativeSizeAxes = Axes.Both });
Add(new ScheduleScreen()); Add(new ScheduleScreen());
} }
} }

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

@ -4,10 +4,8 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
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.Effects;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -24,6 +22,8 @@ namespace osu.Game.Tournament.Components
{ {
private BeatmapInfo beatmap; private BeatmapInfo beatmap;
private const float height = 145;
[Resolved] [Resolved]
private IBindable<RulesetInfo> ruleset { get; set; } private IBindable<RulesetInfo> ruleset { get; set; }
@ -52,15 +52,7 @@ namespace osu.Game.Tournament.Components
} }
} }
private Container panelContents; private FillFlowContainer flow;
private Container innerPanel;
private Container outerPanel;
private TournamentBeatmapPanel panel;
private float panelWidth => expanded ? 0.6f : 1;
private const float main_width = 0.97f;
private const float inner_panel_width = 0.7f;
private bool expanded; private bool expanded;
@ -70,86 +62,27 @@ namespace osu.Game.Tournament.Components
set set
{ {
expanded = value; expanded = value;
panel?.ResizeWidthTo(panelWidth, 800, Easing.OutQuint); flow.Direction = expanded ? FillDirection.Full : FillDirection.Vertical;
if (expanded)
{
innerPanel.ResizeWidthTo(inner_panel_width, 800, Easing.OutQuint);
outerPanel.ResizeWidthTo(main_width, 800, Easing.OutQuint);
}
else
{
innerPanel.ResizeWidthTo(1, 800, Easing.OutQuint);
outerPanel.ResizeWidthTo(0.25f, 800, Easing.OutQuint);
}
} }
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
outerPanel = new Container flow = new FillFlowContainer
{ {
Masking = true,
EdgeEffect = new EdgeEffectParameters
{
Colour = Color4.Black.Opacity(0.2f),
Type = EdgeEffectType.Shadow,
Radius = 5,
},
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
LayoutDuration = 500,
LayoutEasing = Easing.OutQuint,
Direction = FillDirection.Full,
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
RelativePositionAxes = Axes.X,
X = -(1 - main_width) / 2,
Y = -10,
Width = main_width,
Height = TournamentBeatmapPanel.HEIGHT,
CornerRadius = TournamentBeatmapPanel.HEIGHT / 2,
CornerExponent = 2,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(0.93f),
},
new OsuLogo
{
Triangles = false,
Colour = OsuColour.Gray(0.33f),
Scale = new Vector2(0.08f),
Margin = new MarginPadding(50),
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
},
innerPanel = new Container
{
Masking = true,
CornerRadius = TournamentBeatmapPanel.HEIGHT / 2,
CornerExponent = 2,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Width = inner_panel_width,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(0.86f),
},
panelContents = new Container
{
RelativeSizeAxes = Axes.Both,
}
}
}
}
} }
}; };
@ -160,7 +93,7 @@ namespace osu.Game.Tournament.Components
{ {
if (beatmap == null) if (beatmap == null)
{ {
panelContents.Clear(); flow.Clear();
return; return;
} }
@ -219,34 +152,86 @@ namespace osu.Game.Tournament.Components
break; break;
} }
panelContents.Children = new Drawable[] flow.Children = new Drawable[]
{ {
new DiffPiece(("Length", TimeSpan.FromMilliseconds(length).ToString(@"mm\:ss"))) new Container
{ {
Anchor = Anchor.CentreLeft, RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomLeft, Height = height / 2,
Width = 0.5f,
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Children = new Drawable[]
{
new GridContainer
{
RelativeSizeAxes = Axes.Both,
Content = new[]
{
new Drawable[]
{
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new DiffPiece(stats),
new DiffPiece(("Star Rating", $"{beatmap.StarDifficulty:0.#}{srExtra}"))
}
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new DiffPiece(("Length", TimeSpan.FromMilliseconds(length).ToString(@"mm\:ss"))),
new DiffPiece(("BPM", $"{bpm:0.#}"))
}
},
new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
{
Colour = Color4.Black,
RelativeSizeAxes = Axes.Both,
Alpha = 0.1f,
},
new OsuLogo
{
Triangles = false,
Scale = new Vector2(0.08f),
Margin = new MarginPadding(50),
X = -10,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
},
}
},
},
}
}
}
}, },
new DiffPiece(("BPM", $"{bpm:0.#}")) new TournamentBeatmapPanel(beatmap)
{ {
Anchor = Anchor.CentreLeft, RelativeSizeAxes = Axes.X,
Origin = Anchor.TopLeft Width = 0.5f,
}, Height = height / 2,
new DiffPiece(stats) Anchor = Anchor.BottomRight,
{ Origin = Anchor.BottomRight,
Anchor = Anchor.CentreRight,
Origin = Anchor.BottomRight
},
new DiffPiece(("Star Rating", $"{beatmap.StarDifficulty:0.#}{srExtra}"))
{
Anchor = Anchor.CentreRight,
Origin = Anchor.TopRight
},
panel = new TournamentBeatmapPanel(beatmap)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(panelWidth, 1)
} }
}; };
} }
@ -258,10 +243,9 @@ namespace osu.Game.Tournament.Components
Margin = new MarginPadding { Horizontal = 15, Vertical = 1 }; Margin = new MarginPadding { Horizontal = 15, Vertical = 1 };
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
static void cp(SpriteText s, Color4 colour) static void cp(SpriteText s, bool bold)
{ {
s.Colour = colour; s.Font = OsuFont.Torus.With(weight: bold ? FontWeight.Bold : FontWeight.Regular, size: 15);
s.Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 15);
} }
for (var i = 0; i < tuples.Length; i++) for (var i = 0; i < tuples.Length; i++)
@ -272,14 +256,14 @@ namespace osu.Game.Tournament.Components
{ {
AddText(" / ", s => AddText(" / ", s =>
{ {
cp(s, OsuColour.Gray(0.33f)); cp(s, false);
s.Spacing = new Vector2(-2, 0); s.Spacing = new Vector2(-2, 0);
}); });
} }
AddText(new TournamentSpriteText { Text = heading }, s => cp(s, OsuColour.Gray(0.33f))); AddText(new TournamentSpriteText { Text = heading }, s => cp(s, false));
AddText(" ", s => cp(s, OsuColour.Gray(0.33f))); AddText(" ", s => cp(s, false));
AddText(new TournamentSpriteText { Text = content }, s => cp(s, OsuColour.Gray(0.5f))); AddText(new TournamentSpriteText { Text = content }, s => cp(s, true));
} }
} }
} }

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,14 @@ namespace osu.Game.Tournament.Components
new FillFlowContainer new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Anchor = Anchor.TopCentre, Anchor = Anchor.CentreLeft,
Origin = Anchor.TopCentre, Origin = Anchor.CentreLeft,
Padding = new MarginPadding(vertical_padding), Padding = new MarginPadding(15),
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 +84,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[]
{ {
@ -137,8 +130,8 @@ namespace osu.Game.Tournament.Components
Texture = textures.Get($"mods/{mods}"), Texture = textures.Get($"mods/{mods}"),
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
Margin = new MarginPadding(20), Margin = new MarginPadding(10),
Scale = new Vector2(0.5f) Scale = new Vector2(0.8f)
}); });
} }
} }
@ -170,16 +163,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

@ -9,8 +9,6 @@ using osu.Game.Online.Chat;
using osu.Game.Overlays.Chat; using osu.Game.Overlays.Chat;
using osu.Game.Tournament.IPC; using osu.Game.Tournament.IPC;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tournament.Components namespace osu.Game.Tournament.Components
{ {
@ -23,11 +21,11 @@ namespace osu.Game.Tournament.Components
public TournamentMatchChatDisplay() public TournamentMatchChatDisplay()
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Y = 100; Height = 144;
Size = new Vector2(0.45f, 112); Anchor = Anchor.BottomLeft;
Margin = new MarginPadding(10); Origin = Anchor.BottomLeft;
Anchor = Anchor.BottomCentre;
Origin = Anchor.BottomCentre; CornerRadius = 0;
} }
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
@ -66,6 +64,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
@ -75,19 +77,15 @@ namespace osu.Game.Tournament.Components
{ {
} }
[BackgroundDependencyLoader]
private void load(LadderInfo info) private void load(LadderInfo info)
{ {
//if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == Message.Sender.Id)) // if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == Message.Sender.Id))
// ColourBox.Colour = red; // SenderText.Colour = TournamentGame.COLOUR_RED;
//else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == Message.Sender.Id)) // else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == Message.Sender.Id))
// ColourBox.Colour = blue; // SenderText.Colour = TournamentGame.COLOUR_BLUE;
//else if (Message.Sender.Colour != null) // else if (Message.Sender.Colour != null)
// SenderText.Colour = ColourBox.Colour = OsuColour.FromHex(Message.Sender.Colour); // SenderText.Colour = ColourBox.Colour = OsuColour.FromHex(Message.Sender.Colour);
} }
private readonly Color4 red = new Color4(186, 0, 18, 255);
private readonly Color4 blue = new Color4(17, 136, 170, 255);
} }
} }
} }

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

@ -38,7 +38,8 @@ namespace osu.Game.Tournament.Components
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit, FillMode = FillMode.Fit,
Clock = new FramedClock(manualClock = new ManualClock()) Clock = new FramedClock(manualClock = new ManualClock()),
Loop = loop,
}; };
} }
else if (drawFallbackGradient) else if (drawFallbackGradient)
@ -51,15 +52,24 @@ namespace osu.Game.Tournament.Components
} }
} }
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

@ -21,6 +21,7 @@ namespace osu.Game.Tournament.Screens
{ {
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
Depth = float.MinValue,
}); });
} }

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

@ -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;

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>

View File

@ -5,21 +5,28 @@ 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.Components;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osu.Game.Tournament.Screens.Showcase;
using osuTK; 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
{ {
public class MatchHeader : Container public class MatchHeader : Container
{ {
private TeamScoreDisplay teamDisplay1;
private TeamScoreDisplay teamDisplay2;
public bool ShowScores
{
set
{
teamDisplay1.ShowScore = value;
teamDisplay2.ShowScore = value;
}
}
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
@ -27,200 +34,108 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
Height = 95; Height = 95;
Children = new Drawable[] Children = new Drawable[]
{ {
new TournamentLogo(), new FillFlowContainer
new RoundDisplay
{ {
Y = 5, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.BottomCentre, Direction = FillDirection.Vertical,
Origin = Anchor.TopCentre, Spacing = new Vector2(5),
Children = new Drawable[]
{
new DrawableTournamentTitleText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(1.2f)
},
new RoundDisplay
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(0.4f)
},
}
}, },
new TeamScoreDisplay(TeamColour.Red) teamDisplay1 = new TeamScoreDisplay(TeamColour.Red)
{ {
Anchor = Anchor.TopLeft, Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft, Origin = Anchor.TopLeft,
}, },
new TeamScoreDisplay(TeamColour.Blue) teamDisplay2 = new TeamScoreDisplay(TeamColour.Blue)
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
}, },
}; };
} }
}
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?>();
private TeamDisplay teamDisplay;
public bool ShowScore { set => teamDisplay.ShowScore = value; }
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>(); AutoSizeAxes = Axes.X;
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>(); }
public TeamScoreDisplay(TeamColour teamColour) [BackgroundDependencyLoader]
private void load(LadderInfo ladder)
{
currentMatch.BindTo(ladder.CurrentMatch);
currentMatch.BindValueChanged(matchChanged, true);
}
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
{
currentTeamScore.UnbindBindings();
currentTeam.UnbindBindings();
if (match.NewValue != null)
{ {
this.teamColour = teamColour;
RelativeSizeAxes = Axes.Y;
Width = 300;
}
[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); currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1Score : match.NewValue.Team2Score);
currentTeam.UnbindBindings();
currentTeam.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1 : match.NewValue.Team2); 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) // team may change to same team, which means score is not in a good state.
{ // thus we handle this manually.
switch (e.Button) teamChanged(currentTeam.Value);
{
case MouseButton.Left:
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 protected override bool OnMouseDown(MouseDownEvent e)
{ {
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>(); switch (e.Button)
private readonly StarCounter counter;
public TeamScore(Bindable<int?> score, bool flip, int count)
{ {
var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft; case MouseButton.Left:
if (currentTeamScore.Value < currentMatch.Value.PointsToWin)
currentTeamScore.Value++;
return true;
Anchor = anchor; case MouseButton.Right:
Origin = anchor; if (currentTeamScore.Value > 0)
currentTeamScore.Value--;
InternalChild = counter = new StarCounter(count) return true;
{
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; return base.OnMouseDown(e);
} }
private class TeamDisplay : DrawableTournamentTeam private void teamChanged(TournamentTeam team)
{ {
public TeamDisplay(TournamentTeam team, Color4 colour, bool flip) InternalChildren = new Drawable[]
: base(team)
{ {
RelativeSizeAxes = Axes.Both; teamDisplay = new TeamDisplay(team, teamColour, currentTeamScore, currentMatch.Value?.PointsToWin ?? 0),
};
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

@ -11,16 +11,12 @@ using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Tournament.IPC; using osu.Game.Tournament.IPC;
using osu.Game.Tournament.Models; using osu.Game.Tournament.Models;
using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.Gameplay.Components namespace osu.Game.Tournament.Screens.Gameplay.Components
{ {
public class MatchScoreDisplay : CompositeDrawable public class MatchScoreDisplay : CompositeDrawable
{ {
private readonly Color4 red = new Color4(186, 0, 18, 255); private const float bar_height = 18;
private readonly Color4 blue = new Color4(17, 136, 170, 255);
private const float bar_height = 20;
private readonly BindableInt score1 = new BindableInt(); private readonly BindableInt score1 = new BindableInt();
private readonly BindableInt score2 = new BindableInt(); private readonly BindableInt score2 = new BindableInt();
@ -28,45 +24,63 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
private readonly MatchScoreCounter score1Text; private readonly MatchScoreCounter score1Text;
private readonly MatchScoreCounter score2Text; private readonly MatchScoreCounter score2Text;
private readonly Circle score1Bar; private readonly Drawable score1Bar;
private readonly Circle score2Bar; private readonly Drawable score2Bar;
public MatchScoreDisplay() public MatchScoreDisplay()
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
InternalChildren = new Drawable[] InternalChildren = new[]
{ {
score1Bar = new Circle new Box
{
Name = "top bar red (static)",
RelativeSizeAxes = Axes.X,
Height = bar_height / 4,
Width = 0.5f,
Colour = TournamentGame.COLOUR_RED,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopRight
},
new Box
{
Name = "top bar blue (static)",
RelativeSizeAxes = Axes.X,
Height = bar_height / 4,
Width = 0.5f,
Colour = TournamentGame.COLOUR_BLUE,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopLeft
},
score1Bar = new Box
{ {
Name = "top bar red", Name = "top bar red",
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = bar_height, Height = bar_height,
Width = 0, Width = 0,
Colour = red, Colour = TournamentGame.COLOUR_RED,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopRight Origin = Anchor.TopRight
}, },
score1Text = new MatchScoreCounter score1Text = new MatchScoreCounter
{ {
Colour = red,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre Origin = Anchor.TopCentre
}, },
score2Bar = new Circle score2Bar = new Box
{ {
Name = "top bar blue", Name = "top bar blue",
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = bar_height, Height = bar_height,
Width = 0, Width = 0,
Colour = blue, Colour = TournamentGame.COLOUR_BLUE,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopLeft Origin = Anchor.TopLeft
}, },
score2Text = new MatchScoreCounter score2Text = new MatchScoreCounter
{ {
Colour = blue,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre Origin = Anchor.TopCentre
}, },
@ -103,10 +117,9 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint);
} }
protected override void Update() protected override void UpdateAfterChildren()
{ {
base.Update(); base.UpdateAfterChildren();
score1Text.X = -Math.Max(5 + score1Text.DrawWidth / 2, score1Bar.DrawWidth); score1Text.X = -Math.Max(5 + score1Text.DrawWidth / 2, score1Bar.DrawWidth);
score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth); score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth);
} }
@ -115,7 +128,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
{ {
public MatchScoreCounter() public MatchScoreCounter()
{ {
Margin = new MarginPadding { Top = bar_height + 5, Horizontal = 10 }; Margin = new MarginPadding { Top = bar_height, Horizontal = 10 };
Winning = false; Winning = false;
} }
@ -123,8 +136,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
public bool Winning public bool Winning
{ {
set => DisplayedCountSpriteText.Font = value set => DisplayedCountSpriteText.Font = value
? OsuFont.Torus.With(weight: FontWeight.Regular, size: 60) ? OsuFont.Torus.With(weight: FontWeight.Bold, size: 50)
: OsuFont.Torus.With(weight: FontWeight.Light, size: 40); : OsuFont.Torus.With(weight: FontWeight.Regular, size: 40);
} }
} }
} }

View File

@ -0,0 +1,25 @@
// 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.Game.Tournament.Components;
using osu.Game.Tournament.Models;
namespace osu.Game.Tournament.Screens.Gameplay.Components
{
public class RoundDisplay : TournamentSpriteTextWithBackground
{
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
[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,91 @@
// 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.Tournament.Components;
using osu.Game.Tournament.Models;
using osuTK;
namespace osu.Game.Tournament.Screens.Gameplay.Components
{
public class TeamDisplay : DrawableTournamentTeam
{
private readonly TeamScore score;
public bool ShowScore { set => score.FadeTo(value ? 1 : 0, 200); }
public TeamDisplay(TournamentTeam team, TeamColour colour, Bindable<int?> currentTeamScore, int pointsToWin)
: base(team)
{
AutoSizeAxes = Axes.Both;
bool flip = colour == TeamColour.Red;
var anchor = flip ? Anchor.TopLeft : Anchor.TopRight;
Flag.RelativeSizeAxes = Axes.None;
Flag.Size = new Vector2(60, 40);
Flag.Origin = anchor;
Flag.Anchor = anchor;
Margin = new MarginPadding(20);
InternalChild = new Container
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(5),
Children = new Drawable[]
{
Flag,
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Origin = anchor,
Anchor = anchor,
Spacing = new Vector2(5),
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(5),
Children = new Drawable[]
{
new DrawableTeamHeader(colour)
{
Scale = new Vector2(0.75f),
Origin = anchor,
Anchor = anchor,
},
score = new TeamScore(currentTeamScore, colour, pointsToWin)
{
Origin = anchor,
Anchor = anchor,
}
}
},
new TournamentSpriteTextWithBackground(team?.FullName.Value ?? "???")
{
Scale = new Vector2(0.5f),
Origin = anchor,
Anchor = anchor,
},
}
},
}
},
}
};
}
}
}

View File

@ -0,0 +1,103 @@
// 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.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Tournament.Models;
using osuTK;
using osuTK.Graphics;
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, TeamColour colour, int count)
{
bool flip = colour == TeamColour.Blue;
var anchor = flip ? Anchor.TopRight : Anchor.TopLeft;
AutoSizeAxes = Axes.Both;
InternalChild = counter = new TeamScoreStarCounter(count)
{
Anchor = anchor,
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;
public class TeamScoreStarCounter : StarCounter
{
public TeamScoreStarCounter(int count)
: base(count)
{
}
public override Star CreateStar() => new LightSquare();
public class LightSquare : Star
{
private readonly Box box;
public LightSquare()
{
Size = new Vector2(22.5f);
InternalChildren = new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderColour = OsuColour.Gray(0.5f),
BorderThickness = 3,
Children = new Drawable[]
{
new Box
{
Colour = Color4.Transparent,
RelativeSizeAxes = Axes.Both,
AlwaysPresent = true,
},
}
},
box = new Box
{
Colour = OsuColour.FromHex("#FFE8AD"),
RelativeSizeAxes = Axes.Both,
},
};
Masking = true;
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Glow,
Colour = OsuColour.FromHex("#FFE8AD").Opacity(0.1f),
Hollow = true,
Radius = 20,
Roundness = 10,
};
}
public override void DisplayAt(float scale)
{
box.FadeTo(scale, 500, Easing.OutQuint);
FadeEdgeEffectTo(0.2f * scale, 500, Easing.OutQuint);
}
}
}
}
}

View File

@ -15,7 +15,6 @@ using osu.Game.Tournament.Models;
using osu.Game.Tournament.Screens.Gameplay.Components; using osu.Game.Tournament.Screens.Gameplay.Components;
using osu.Game.Tournament.Screens.MapPool; using osu.Game.Tournament.Screens.MapPool;
using osu.Game.Tournament.Screens.TeamWin; using osu.Game.Tournament.Screens.TeamWin;
using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.Gameplay namespace osu.Game.Tournament.Screens.Gameplay
@ -30,9 +29,6 @@ namespace osu.Game.Tournament.Screens.Gameplay
private OsuButton warmupButton; private OsuButton warmupButton;
private MatchIPCInfo ipc; private MatchIPCInfo ipc;
private readonly Color4 red = new Color4(186, 0, 18, 255);
private readonly Color4 blue = new Color4(17, 136, 170, 255);
[Resolved(canBeNull: true)] [Resolved(canBeNull: true)]
private TournamentSceneManager sceneManager { get; set; } private TournamentSceneManager sceneManager { get; set; }
@ -51,14 +47,14 @@ namespace osu.Game.Tournament.Screens.Gameplay
Loop = true, Loop = true,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}, },
new MatchHeader(), header = new MatchHeader(),
new Container new Container
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Y = 5, Y = 110,
Anchor = Anchor.Centre, Anchor = Anchor.TopCentre,
Origin = Anchor.Centre, Origin = Anchor.TopCentre,
Children = new Drawable[] Children = new Drawable[]
{ {
new Box new Box
@ -66,44 +62,18 @@ namespace osu.Game.Tournament.Screens.Gameplay
// chroma key area for stable gameplay // chroma key area for stable gameplay
Name = "chroma", Name = "chroma",
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Height = 512, Height = 512,
Colour = new Color4(0, 255, 0, 255), Colour = new Color4(0, 255, 0, 255),
}, },
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Y = -4,
Children = new Drawable[]
{
new Circle
{
Name = "top bar red",
RelativeSizeAxes = Axes.X,
Height = 8,
Width = 0.5f,
Colour = red,
},
new Circle
{
Name = "top bar blue",
RelativeSizeAxes = Axes.X,
Height = 8,
Width = 0.5f,
Colour = blue,
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
},
}
},
} }
}, },
scoreDisplay = new MatchScoreDisplay scoreDisplay = new MatchScoreDisplay
{ {
Y = -60, Y = -147,
Scale = new Vector2(0.8f),
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre, Origin = Anchor.TopCentre,
}, },
new ControlPanel new ControlPanel
{ {
@ -136,13 +106,18 @@ namespace osu.Game.Tournament.Screens.Gameplay
currentMatch.BindTo(ladder.CurrentMatch); currentMatch.BindTo(ladder.CurrentMatch);
warmup.BindValueChanged(w => warmupButton.Alpha = !w.NewValue ? 0.5f : 1, true); warmup.BindValueChanged(w =>
{
warmupButton.Alpha = !w.NewValue ? 0.5f : 1;
header.ShowScores = !w.NewValue;
}, true);
} }
private ScheduledDelegate scheduledOperation; private ScheduledDelegate scheduledOperation;
private MatchScoreDisplay scoreDisplay; private MatchScoreDisplay scoreDisplay;
private TourneyState lastState; private TourneyState lastState;
private MatchHeader header;
private void stateChanged(ValueChangedEvent<TourneyState> state) private void stateChanged(ValueChangedEvent<TourneyState> state)
{ {
@ -162,7 +137,7 @@ namespace osu.Game.Tournament.Screens.Gameplay
void expand() void expand()
{ {
chat?.Expand(); chat?.Contract();
using (BeginDelayedSequence(300, true)) using (BeginDelayedSequence(300, true))
{ {
@ -176,7 +151,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)
@ -203,7 +178,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

@ -23,7 +23,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
private readonly bool editor; private readonly bool editor;
protected readonly FillFlowContainer<DrawableMatchTeam> Flow; protected readonly FillFlowContainer<DrawableMatchTeam> Flow;
private readonly Drawable selectionBox; private readonly Drawable selectionBox;
private readonly Drawable currentMatchSelectionBox; protected readonly Drawable CurrentMatchSelectionBox;
private Bindable<TournamentMatch> globalSelection; private Bindable<TournamentMatch> globalSelection;
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
@ -45,9 +45,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,
@ -55,16 +53,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
Colour = Color4.YellowGreen, Colour = Color4.YellowGreen,
Child = new Box { RelativeSizeAxes = Axes.Both } Child = new Box { RelativeSizeAxes = Axes.Both }
}, },
currentMatchSelectionBox = new Container CurrentMatchSelectionBox = new Container
{ {
CornerRadius = 5, Scale = new Vector2(1.05f, 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 = Color4.White,
Child = new Box { RelativeSizeAxes = Axes.Both } Child = new Box { RelativeSizeAxes = Axes.Both }
}, },
Flow = new FillFlowContainer<DrawableMatchTeam> Flow = new FillFlowContainer<DrawableMatchTeam>
@ -128,9 +124,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
private void updateCurrentMatch() private void updateCurrentMatch()
{ {
if (Match.Current.Value) if (Match.Current.Value)
currentMatchSelectionBox.Show(); CurrentMatchSelectionBox.Show();
else else
currentMatchSelectionBox.Hide(); CurrentMatchSelectionBox.Hide();
} }
private bool selected; private bool selected;

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;
@ -47,6 +47,12 @@ namespace osu.Game.Tournament.Screens.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 public class ScheduleScreen : TournamentScreen // IProvidesVideo
{ {
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>(); private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
private Container mainContainer; private Container mainContainer;
@ -38,10 +38,63 @@ namespace osu.Game.Tournament.Screens.Schedule
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Loop = true, Loop = true,
}, },
mainContainer = new Container new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
} Padding = new MarginPadding(100) { Bottom = 50 },
Children = new Drawable[]
{
new GridContainer
{
RelativeSizeAxes = Axes.Both,
RowDimensions = new[]
{
new Dimension(GridSizeMode.AutoSize),
new Dimension(),
},
Content = new[]
{
new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new DrawableTournamentTitleText(),
new Container
{
Margin = new MarginPadding { Top = 40 },
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
{
Colour = Color4.White,
Size = new Vector2(50, 10),
},
new TournamentSpriteTextWithBackground("Schedule")
{
X = 60,
Scale = new Vector2(0.8f)
}
}
},
}
},
},
new Drawable[]
{
mainContainer = new Container
{
RelativeSizeAxes = Axes.Both,
}
}
}
}
}
},
}; };
currentMatch.BindValueChanged(matchChanged); currentMatch.BindValueChanged(matchChanged);
@ -62,7 +115,7 @@ namespace osu.Game.Tournament.Screens.Schedule
.SelectMany(m => m.ConditionalMatches.Where(cp => m.Acronyms.TrueForAll(a => cp.Acronyms.Contains(a)))); .SelectMany(m => m.ConditionalMatches.Where(cp => m.Acronyms.TrueForAll(a => cp.Acronyms.Contains(a))));
upcoming = upcoming.Concat(conditionals); upcoming = upcoming.Concat(conditionals);
upcoming = upcoming.OrderBy(p => p.Date.Value).Take(12); upcoming = upcoming.OrderBy(p => p.Date.Value).Take(8);
mainContainer.Child = new FillFlowContainer mainContainer.Child = new FillFlowContainer
{ {
@ -73,7 +126,7 @@ namespace osu.Game.Tournament.Screens.Schedule
new Container new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Height = 0.65f, Height = 0.74f,
Child = new FillFlowContainer Child = new FillFlowContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -91,7 +144,7 @@ namespace osu.Game.Tournament.Screens.Schedule
.Take(8) .Take(8)
.Select(p => new ScheduleMatch(p)) .Select(p => new ScheduleMatch(p))
}, },
new ScheduleContainer("match overview") new ScheduleContainer("upcoming matches")
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Width = 0.6f, Width = 0.6f,
@ -100,26 +153,57 @@ namespace osu.Game.Tournament.Screens.Schedule
} }
} }
}, },
new ScheduleContainer("current match") new ScheduleContainer("coming up next")
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Height = 0.25f, Height = 0.25f,
Children = new Drawable[] Children = new Drawable[]
{ {
new TournamentSpriteText new FillFlowContainer
{ {
Margin = new MarginPadding { Left = -10, Bottom = 10, Top = -5 }, AutoSizeAxes = Axes.Both,
Spacing = new Vector2(10, 0), Direction = FillDirection.Horizontal,
Text = match.NewValue.Round.Value?.Name.Value, Spacing = new Vector2(30),
Colour = Color4.Black, Children = new Drawable[]
Font = OsuFont.Torus.With(size: 20) {
}, new ScheduleMatch(match.NewValue, false)
new ScheduleMatch(match.NewValue, false), {
new TournamentSpriteText Anchor = Anchor.CentreLeft,
{ Origin = Anchor.CentreLeft,
Text = "Start Time " + match.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), },
Colour = Color4.Black, new TournamentSpriteTextWithBackground(match.NewValue.Round.Value?.Name.Value)
Font = OsuFont.Torus.With(size: 20) {
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Scale = new Vector2(0.5f)
},
new TournamentSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Text = match.NewValue.Team1.Value?.FullName + " vs " + match.NewValue.Team2.Value?.FullName,
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.SemiBold)
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Children = new Drawable[]
{
new TournamentSpriteText
{
Text = "Starting ",
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.Regular)
},
new DrawableDate(match.NewValue.Date.Value)
{
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.Regular)
}
}
},
}
}, },
} }
} }
@ -134,6 +218,10 @@ namespace osu.Game.Tournament.Screens.Schedule
{ {
Flow.Direction = FillDirection.Horizontal; Flow.Direction = FillDirection.Horizontal;
Scale = new Vector2(0.8f);
CurrentMatchSelectionBox.Scale = new Vector2(1.02f, 1.15f);
bool conditional = match is ConditionalTournamentMatch; bool conditional = match is ConditionalTournamentMatch;
if (conditional) if (conditional)
@ -145,15 +233,16 @@ namespace osu.Game.Tournament.Screens.Schedule
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopLeft, Origin = Anchor.TopLeft,
Colour = Color4.Black, Colour = OsuColour.Gray(0.7f),
Alpha = conditional ? 0.6f : 1, Alpha = conditional ? 0.6f : 1,
Font = OsuFont.Torus,
Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, Margin = new MarginPadding { Horizontal = 10, Vertical = 5 },
}); });
AddInternal(new TournamentSpriteText AddInternal(new TournamentSpriteText
{ {
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
Colour = Color4.Black, Colour = OsuColour.Gray(0.7f),
Alpha = conditional ? 0.6f : 1, Alpha = conditional ? 0.6f : 1,
Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, Margin = new MarginPadding { Horizontal = 10, Vertical = 5 },
Text = match.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + (conditional ? " (conditional)" : "") Text = match.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + (conditional ? " (conditional)" : "")
@ -170,29 +259,27 @@ namespace osu.Game.Tournament.Screens.Schedule
public ScheduleContainer(string title) public ScheduleContainer(string title)
{ {
Padding = new MarginPadding { Left = 30, Top = 30 }; Padding = new MarginPadding { Left = 60, Top = 10 };
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new TournamentSpriteText new FillFlowContainer
{ {
X = 30,
Text = title,
Colour = Color4.Black,
Spacing = new Vector2(10, 0),
Font = OsuFont.Torus.With(size: 30)
},
content = new FillFlowContainer
{
Direction = FillDirection.Vertical,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Margin = new MarginPadding(40) Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new TournamentSpriteTextWithBackground(title.ToUpperInvariant())
{
Scale = new Vector2(0.5f)
},
content = new FillFlowContainer
{
Direction = FillDirection.Vertical,
RelativeSizeAxes = Axes.Both,
Margin = new MarginPadding(10)
},
}
}, },
new Circle
{
Colour = new Color4(233, 187, 79, 255),
Width = 5,
RelativeSizeAxes = Axes.Y,
}
}; };
} }
} }

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;
@ -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
{ {
@ -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

@ -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

@ -194,9 +194,14 @@ namespace osu.Game.Tournament
switch (currentScreen) switch (currentScreen)
{ {
case GameplayScreen _:
case MapPoolScreen _: case MapPoolScreen _:
chatContainer.FadeIn(TournamentScreen.FADE_DELAY); chatContainer.FadeIn(TournamentScreen.FADE_DELAY);
chatContainer.ResizeWidthTo(1, 500, Easing.OutQuint);
break;
case GameplayScreen _:
chatContainer.FadeIn(TournamentScreen.FADE_DELAY);
chatContainer.ResizeWidthTo(0.5f, 500, Easing.OutQuint);
break; break;
default: default:

View File

@ -3,7 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.IO; using System.IO;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -93,8 +92,8 @@ namespace osu.Game.Beatmaps.Formats
var layer = parseLayer(split[1]); var layer = parseLayer(split[1]);
var origin = parseOrigin(split[2]); var origin = parseOrigin(split[2]);
var path = CleanFilename(split[3]); var path = CleanFilename(split[3]);
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo); var x = Parsing.ParseFloat(split[4], Parsing.MAX_COORDINATE_VALUE);
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); var y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE);
storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y)); storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y));
storyboard.GetLayer(layer).Add(storyboardSprite); storyboard.GetLayer(layer).Add(storyboardSprite);
break; break;
@ -105,10 +104,10 @@ namespace osu.Game.Beatmaps.Formats
var layer = parseLayer(split[1]); var layer = parseLayer(split[1]);
var origin = parseOrigin(split[2]); var origin = parseOrigin(split[2]);
var path = CleanFilename(split[3]); var path = CleanFilename(split[3]);
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo); var x = Parsing.ParseFloat(split[4], Parsing.MAX_COORDINATE_VALUE);
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); var y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE);
var frameCount = int.Parse(split[6]); var frameCount = Parsing.ParseInt(split[6]);
var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo); var frameDelay = Parsing.ParseDouble(split[7]);
var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever; var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever;
storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType);
storyboard.GetLayer(layer).Add(storyboardSprite); storyboard.GetLayer(layer).Add(storyboardSprite);
@ -117,10 +116,10 @@ namespace osu.Game.Beatmaps.Formats
case LegacyEventType.Sample: case LegacyEventType.Sample:
{ {
var time = double.Parse(split[1], CultureInfo.InvariantCulture); var time = Parsing.ParseDouble(split[1]);
var layer = parseLayer(split[2]); var layer = parseLayer(split[2]);
var path = CleanFilename(split[3]); var path = CleanFilename(split[3]);
var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100; var volume = split.Length > 4 ? Parsing.ParseFloat(split[4]) : 100;
storyboard.GetLayer(layer).Add(new StoryboardSampleInfo(path, time, (int)volume)); storyboard.GetLayer(layer).Add(new StoryboardSampleInfo(path, time, (int)volume));
break; break;
} }
@ -138,17 +137,17 @@ namespace osu.Game.Beatmaps.Formats
case "T": case "T":
{ {
var triggerName = split[1]; var triggerName = split[1];
var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue; var startTime = split.Length > 2 ? Parsing.ParseDouble(split[2]) : double.MinValue;
var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue; var endTime = split.Length > 3 ? Parsing.ParseDouble(split[3]) : double.MaxValue;
var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0; var groupNumber = split.Length > 4 ? Parsing.ParseInt(split[4]) : 0;
timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber); timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber);
break; break;
} }
case "L": case "L":
{ {
var startTime = double.Parse(split[1], CultureInfo.InvariantCulture); var startTime = Parsing.ParseDouble(split[1]);
var loopCount = int.Parse(split[2]); var loopCount = Parsing.ParseInt(split[2]);
timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount); timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount);
break; break;
} }
@ -158,52 +157,52 @@ namespace osu.Game.Beatmaps.Formats
if (string.IsNullOrEmpty(split[3])) if (string.IsNullOrEmpty(split[3]))
split[3] = split[2]; split[3] = split[2];
var easing = (Easing)int.Parse(split[1]); var easing = (Easing)Parsing.ParseInt(split[1]);
var startTime = double.Parse(split[2], CultureInfo.InvariantCulture); var startTime = Parsing.ParseDouble(split[2]);
var endTime = double.Parse(split[3], CultureInfo.InvariantCulture); var endTime = Parsing.ParseDouble(split[3]);
switch (commandType) switch (commandType)
{ {
case "F": case "F":
{ {
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var startValue = Parsing.ParseFloat(split[4]);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue;
timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue);
break; break;
} }
case "S": case "S":
{ {
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var startValue = Parsing.ParseFloat(split[4]);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue;
timelineGroup?.Scale.Add(easing, startTime, endTime, startValue, endValue); timelineGroup?.Scale.Add(easing, startTime, endTime, startValue, endValue);
break; break;
} }
case "V": case "V":
{ {
var startX = float.Parse(split[4], CultureInfo.InvariantCulture); var startX = Parsing.ParseFloat(split[4]);
var startY = float.Parse(split[5], CultureInfo.InvariantCulture); var startY = Parsing.ParseFloat(split[5]);
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; var endX = split.Length > 6 ? Parsing.ParseFloat(split[6]) : startX;
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; var endY = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startY;
timelineGroup?.VectorScale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); timelineGroup?.VectorScale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY));
break; break;
} }
case "R": case "R":
{ {
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var startValue = Parsing.ParseFloat(split[4]);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue;
timelineGroup?.Rotation.Add(easing, startTime, endTime, MathUtils.RadiansToDegrees(startValue), MathUtils.RadiansToDegrees(endValue)); timelineGroup?.Rotation.Add(easing, startTime, endTime, MathUtils.RadiansToDegrees(startValue), MathUtils.RadiansToDegrees(endValue));
break; break;
} }
case "M": case "M":
{ {
var startX = float.Parse(split[4], CultureInfo.InvariantCulture); var startX = Parsing.ParseFloat(split[4]);
var startY = float.Parse(split[5], CultureInfo.InvariantCulture); var startY = Parsing.ParseFloat(split[5]);
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; var endX = split.Length > 6 ? Parsing.ParseFloat(split[6]) : startX;
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; var endY = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startY;
timelineGroup?.X.Add(easing, startTime, endTime, startX, endX); timelineGroup?.X.Add(easing, startTime, endTime, startX, endX);
timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY);
break; break;
@ -211,28 +210,28 @@ namespace osu.Game.Beatmaps.Formats
case "MX": case "MX":
{ {
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var startValue = Parsing.ParseFloat(split[4]);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue;
timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue);
break; break;
} }
case "MY": case "MY":
{ {
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var startValue = Parsing.ParseFloat(split[4]);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; var endValue = split.Length > 5 ? Parsing.ParseFloat(split[5]) : startValue;
timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue);
break; break;
} }
case "C": case "C":
{ {
var startRed = float.Parse(split[4], CultureInfo.InvariantCulture); var startRed = Parsing.ParseFloat(split[4]);
var startGreen = float.Parse(split[5], CultureInfo.InvariantCulture); var startGreen = Parsing.ParseFloat(split[5]);
var startBlue = float.Parse(split[6], CultureInfo.InvariantCulture); var startBlue = Parsing.ParseFloat(split[6]);
var endRed = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startRed; var endRed = split.Length > 7 ? Parsing.ParseFloat(split[7]) : startRed;
var endGreen = split.Length > 8 ? float.Parse(split[8], CultureInfo.InvariantCulture) : startGreen; var endGreen = split.Length > 8 ? Parsing.ParseFloat(split[8]) : startGreen;
var endBlue = split.Length > 9 ? float.Parse(split[9], CultureInfo.InvariantCulture) : startBlue; var endBlue = split.Length > 9 ? Parsing.ParseFloat(split[9]) : startBlue;
timelineGroup?.Colour.Add(easing, startTime, endTime, timelineGroup?.Colour.Add(easing, startTime, endTime,
new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1), new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1),
new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1));

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

@ -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

@ -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.305.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.310.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.305.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2020.310.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.305.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.310.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" />