1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-08 03:12:57 +08:00

Merge branch 'master' into video-offset

This commit is contained in:
Dan Balasescu 2020-03-11 15:13:18 +09:00 committed by GitHub
commit 1d556bfc5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
140 changed files with 2485 additions and 1316 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>

View File

@ -0,0 +1,54 @@
// 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.Rulesets.Catch.Mods;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Tests.Visual;
using osuTK;
namespace osu.Game.Rulesets.Catch.Tests.Mods
{
public class TestSceneCatchModPerfect : ModPerfectTestScene
{
public TestSceneCatchModPerfect()
: base(new CatchRuleset(), new CatchModPerfect())
{
}
[TestCase(false)]
[TestCase(true)]
public void TestBananaShower(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new BananaShower { StartTime = 1000, EndTime = 3000 }, false), shouldMiss);
[TestCase(false)]
[TestCase(true)]
public void TestFruit(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Fruit { StartTime = 1000 }), shouldMiss);
[TestCase(false)]
[TestCase(true)]
public void TestJuiceStream(bool shouldMiss)
{
var stream = new JuiceStream
{
StartTime = 1000,
Path = new SliderPath(PathType.Linear, new[]
{
Vector2.Zero,
new Vector2(100, 0),
})
};
CreateHitObjectTest(new HitObjectTestData(stream), shouldMiss);
}
// We only care about testing misses, hits are tested via JuiceStream
[TestCase(true)]
public void TestDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Droplet { StartTime = 1000 }), shouldMiss);
// We only care about testing misses, hits are tested via JuiceStream
[TestCase(true)]
public void TestTinyDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new TinyDroplet { StartTime = 1000 }), shouldMiss);
}
}

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,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -22,11 +20,6 @@ namespace osu.Game.Rulesets.Catch.Tests
{ {
private RulesetInfo catchRuleset; private RulesetInfo catchRuleset;
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(CatcherArea),
};
public TestSceneCatcherArea() public TestSceneCatcherArea()
{ {
AddSliderStep<float>("CircleSize", 0, 8, 5, createCatcher); AddSliderStep<float>("CircleSize", 0, 8, 5, createCatcher);

View File

@ -1,16 +1,28 @@
// 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 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.Rulesets.Objects;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
using osuTK;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
{ {
[TestFixture] [TestFixture]
public class TestSceneHyperDash : PlayerTestScene public class TestSceneHyperDash : PlayerTestScene
{ {
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(CatcherArea),
};
public TestSceneHyperDash() public TestSceneHyperDash()
: base(new CatchRuleset()) : base(new CatchRuleset())
{ {
@ -22,8 +34,19 @@ 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 right movement", () => getCatcher().Scale.X > 0); // don't check hyperdashing as it happens too fast.
AddUntilStep("wait for left movement", () => getCatcher().Scale.X < 0);
for (int i = 0; i < 3; 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 +58,52 @@ 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 = 56 / 512f, NewCombo = true });
beatmap.HitObjects.Add(new Fruit { StartTime = 1008, X = 56 / 512f, }); beatmap.HitObjects.Add(new Fruit { StartTime = 2008, X = 308 / 512f, NewCombo = true });
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 { X = left_x });
createObjects(() => new TestJuiceStream(right_x), 1);
createObjects(() => new TestJuiceStream(left_x), 1);
createObjects(() => new Fruit { X = right_x });
createObjects(() => new Fruit { X = left_x });
createObjects(() => new Fruit { X = right_x });
createObjects(() => new TestJuiceStream(left_x), 1);
return beatmap; return beatmap;
void createObjects(Func<CatchHitObject> createObject, int count = 3)
{
const float spacing = 140;
for (int i = 0; i < count; i++)
{
var hitObject = createObject();
hitObject.StartTime = startTime + i * spacing;
beatmap.HitObjects.Add(hitObject);
}
startTime += 700;
}
}
private class TestJuiceStream : JuiceStream
{
public TestJuiceStream(float x)
{
X = x;
Path = new SliderPath(new[]
{
new PathControlPoint(Vector2.Zero),
new PathControlPoint(new Vector2(30, 0)),
});
}
} }
} }
} }

View File

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

View File

@ -1,11 +1,17 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Catch.Judgements;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Catch.Mods namespace osu.Game.Rulesets.Catch.Mods
{ {
public class CatchModPerfect : ModPerfect public class CatchModPerfect : ModPerfect
{ {
protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
=> !(result.Judgement is CatchBananaJudgement)
&& base.FailCondition(healthProcessor, result);
} }
} }

View File

@ -91,10 +91,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss);
} }
protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
protected override void UpdateInitialTransforms() => this.FadeInFromZero(200);
protected override void UpdateStateTransforms(ArmedState state) protected override void UpdateStateTransforms(ArmedState state)
{ {
var endTime = HitObject.GetEndTime(); var endTime = HitObject.GetEndTime();

View File

@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
float startRotation = RNG.NextSingle() * 20; float startRotation = RNG.NextSingle() * 20;
double duration = HitObject.TimePreempt + 2000; double duration = HitObject.TimePreempt + 2000;
this.RotateTo(startRotation).RotateTo(startRotation + 720, duration); ScaleContainer.RotateTo(startRotation).RotateTo(startRotation + 720, duration);
} }
} }
} }

View File

@ -13,7 +13,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
public DrawableFruit(Fruit h) public DrawableFruit(Fruit h)
: base(h) : base(h)
{ {
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -21,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
{ {
ScaleContainer.Child = new SkinnableDrawable( ScaleContainer.Child = new SkinnableDrawable(
new CatchSkinComponent(getComponent(HitObject.VisualRepresentation)), _ => new FruitPiece()); new CatchSkinComponent(getComponent(HitObject.VisualRepresentation)), _ => new FruitPiece());
ScaleContainer.Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
} }
private CatchSkinComponents getComponent(FruitVisualRepresentation hitObjectVisualRepresentation) private CatchSkinComponents getComponent(FruitVisualRepresentation hitObjectVisualRepresentation)

View File

@ -6,6 +6,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
namespace osu.Game.Rulesets.Catch.Objects.Drawables namespace osu.Game.Rulesets.Catch.Objects.Drawables
{ {
@ -14,11 +15,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
private readonly Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation; private readonly Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation;
private readonly Container dropletContainer; private readonly Container dropletContainer;
public override Vector2 OriginPosition => base.OriginPosition - new Vector2(0, CatchHitObject.OBJECT_RADIUS);
public DrawableJuiceStream(JuiceStream s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation = null) public DrawableJuiceStream(JuiceStream s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> createDrawableRepresentation = null)
: base(s) : base(s)
{ {
this.createDrawableRepresentation = createDrawableRepresentation; this.createDrawableRepresentation = createDrawableRepresentation;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.X;
Origin = Anchor.BottomLeft; Origin = Anchor.BottomLeft;
X = 0; X = 0;
@ -27,6 +30,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
protected override void AddNestedHitObject(DrawableHitObject hitObject) protected override void AddNestedHitObject(DrawableHitObject hitObject)
{ {
hitObject.Origin = Anchor.BottomCentre;
base.AddNestedHitObject(hitObject); base.AddNestedHitObject(hitObject);
dropletContainer.Add(hitObject); dropletContainer.Add(hitObject);
} }

View File

@ -24,8 +24,8 @@ namespace osu.Game.Rulesets.Catch.Objects
public int RepeatCount { get; set; } public int RepeatCount { get; set; }
public double Velocity; public double Velocity { get; private set; }
public double TickDistance; public double TickDistance { get; private set; }
/// <summary> /// <summary>
/// The length of one span of this <see cref="JuiceStream"/>. /// The length of one span of this <see cref="JuiceStream"/>.
@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.Objects
{ {
base.CreateNestedHitObjects(); base.CreateNestedHitObjects();
var tickSamples = Samples.Select(s => new HitSampleInfo var dropletSamples = Samples.Select(s => new HitSampleInfo
{ {
Bank = s.Bank, Bank = s.Bank,
Name = @"slidertick", Name = @"slidertick",
@ -75,7 +75,6 @@ namespace osu.Game.Rulesets.Catch.Objects
{ {
AddNested(new TinyDroplet AddNested(new TinyDroplet
{ {
Samples = tickSamples,
StartTime = t + lastEvent.Value.Time, StartTime = t + lastEvent.Value.Time,
X = X + Path.PositionAt( X = X + Path.PositionAt(
lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X / CatchPlayfield.BASE_WIDTH, lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X / CatchPlayfield.BASE_WIDTH,
@ -93,7 +92,7 @@ namespace osu.Game.Rulesets.Catch.Objects
case SliderEventType.Tick: case SliderEventType.Tick:
AddNested(new Droplet AddNested(new Droplet
{ {
Samples = tickSamples, Samples = dropletSamples,
StartTime = e.Time, StartTime = e.Time,
X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH, X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH,
}); });

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;
})
}; };
} }
@ -202,17 +205,7 @@ namespace osu.Game.Rulesets.Catch.UI
if (!Trail) return; if (!Trail) return;
var additive = createCatcherSprite(); var additive = createAdditiveSprite(HyperDashing);
additive.Anchor = Anchor;
additive.OriginPosition += new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly.
additive.Position = Position;
additive.Scale = Scale;
additive.Colour = HyperDashing ? Color4.Red : Color4.White;
additive.RelativePositionAxes = RelativePositionAxes;
additive.Blending = BlendingParameters.Additive;
AdditiveTarget.Add(additive);
additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint);
additive.Expire(true); additive.Expire(true);
@ -220,6 +213,22 @@ namespace osu.Game.Rulesets.Catch.UI
Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50); Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50);
} }
private Drawable createAdditiveSprite(bool hyperDash)
{
var additive = createCatcherSprite();
additive.Anchor = Anchor;
additive.Scale = Scale;
additive.Colour = hyperDash ? Color4.Red : Color4.White;
additive.Blending = BlendingParameters.Additive;
additive.RelativePositionAxes = RelativePositionAxes;
additive.Position = Position;
AdditiveTarget.Add(additive);
return additive;
}
private Drawable createCatcherSprite() => new CatcherSprite(); private Drawable createCatcherSprite() => new CatcherSprite();
/// <summary> /// <summary>
@ -270,6 +279,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;
@ -305,14 +318,14 @@ namespace osu.Game.Rulesets.Catch.UI
{ {
const float hyper_dash_transition_length = 180; const float hyper_dash_transition_length = 180;
bool previouslyHyperDashing = HyperDashing; bool wasHyperDashing = HyperDashing;
if (modifier <= 1 || X == targetPosition) if (modifier <= 1 || X == targetPosition)
{ {
hyperDashModifier = 1; hyperDashModifier = 1;
hyperDashDirection = 0; hyperDashDirection = 0;
if (previouslyHyperDashing) if (wasHyperDashing)
{ {
this.FadeColour(Color4.White, hyper_dash_transition_length, Easing.OutQuint); this.FadeColour(Color4.White, hyper_dash_transition_length, Easing.OutQuint);
this.FadeTo(1, hyper_dash_transition_length, Easing.OutQuint); this.FadeTo(1, hyper_dash_transition_length, Easing.OutQuint);
@ -325,11 +338,18 @@ namespace osu.Game.Rulesets.Catch.UI
hyperDashDirection = Math.Sign(targetPosition - X); hyperDashDirection = Math.Sign(targetPosition - X);
hyperDashTargetPosition = targetPosition; hyperDashTargetPosition = targetPosition;
if (!previouslyHyperDashing) if (!wasHyperDashing)
{ {
this.FadeColour(Color4.OrangeRed, hyper_dash_transition_length, Easing.OutQuint); this.FadeColour(Color4.OrangeRed, hyper_dash_transition_length, Easing.OutQuint);
this.FadeTo(0.2f, hyper_dash_transition_length, Easing.OutQuint); this.FadeTo(0.2f, hyper_dash_transition_length, Easing.OutQuint);
Trail = true; Trail = true;
var hyperDashEndGlow = createAdditiveSprite(true);
hyperDashEndGlow.MoveToOffset(new Vector2(0, -20), 1200, Easing.In);
hyperDashEndGlow.ScaleTo(hyperDashEndGlow.Scale * 0.9f).ScaleTo(hyperDashEndGlow.Scale * 1.2f, 1200, Easing.In);
hyperDashEndGlow.FadeOut(1200);
hyperDashEndGlow.Expire(true);
} }
} }
} }

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,26 @@
// 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.Rulesets.Mania.Mods;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Mania.Tests.Mods
{
public class TestSceneManiaModPerfect : ModPerfectTestScene
{
public TestSceneManiaModPerfect()
: base(new ManiaRuleset(), new ManiaModPerfect())
{
}
[TestCase(false)]
[TestCase(true)]
public void TestNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Note { StartTime = 1000 }), shouldMiss);
[TestCase(false)]
[TestCase(true)]
public void TestHoldNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HoldNote { StartTime = 1000, EndTime = 3000 }), shouldMiss);
}
}

View File

@ -0,0 +1,52 @@
// 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.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Tests.Visual;
using osuTK;
namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public class TestSceneOsuModPerfect : ModPerfectTestScene
{
public TestSceneOsuModPerfect()
: base(new OsuRuleset(), new OsuModPerfect())
{
}
[TestCase(false)]
[TestCase(true)]
public void TestHitCircle(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HitCircle { StartTime = 1000 }), shouldMiss);
[TestCase(false)]
[TestCase(true)]
public void TestSlider(bool shouldMiss)
{
var slider = new Slider
{
StartTime = 1000,
Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(100, 0), })
};
CreateHitObjectTest(new HitObjectTestData(slider), shouldMiss);
}
[TestCase(false)]
[TestCase(true)]
public void TestSpinner(bool shouldMiss)
{
var spinner = new Spinner
{
StartTime = 1000,
EndTime = 3000,
Position = new Vector2(256, 192)
};
CreateHitObjectTest(new HitObjectTestData(spinner), shouldMiss);
}
}
}

View File

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

View File

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

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

View File

@ -36,8 +36,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private readonly SpriteIcon symbol; private readonly SpriteIcon symbol;
private readonly Color4 baseColour = OsuColour.FromHex(@"002c3c"); private readonly Color4 baseColour = Color4Extensions.FromHex(@"002c3c");
private readonly Color4 fillColour = OsuColour.FromHex(@"005b7c"); private readonly Color4 fillColour = Color4Extensions.FromHex(@"005b7c");
private readonly IBindable<Vector2> positionBindable = new Bindable<Vector2>(); private readonly IBindable<Vector2> positionBindable = new Bindable<Vector2>();

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

@ -0,0 +1,47 @@
// 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.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Mods;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Scoring;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Taiko.Tests.Mods
{
public class TestSceneTaikoModPerfect : ModPerfectTestScene
{
public TestSceneTaikoModPerfect()
: base(new TestTaikoRuleset(), new TaikoModPerfect())
{
}
[TestCase(false)]
[TestCase(true)]
public void TestHit(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new CentreHit { StartTime = 1000 }), shouldMiss);
[TestCase(false)]
[TestCase(true)]
public void TestDrumRoll(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new DrumRoll { StartTime = 1000, EndTime = 3000 }), shouldMiss);
[TestCase(false)]
[TestCase(true)]
public void TestSwell(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Swell { StartTime = 1000, EndTime = 3000 }), shouldMiss);
private class TestTaikoRuleset : TaikoRuleset
{
public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new TestTaikoHealthProcessor();
private class TestTaikoHealthProcessor : TaikoHealthProcessor
{
protected override void Reset(bool storeResults)
{
base.Reset(storeResults);
Health.Value = 1; // Don't care about the health condition (only the mod condition)
}
}
}
}
}

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.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
@ -39,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring
{ {
base.ApplyBeatmap(beatmap); base.ApplyBeatmap(beatmap);
hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.OfType<Hit>().Count() * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); hpMultiplier = 1 / (object_count_factor * Math.Max(1, beatmap.HitObjects.OfType<Hit>().Count()) * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
} }

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

@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Menus
API.LocalUser.Value = new User API.LocalUser.Value = new User
{ {
Username = API.LocalUser.Value.Username, Username = API.LocalUser.Value.Username,
Id = API.LocalUser.Value.Id, Id = API.LocalUser.Value.Id + 1,
IsSupporter = !API.LocalUser.Value.IsSupporter, IsSupporter = !API.LocalUser.Value.IsSupporter,
}; };
}); });

View File

@ -7,6 +7,7 @@ using System.Linq;
using NUnit.Framework; using NUnit.Framework;
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.Game.Graphics; using osu.Game.Graphics;
@ -102,7 +103,7 @@ namespace osu.Game.Tests.Visual.Online
{ {
bool hasBackground = !string.IsNullOrEmpty(newLine.Message.Sender.Colour); bool hasBackground = !string.IsNullOrEmpty(newLine.Message.Sender.Colour);
Color4 textColour = isAction && hasBackground ? OsuColour.FromHex(newLine.Message.Sender.Colour) : Color4.White; Color4 textColour = isAction && hasBackground ? Color4Extensions.FromHex(newLine.Message.Sender.Colour) : Color4.White;
var linkCompilers = newLine.ContentFlow.Where(d => d is DrawableLinkCompiler).ToList(); var linkCompilers = newLine.ContentFlow.Where(d => d is DrawableLinkCompiler).ToList();
var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts); var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts);

View File

@ -465,6 +465,43 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("carousel still correct", () => songSelect.Carousel.SelectedBeatmap.OnlineBeatmapID == target.OnlineBeatmapID); AddAssert("carousel still correct", () => songSelect.Carousel.SelectedBeatmap.OnlineBeatmapID == target.OnlineBeatmapID);
} }
[Test]
public void TestExternalBeatmapChangeWhileFilteredThenRefilter()
{
createSongSelect();
addManyTestMaps();
changeRuleset(0);
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmap != null);
AddStep("set filter text", () => songSelect.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = "nonono");
AddUntilStep("dummy selected", () => Beatmap.Value is DummyWorkingBeatmap);
AddUntilStep("has no selection", () => songSelect.Carousel.SelectedBeatmap == null);
BeatmapInfo target = null;
AddStep("select beatmap externally", () =>
{
target = manager.GetAllUsableBeatmapSets().Where(b => b.Beatmaps.Any(bi => bi.RulesetID == 1))
.ElementAt(5).Beatmaps.First();
Beatmap.Value = manager.GetWorkingBeatmap(target);
});
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmap != null);
AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmap?.OnlineBeatmapID == target.OnlineBeatmapID);
AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.OnlineBeatmapID == target.OnlineBeatmapID);
AddStep("set filter text", () => songSelect.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = "nononoo");
AddUntilStep("game lost selection", () => Beatmap.Value is DummyWorkingBeatmap);
AddAssert("carousel lost selection", () => songSelect.Carousel.SelectedBeatmap == null);
}
[Test] [Test]
public void TestAutoplayViaCtrlEnter() public void TestAutoplayViaCtrlEnter()
{ {

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 = Color4Extensions.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 = Color4Extensions.FromHex("#FFE8AD"),
RelativeSizeAxes = Axes.Both,
},
};
Masking = true;
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Glow,
Colour = Color4Extensions.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

@ -4,6 +4,7 @@
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.Cursor; using osu.Framework.Graphics.Cursor;
@ -27,21 +28,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 +63,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 +85,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); ? Color4Extensions.FromHex("#8E7F48")
: Color4Extensions.FromHex("#1462AA");
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
@ -102,29 +103,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 +181,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 : Color4Extensions.FromHex("#444"), winner ? 500 : 0, Easing.OutQuint);
backgroundRight.FadeColour(winner ? colourWinner : Color4Extensions.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 = Color4Extensions.FromHex("#66D1FF");
losersPathColour = colours.YellowDarker.Darken(2); losersPathColour = Color4Extensions.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

@ -1,16 +1,26 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
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 = Color4Extensions.FromHex("#AA1414");
public static readonly Color4 COLOUR_BLUE = Color4Extensions.FromHex("#1462AA");
public static readonly Color4 ELEMENT_BACKGROUND_COLOUR = Color4Extensions.FromHex("#fff");
public static readonly Color4 ELEMENT_FOREGROUND_COLOUR = Color4Extensions.FromHex("#000");
public static readonly Color4 TEXT_COLOUR = Color4Extensions.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 osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Utils; using osu.Framework.Utils;
@ -102,8 +101,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;
@ -114,10 +113,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);
@ -126,10 +125,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;
} }
@ -147,17 +146,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;
} }
@ -167,52 +166,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;
@ -220,28 +219,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

@ -15,11 +15,13 @@ namespace osu.Game.Database
{ {
/// <summary> /// <summary>
/// Fired when a <typeparamref name="TModel"/> download begins. /// Fired when a <typeparamref name="TModel"/> download begins.
/// This is NOT run on the update thread and should be scheduled.
/// </summary> /// </summary>
event Action<ArchiveDownloadRequest<TModel>> DownloadBegan; event Action<ArchiveDownloadRequest<TModel>> DownloadBegan;
/// <summary> /// <summary>
/// Fired when a <typeparamref name="TModel"/> download is interrupted, either due to user cancellation or failure. /// Fired when a <typeparamref name="TModel"/> download is interrupted, either due to user cancellation or failure.
/// This is NOT run on the update thread and should be scheduled.
/// </summary> /// </summary>
event Action<ArchiveDownloadRequest<TModel>> DownloadFailed; event Action<ArchiveDownloadRequest<TModel>> DownloadFailed;

View File

@ -1,8 +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 osu.Framework.Extensions.Color4Extensions;
using System.Globalization;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osuTK.Graphics; using osuTK.Graphics;
@ -13,45 +12,6 @@ namespace osu.Game.Graphics
public static Color4 Gray(float amt) => new Color4(amt, amt, amt, 1f); public static Color4 Gray(float amt) => new Color4(amt, amt, amt, 1f);
public static Color4 Gray(byte amt) => new Color4(amt, amt, amt, 255); public static Color4 Gray(byte amt) => new Color4(amt, amt, amt, 255);
public static Color4 FromHex(string hex)
{
var hexSpan = hex[0] == '#' ? hex.AsSpan().Slice(1) : hex.AsSpan();
switch (hexSpan.Length)
{
default:
throw new ArgumentException(@"Invalid hex string length!");
case 3:
return new Color4(
(byte)(byte.Parse(hexSpan.Slice(0, 1), NumberStyles.HexNumber) * 17),
(byte)(byte.Parse(hexSpan.Slice(1, 1), NumberStyles.HexNumber) * 17),
(byte)(byte.Parse(hexSpan.Slice(2, 1), NumberStyles.HexNumber) * 17),
255);
case 6:
return new Color4(
byte.Parse(hexSpan.Slice(0, 2), NumberStyles.HexNumber),
byte.Parse(hexSpan.Slice(2, 2), NumberStyles.HexNumber),
byte.Parse(hexSpan.Slice(4, 2), NumberStyles.HexNumber),
255);
case 4:
return new Color4(
(byte)(byte.Parse(hexSpan.Slice(0, 1), NumberStyles.HexNumber) * 17),
(byte)(byte.Parse(hexSpan.Slice(1, 1), NumberStyles.HexNumber) * 17),
(byte)(byte.Parse(hexSpan.Slice(0, 1), NumberStyles.HexNumber) * 17),
(byte)(byte.Parse(hexSpan.Slice(0, 1), NumberStyles.HexNumber) * 17));
case 8:
return new Color4(
byte.Parse(hexSpan.Slice(0, 2), NumberStyles.HexNumber),
byte.Parse(hexSpan.Slice(2, 2), NumberStyles.HexNumber),
byte.Parse(hexSpan.Slice(4, 2), NumberStyles.HexNumber),
byte.Parse(hexSpan.Slice(6, 2), NumberStyles.HexNumber));
}
}
public Color4 ForDifficultyRating(DifficultyRating difficulty, bool useLighterColour = false) public Color4 ForDifficultyRating(DifficultyRating difficulty, bool useLighterColour = false)
{ {
switch (difficulty) switch (difficulty)
@ -78,105 +38,105 @@ namespace osu.Game.Graphics
} }
// See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less // See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less
public readonly Color4 PurpleLighter = FromHex(@"eeeeff"); public readonly Color4 PurpleLighter = Color4Extensions.FromHex(@"eeeeff");
public readonly Color4 PurpleLight = FromHex(@"aa88ff"); public readonly Color4 PurpleLight = Color4Extensions.FromHex(@"aa88ff");
public readonly Color4 PurpleLightAlternative = FromHex(@"cba4da"); public readonly Color4 PurpleLightAlternative = Color4Extensions.FromHex(@"cba4da");
public readonly Color4 Purple = FromHex(@"8866ee"); public readonly Color4 Purple = Color4Extensions.FromHex(@"8866ee");
public readonly Color4 PurpleDark = FromHex(@"6644cc"); public readonly Color4 PurpleDark = Color4Extensions.FromHex(@"6644cc");
public readonly Color4 PurpleDarkAlternative = FromHex(@"312436"); public readonly Color4 PurpleDarkAlternative = Color4Extensions.FromHex(@"312436");
public readonly Color4 PurpleDarker = FromHex(@"441188"); public readonly Color4 PurpleDarker = Color4Extensions.FromHex(@"441188");
public readonly Color4 PinkLighter = FromHex(@"ffddee"); public readonly Color4 PinkLighter = Color4Extensions.FromHex(@"ffddee");
public readonly Color4 PinkLight = FromHex(@"ff99cc"); public readonly Color4 PinkLight = Color4Extensions.FromHex(@"ff99cc");
public readonly Color4 Pink = FromHex(@"ff66aa"); public readonly Color4 Pink = Color4Extensions.FromHex(@"ff66aa");
public readonly Color4 PinkDark = FromHex(@"cc5288"); public readonly Color4 PinkDark = Color4Extensions.FromHex(@"cc5288");
public readonly Color4 PinkDarker = FromHex(@"bb1177"); public readonly Color4 PinkDarker = Color4Extensions.FromHex(@"bb1177");
public readonly Color4 BlueLighter = FromHex(@"ddffff"); public readonly Color4 BlueLighter = Color4Extensions.FromHex(@"ddffff");
public readonly Color4 BlueLight = FromHex(@"99eeff"); public readonly Color4 BlueLight = Color4Extensions.FromHex(@"99eeff");
public readonly Color4 Blue = FromHex(@"66ccff"); public readonly Color4 Blue = Color4Extensions.FromHex(@"66ccff");
public readonly Color4 BlueDark = FromHex(@"44aadd"); public readonly Color4 BlueDark = Color4Extensions.FromHex(@"44aadd");
public readonly Color4 BlueDarker = FromHex(@"2299bb"); public readonly Color4 BlueDarker = Color4Extensions.FromHex(@"2299bb");
public readonly Color4 YellowLighter = FromHex(@"ffffdd"); public readonly Color4 YellowLighter = Color4Extensions.FromHex(@"ffffdd");
public readonly Color4 YellowLight = FromHex(@"ffdd55"); public readonly Color4 YellowLight = Color4Extensions.FromHex(@"ffdd55");
public readonly Color4 Yellow = FromHex(@"ffcc22"); public readonly Color4 Yellow = Color4Extensions.FromHex(@"ffcc22");
public readonly Color4 YellowDark = FromHex(@"eeaa00"); public readonly Color4 YellowDark = Color4Extensions.FromHex(@"eeaa00");
public readonly Color4 YellowDarker = FromHex(@"cc6600"); public readonly Color4 YellowDarker = Color4Extensions.FromHex(@"cc6600");
public readonly Color4 GreenLighter = FromHex(@"eeffcc"); public readonly Color4 GreenLighter = Color4Extensions.FromHex(@"eeffcc");
public readonly Color4 GreenLight = FromHex(@"b3d944"); public readonly Color4 GreenLight = Color4Extensions.FromHex(@"b3d944");
public readonly Color4 Green = FromHex(@"88b300"); public readonly Color4 Green = Color4Extensions.FromHex(@"88b300");
public readonly Color4 GreenDark = FromHex(@"668800"); public readonly Color4 GreenDark = Color4Extensions.FromHex(@"668800");
public readonly Color4 GreenDarker = FromHex(@"445500"); public readonly Color4 GreenDarker = Color4Extensions.FromHex(@"445500");
public readonly Color4 Sky = FromHex(@"6bb5ff"); public readonly Color4 Sky = Color4Extensions.FromHex(@"6bb5ff");
public readonly Color4 GreySkyLighter = FromHex(@"c6e3f4"); public readonly Color4 GreySkyLighter = Color4Extensions.FromHex(@"c6e3f4");
public readonly Color4 GreySkyLight = FromHex(@"8ab3cc"); public readonly Color4 GreySkyLight = Color4Extensions.FromHex(@"8ab3cc");
public readonly Color4 GreySky = FromHex(@"405461"); public readonly Color4 GreySky = Color4Extensions.FromHex(@"405461");
public readonly Color4 GreySkyDark = FromHex(@"303d47"); public readonly Color4 GreySkyDark = Color4Extensions.FromHex(@"303d47");
public readonly Color4 GreySkyDarker = FromHex(@"21272c"); public readonly Color4 GreySkyDarker = Color4Extensions.FromHex(@"21272c");
public readonly Color4 Seafoam = FromHex(@"05ffa2"); public readonly Color4 Seafoam = Color4Extensions.FromHex(@"05ffa2");
public readonly Color4 GreySeafoamLighter = FromHex(@"9ebab1"); public readonly Color4 GreySeafoamLighter = Color4Extensions.FromHex(@"9ebab1");
public readonly Color4 GreySeafoamLight = FromHex(@"4d7365"); public readonly Color4 GreySeafoamLight = Color4Extensions.FromHex(@"4d7365");
public readonly Color4 GreySeafoam = FromHex(@"33413c"); public readonly Color4 GreySeafoam = Color4Extensions.FromHex(@"33413c");
public readonly Color4 GreySeafoamDark = FromHex(@"2c3532"); public readonly Color4 GreySeafoamDark = Color4Extensions.FromHex(@"2c3532");
public readonly Color4 GreySeafoamDarker = FromHex(@"1e2422"); public readonly Color4 GreySeafoamDarker = Color4Extensions.FromHex(@"1e2422");
public readonly Color4 Cyan = FromHex(@"05f4fd"); public readonly Color4 Cyan = Color4Extensions.FromHex(@"05f4fd");
public readonly Color4 GreyCyanLighter = FromHex(@"77b1b3"); public readonly Color4 GreyCyanLighter = Color4Extensions.FromHex(@"77b1b3");
public readonly Color4 GreyCyanLight = FromHex(@"436d6f"); public readonly Color4 GreyCyanLight = Color4Extensions.FromHex(@"436d6f");
public readonly Color4 GreyCyan = FromHex(@"293d3e"); public readonly Color4 GreyCyan = Color4Extensions.FromHex(@"293d3e");
public readonly Color4 GreyCyanDark = FromHex(@"243536"); public readonly Color4 GreyCyanDark = Color4Extensions.FromHex(@"243536");
public readonly Color4 GreyCyanDarker = FromHex(@"1e2929"); public readonly Color4 GreyCyanDarker = Color4Extensions.FromHex(@"1e2929");
public readonly Color4 Lime = FromHex(@"82ff05"); public readonly Color4 Lime = Color4Extensions.FromHex(@"82ff05");
public readonly Color4 GreyLimeLighter = FromHex(@"deff87"); public readonly Color4 GreyLimeLighter = Color4Extensions.FromHex(@"deff87");
public readonly Color4 GreyLimeLight = FromHex(@"657259"); public readonly Color4 GreyLimeLight = Color4Extensions.FromHex(@"657259");
public readonly Color4 GreyLime = FromHex(@"3f443a"); public readonly Color4 GreyLime = Color4Extensions.FromHex(@"3f443a");
public readonly Color4 GreyLimeDark = FromHex(@"32352e"); public readonly Color4 GreyLimeDark = Color4Extensions.FromHex(@"32352e");
public readonly Color4 GreyLimeDarker = FromHex(@"2e302b"); public readonly Color4 GreyLimeDarker = Color4Extensions.FromHex(@"2e302b");
public readonly Color4 Violet = FromHex(@"bf04ff"); public readonly Color4 Violet = Color4Extensions.FromHex(@"bf04ff");
public readonly Color4 GreyVioletLighter = FromHex(@"ebb8fe"); public readonly Color4 GreyVioletLighter = Color4Extensions.FromHex(@"ebb8fe");
public readonly Color4 GreyVioletLight = FromHex(@"685370"); public readonly Color4 GreyVioletLight = Color4Extensions.FromHex(@"685370");
public readonly Color4 GreyViolet = FromHex(@"46334d"); public readonly Color4 GreyViolet = Color4Extensions.FromHex(@"46334d");
public readonly Color4 GreyVioletDark = FromHex(@"2c2230"); public readonly Color4 GreyVioletDark = Color4Extensions.FromHex(@"2c2230");
public readonly Color4 GreyVioletDarker = FromHex(@"201823"); public readonly Color4 GreyVioletDarker = Color4Extensions.FromHex(@"201823");
public readonly Color4 Carmine = FromHex(@"ff0542"); public readonly Color4 Carmine = Color4Extensions.FromHex(@"ff0542");
public readonly Color4 GreyCarmineLighter = FromHex(@"deaab4"); public readonly Color4 GreyCarmineLighter = Color4Extensions.FromHex(@"deaab4");
public readonly Color4 GreyCarmineLight = FromHex(@"644f53"); public readonly Color4 GreyCarmineLight = Color4Extensions.FromHex(@"644f53");
public readonly Color4 GreyCarmine = FromHex(@"342b2d"); public readonly Color4 GreyCarmine = Color4Extensions.FromHex(@"342b2d");
public readonly Color4 GreyCarmineDark = FromHex(@"302a2b"); public readonly Color4 GreyCarmineDark = Color4Extensions.FromHex(@"302a2b");
public readonly Color4 GreyCarmineDarker = FromHex(@"241d1e"); public readonly Color4 GreyCarmineDarker = Color4Extensions.FromHex(@"241d1e");
public readonly Color4 Gray0 = FromHex(@"000"); public readonly Color4 Gray0 = Color4Extensions.FromHex(@"000");
public readonly Color4 Gray1 = FromHex(@"111"); public readonly Color4 Gray1 = Color4Extensions.FromHex(@"111");
public readonly Color4 Gray2 = FromHex(@"222"); public readonly Color4 Gray2 = Color4Extensions.FromHex(@"222");
public readonly Color4 Gray3 = FromHex(@"333"); public readonly Color4 Gray3 = Color4Extensions.FromHex(@"333");
public readonly Color4 Gray4 = FromHex(@"444"); public readonly Color4 Gray4 = Color4Extensions.FromHex(@"444");
public readonly Color4 Gray5 = FromHex(@"555"); public readonly Color4 Gray5 = Color4Extensions.FromHex(@"555");
public readonly Color4 Gray6 = FromHex(@"666"); public readonly Color4 Gray6 = Color4Extensions.FromHex(@"666");
public readonly Color4 Gray7 = FromHex(@"777"); public readonly Color4 Gray7 = Color4Extensions.FromHex(@"777");
public readonly Color4 Gray8 = FromHex(@"888"); public readonly Color4 Gray8 = Color4Extensions.FromHex(@"888");
public readonly Color4 Gray9 = FromHex(@"999"); public readonly Color4 Gray9 = Color4Extensions.FromHex(@"999");
public readonly Color4 GrayA = FromHex(@"aaa"); public readonly Color4 GrayA = Color4Extensions.FromHex(@"aaa");
public readonly Color4 GrayB = FromHex(@"bbb"); public readonly Color4 GrayB = Color4Extensions.FromHex(@"bbb");
public readonly Color4 GrayC = FromHex(@"ccc"); public readonly Color4 GrayC = Color4Extensions.FromHex(@"ccc");
public readonly Color4 GrayD = FromHex(@"ddd"); public readonly Color4 GrayD = Color4Extensions.FromHex(@"ddd");
public readonly Color4 GrayE = FromHex(@"eee"); public readonly Color4 GrayE = Color4Extensions.FromHex(@"eee");
public readonly Color4 GrayF = FromHex(@"fff"); public readonly Color4 GrayF = Color4Extensions.FromHex(@"fff");
public readonly Color4 RedLighter = FromHex(@"ffeded"); public readonly Color4 RedLighter = Color4Extensions.FromHex(@"ffeded");
public readonly Color4 RedLight = FromHex(@"ed7787"); public readonly Color4 RedLight = Color4Extensions.FromHex(@"ed7787");
public readonly Color4 Red = FromHex(@"ed1121"); public readonly Color4 Red = Color4Extensions.FromHex(@"ed1121");
public readonly Color4 RedDark = FromHex(@"ba0011"); public readonly Color4 RedDark = Color4Extensions.FromHex(@"ba0011");
public readonly Color4 RedDarker = FromHex(@"870000"); public readonly Color4 RedDarker = Color4Extensions.FromHex(@"870000");
public readonly Color4 ChatBlue = FromHex(@"17292e"); public readonly Color4 ChatBlue = Color4Extensions.FromHex(@"17292e");
public readonly Color4 ContextMenuGray = FromHex(@"223034"); public readonly Color4 ContextMenuGray = Color4Extensions.FromHex(@"223034");
} }
} }

View File

@ -4,6 +4,7 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
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.Sprites; using osu.Framework.Graphics.Sprites;
@ -38,7 +39,7 @@ namespace osu.Game.Graphics.UserInterface
sampleClick = audio.Samples.Get(@"UI/generic-select"); sampleClick = audio.Samples.Get(@"UI/generic-select");
BackgroundColour = Color4.Transparent; BackgroundColour = Color4.Transparent;
BackgroundColourHover = OsuColour.FromHex(@"172023"); BackgroundColourHover = Color4Extensions.FromHex(@"172023");
updateTextColour(); updateTextColour();
} }
@ -57,7 +58,7 @@ namespace osu.Game.Graphics.UserInterface
break; break;
case MenuItemType.Highlighted: case MenuItemType.Highlighted:
text.Colour = OsuColour.FromHex(@"ffcc22"); text.Colour = Color4Extensions.FromHex(@"ffcc22");
break; break;
} }
} }

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

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -42,7 +43,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
new Box new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex("1c2125"), Colour = Color4Extensions.FromHex("1c2125"),
}, },
new FillFlowContainer new FillFlowContainer
{ {

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

@ -53,17 +53,17 @@ namespace osu.Game.Online
manager.ItemRemoved += itemRemoved; manager.ItemRemoved += itemRemoved;
} }
private void downloadBegan(ArchiveDownloadRequest<TModel> request) private void downloadBegan(ArchiveDownloadRequest<TModel> request) => Schedule(() =>
{ {
if (request.Model.Equals(Model.Value)) if (request.Model.Equals(Model.Value))
attachDownload(request); attachDownload(request);
} });
private void downloadFailed(ArchiveDownloadRequest<TModel> request) private void downloadFailed(ArchiveDownloadRequest<TModel> request) => Schedule(() =>
{ {
if (request.Model.Equals(Model.Value)) if (request.Model.Equals(Model.Value))
attachDownload(null); attachDownload(null);
} });
private ArchiveDownloadRequest<TModel> attachedRequest; private ArchiveDownloadRequest<TModel> attachedRequest;

View File

@ -80,23 +80,23 @@ namespace osu.Game.Online.Leaderboards
{ {
case ScoreRank.XH: case ScoreRank.XH:
case ScoreRank.X: case ScoreRank.X:
return OsuColour.FromHex(@"ce1c9d"); return Color4Extensions.FromHex(@"ce1c9d");
case ScoreRank.SH: case ScoreRank.SH:
case ScoreRank.S: case ScoreRank.S:
return OsuColour.FromHex(@"00a8b5"); return Color4Extensions.FromHex(@"00a8b5");
case ScoreRank.A: case ScoreRank.A:
return OsuColour.FromHex(@"7cce14"); return Color4Extensions.FromHex(@"7cce14");
case ScoreRank.B: case ScoreRank.B:
return OsuColour.FromHex(@"e3b130"); return Color4Extensions.FromHex(@"e3b130");
case ScoreRank.C: case ScoreRank.C:
return OsuColour.FromHex(@"f18252"); return Color4Extensions.FromHex(@"f18252");
default: default:
return OsuColour.FromHex(@"e95353"); return Color4Extensions.FromHex(@"e95353");
} }
} }
@ -109,23 +109,23 @@ namespace osu.Game.Online.Leaderboards
{ {
case ScoreRank.XH: case ScoreRank.XH:
case ScoreRank.SH: case ScoreRank.SH:
return ColourInfo.GradientVertical(Color4.White, OsuColour.FromHex("afdff0")); return ColourInfo.GradientVertical(Color4.White, Color4Extensions.FromHex("afdff0"));
case ScoreRank.X: case ScoreRank.X:
case ScoreRank.S: case ScoreRank.S:
return ColourInfo.GradientVertical(OsuColour.FromHex(@"ffe7a8"), OsuColour.FromHex(@"ffb800")); return ColourInfo.GradientVertical(Color4Extensions.FromHex(@"ffe7a8"), Color4Extensions.FromHex(@"ffb800"));
case ScoreRank.A: case ScoreRank.A:
return OsuColour.FromHex(@"275227"); return Color4Extensions.FromHex(@"275227");
case ScoreRank.B: case ScoreRank.B:
return OsuColour.FromHex(@"553a2b"); return Color4Extensions.FromHex(@"553a2b");
case ScoreRank.C: case ScoreRank.C:
return OsuColour.FromHex(@"473625"); return Color4Extensions.FromHex(@"473625");
default: default:
return OsuColour.FromHex(@"512525"); return Color4Extensions.FromHex(@"512525");
} }
} }
} }

View File

@ -200,7 +200,7 @@ namespace osu.Game.Online.Leaderboards
scoreLabel = new GlowingSpriteText scoreLabel = new GlowingSpriteText
{ {
TextColour = Color4.White, TextColour = Color4.White,
GlowColour = OsuColour.FromHex(@"83ccfa"), GlowColour = Color4Extensions.FromHex(@"83ccfa"),
Text = score.TotalScore.ToString(@"N0"), Text = score.TotalScore.ToString(@"N0"),
Font = OsuFont.Numeric.With(size: 23), Font = OsuFont.Numeric.With(size: 23),
}, },
@ -325,7 +325,7 @@ namespace osu.Game.Online.Leaderboards
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(icon_size), Size = new Vector2(icon_size),
Rotation = 45, Rotation = 45,
Colour = OsuColour.FromHex(@"3087ac"), Colour = Color4Extensions.FromHex(@"3087ac"),
Icon = FontAwesome.Solid.Square, Icon = FontAwesome.Solid.Square,
Shadow = true, Shadow = true,
}, },
@ -334,7 +334,7 @@ namespace osu.Game.Online.Leaderboards
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(icon_size - 6), Size = new Vector2(icon_size - 6),
Colour = OsuColour.FromHex(@"a4edff"), Colour = Color4Extensions.FromHex(@"a4edff"),
Icon = statistic.Icon, Icon = statistic.Icon,
}, },
}, },
@ -344,7 +344,7 @@ namespace osu.Game.Online.Leaderboards
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
TextColour = Color4.White, TextColour = Color4.White,
GlowColour = OsuColour.FromHex(@"83ccfa"), GlowColour = Color4Extensions.FromHex(@"83ccfa"),
Text = statistic.Value, Text = statistic.Value,
Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold), Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold),
}, },

View File

@ -3,6 +3,7 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
@ -124,7 +125,7 @@ namespace osu.Game.Overlays.BeatmapSet
Icon = FontAwesome.Solid.Square, Icon = FontAwesome.Solid.Square,
Size = new Vector2(12), Size = new Vector2(12),
Rotation = 45, Rotation = 45,
Colour = OsuColour.FromHex(@"441288"), Colour = Color4Extensions.FromHex(@"441288"),
}, },
new SpriteIcon new SpriteIcon
{ {
@ -132,7 +133,7 @@ namespace osu.Game.Overlays.BeatmapSet
Origin = Anchor.Centre, Origin = Anchor.Centre,
Icon = icon, Icon = icon,
Size = new Vector2(12), Size = new Vector2(12),
Colour = OsuColour.FromHex(@"f7dd55"), Colour = Color4Extensions.FromHex(@"f7dd55"),
Scale = new Vector2(0.8f), Scale = new Vector2(0.8f),
}, },
value = new OsuSpriteText value = new OsuSpriteText

View File

@ -2,8 +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.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.BeatmapSet.Buttons namespace osu.Game.Overlays.BeatmapSet.Buttons
@ -19,9 +19,9 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
BackgroundColour = OsuColour.FromHex(@"094c5f"); BackgroundColour = Color4Extensions.FromHex(@"094c5f");
Triangles.ColourLight = OsuColour.FromHex(@"0f7c9b"); Triangles.ColourLight = Color4Extensions.FromHex(@"0f7c9b");
Triangles.ColourDark = OsuColour.FromHex(@"094c5f"); Triangles.ColourDark = Color4Extensions.FromHex(@"094c5f");
Triangles.TriangleScale = 1.5f; Triangles.TriangleScale = 1.5f;
} }
} }

View File

@ -52,22 +52,28 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
highAccuracyColour = colours.GreenLight; highAccuracyColour = colours.GreenLight;
} }
public IReadOnlyList<ScoreInfo> Scores private bool showPerformancePoints;
public void DisplayScores(IReadOnlyList<ScoreInfo> scores, bool showPerformanceColumn)
{ {
set ClearScores();
{
Content = null;
backgroundFlow.Clear();
if (value?.Any() != true) if (!scores.Any())
return; return;
for (int i = 0; i < value.Count; i++) showPerformancePoints = showPerformanceColumn;
backgroundFlow.Add(new ScoreTableRowBackground(i, value[i], row_height));
Columns = createHeaders(value[0]); for (int i = 0; i < scores.Count; i++)
Content = value.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); backgroundFlow.Add(new ScoreTableRowBackground(i, scores[i], row_height));
}
Columns = createHeaders(scores.FirstOrDefault());
Content = scores.Select((s, i) => createContent(i, s)).ToArray().ToRectangular();
}
public void ClearScores()
{
Content = null;
backgroundFlow.Clear();
} }
private TableColumn[] createHeaders(ScoreInfo score) private TableColumn[] createHeaders(ScoreInfo score)
@ -88,11 +94,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
columns.Add(new TableColumn(score.SortedStatistics.LastOrDefault().Key.GetDescription(), Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 45, maxSize: 95))); columns.Add(new TableColumn(score.SortedStatistics.LastOrDefault().Key.GetDescription(), Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 45, maxSize: 95)));
columns.AddRange(new[] if (showPerformancePoints)
{ columns.Add(new TableColumn("pp", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 30)));
new TableColumn("pp", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 30)),
new TableColumn("mods", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), columns.Add(new TableColumn("mods", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)));
});
return columns.ToArray(); return columns.ToArray();
} }
@ -150,24 +155,25 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
}); });
} }
content.AddRange(new Drawable[] if (showPerformancePoints)
{ {
new OsuSpriteText content.Add(new OsuSpriteText
{ {
Text = $@"{score.PP:N0}", Text = $@"{score.PP:N0}",
Font = OsuFont.GetFont(size: text_size) Font = OsuFont.GetFont(size: text_size)
}, });
new FillFlowContainer }
content.Add(new FillFlowContainer
{
Direction = FillDirection.Horizontal,
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(1),
ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m)
{ {
Direction = FillDirection.Horizontal,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Spacing = new Vector2(1), Scale = new Vector2(0.3f)
ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m) })
{
AutoSizeAxes = Axes.Both,
Scale = new Vector2(0.3f)
})
},
}); });
return content.ToArray(); return content.ToArray();

View File

@ -52,17 +52,17 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
if (value?.Scores.Any() != true) if (value?.Scores.Any() != true)
{ {
scoreTable.Scores = null; scoreTable.ClearScores();
scoreTable.Hide(); scoreTable.Hide();
return; return;
} }
var scoreInfos = value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToList(); var scoreInfos = value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToList();
var topScore = scoreInfos.First();
scoreTable.Scores = scoreInfos; scoreTable.DisplayScores(scoreInfos, topScore.Beatmap?.Status == BeatmapSetOnlineStatus.Ranked);
scoreTable.Show(); scoreTable.Show();
var topScore = scoreInfos.First();
var userScore = value.UserScore; var userScore = value.UserScore;
var userScoreInfo = userScore?.Score.CreateScoreInfo(rulesets); var userScoreInfo = userScore?.Score.CreateScoreInfo(rulesets);

View File

@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -96,6 +97,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
totalScoreColumn.Text = $@"{value.TotalScore:N0}"; totalScoreColumn.Text = $@"{value.TotalScore:N0}";
accuracyColumn.Text = value.DisplayAccuracy; accuracyColumn.Text = value.DisplayAccuracy;
maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; maxComboColumn.Text = $@"{value.MaxCombo:N0}x";
ppColumn.Alpha = value.Beatmap?.Status == BeatmapSetOnlineStatus.Ranked ? 1 : 0;
ppColumn.Text = $@"{value.PP:N0}"; ppColumn.Text = $@"{value.PP:N0}";
statisticsColumns.ChildrenEnumerable = value.SortedStatistics.Select(kvp => createStatisticsColumn(kvp.Key, kvp.Value)); statisticsColumns.ChildrenEnumerable = value.SortedStatistics.Select(kvp => createStatisticsColumn(kvp.Key, kvp.Value));

View File

@ -123,7 +123,7 @@ namespace osu.Game.Overlays.Chat
EdgeEffect = new EdgeEffectParameters EdgeEffect = new EdgeEffectParameters
{ {
Radius = 1, Radius = 1,
Colour = OsuColour.FromHex(message.Sender.Colour), Colour = Color4Extensions.FromHex(message.Sender.Colour),
Type = EdgeEffectType.Shadow, Type = EdgeEffectType.Shadow,
}, },
Padding = new MarginPadding { Left = 3, Right = 3, Bottom = 1, Top = -3 }, Padding = new MarginPadding { Left = 3, Right = 3, Bottom = 1, Top = -3 },
@ -172,7 +172,7 @@ namespace osu.Game.Overlays.Chat
t.Font = OsuFont.GetFont(italics: true); t.Font = OsuFont.GetFont(italics: true);
if (senderHasBackground) if (senderHasBackground)
t.Colour = OsuColour.FromHex(message.Sender.Colour); t.Colour = Color4Extensions.FromHex(message.Sender.Colour);
} }
t.Font = t.Font.With(size: TextSize); t.Font = t.Font.With(size: TextSize);
@ -249,41 +249,41 @@ namespace osu.Game.Overlays.Chat
private static readonly Color4[] username_colours = private static readonly Color4[] username_colours =
{ {
OsuColour.FromHex("588c7e"), Color4Extensions.FromHex("588c7e"),
OsuColour.FromHex("b2a367"), Color4Extensions.FromHex("b2a367"),
OsuColour.FromHex("c98f65"), Color4Extensions.FromHex("c98f65"),
OsuColour.FromHex("bc5151"), Color4Extensions.FromHex("bc5151"),
OsuColour.FromHex("5c8bd6"), Color4Extensions.FromHex("5c8bd6"),
OsuColour.FromHex("7f6ab7"), Color4Extensions.FromHex("7f6ab7"),
OsuColour.FromHex("a368ad"), Color4Extensions.FromHex("a368ad"),
OsuColour.FromHex("aa6880"), Color4Extensions.FromHex("aa6880"),
OsuColour.FromHex("6fad9b"), Color4Extensions.FromHex("6fad9b"),
OsuColour.FromHex("f2e394"), Color4Extensions.FromHex("f2e394"),
OsuColour.FromHex("f2ae72"), Color4Extensions.FromHex("f2ae72"),
OsuColour.FromHex("f98f8a"), Color4Extensions.FromHex("f98f8a"),
OsuColour.FromHex("7daef4"), Color4Extensions.FromHex("7daef4"),
OsuColour.FromHex("a691f2"), Color4Extensions.FromHex("a691f2"),
OsuColour.FromHex("c894d3"), Color4Extensions.FromHex("c894d3"),
OsuColour.FromHex("d895b0"), Color4Extensions.FromHex("d895b0"),
OsuColour.FromHex("53c4a1"), Color4Extensions.FromHex("53c4a1"),
OsuColour.FromHex("eace5c"), Color4Extensions.FromHex("eace5c"),
OsuColour.FromHex("ea8c47"), Color4Extensions.FromHex("ea8c47"),
OsuColour.FromHex("fc4f4f"), Color4Extensions.FromHex("fc4f4f"),
OsuColour.FromHex("3d94ea"), Color4Extensions.FromHex("3d94ea"),
OsuColour.FromHex("7760ea"), Color4Extensions.FromHex("7760ea"),
OsuColour.FromHex("af52c6"), Color4Extensions.FromHex("af52c6"),
OsuColour.FromHex("e25696"), Color4Extensions.FromHex("e25696"),
OsuColour.FromHex("677c66"), Color4Extensions.FromHex("677c66"),
OsuColour.FromHex("9b8732"), Color4Extensions.FromHex("9b8732"),
OsuColour.FromHex("8c5129"), Color4Extensions.FromHex("8c5129"),
OsuColour.FromHex("8c3030"), Color4Extensions.FromHex("8c3030"),
OsuColour.FromHex("1f5d91"), Color4Extensions.FromHex("1f5d91"),
OsuColour.FromHex("4335a5"), Color4Extensions.FromHex("4335a5"),
OsuColour.FromHex("812a96"), Color4Extensions.FromHex("812a96"),
OsuColour.FromHex("992861"), Color4Extensions.FromHex("992861"),
}; };
} }
} }

View File

@ -41,10 +41,10 @@ namespace osu.Game.Overlays.Chat.Selection
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Waves.FirstWaveColour = OsuColour.FromHex("353535"); Waves.FirstWaveColour = Color4Extensions.FromHex("353535");
Waves.SecondWaveColour = OsuColour.FromHex("434343"); Waves.SecondWaveColour = Color4Extensions.FromHex("434343");
Waves.ThirdWaveColour = OsuColour.FromHex("515151"); Waves.ThirdWaveColour = Color4Extensions.FromHex("515151");
Waves.FourthWaveColour = OsuColour.FromHex("595959"); Waves.FourthWaveColour = Color4Extensions.FromHex("595959");
Children = new Drawable[] Children = new Drawable[]
{ {
@ -154,7 +154,7 @@ namespace osu.Game.Overlays.Chat.Selection
{ {
bg.Colour = colours.Gray3; bg.Colour = colours.Gray3;
triangles.ColourDark = colours.Gray3; triangles.ColourDark = colours.Gray3;
triangles.ColourLight = OsuColour.FromHex(@"353535"); triangles.ColourLight = Color4Extensions.FromHex(@"353535");
headerBg.Colour = colours.Gray2.Opacity(0.75f); headerBg.Colour = colours.Gray2.Opacity(0.75f);
} }

View File

@ -89,7 +89,7 @@ namespace osu.Game.Overlays.Chat.Tabs
{ {
var user = Value.Users.First(); var user = Value.Users.First();
BackgroundActive = user.Colour != null ? OsuColour.FromHex(user.Colour) : colours.BlueDark; BackgroundActive = user.Colour != null ? Color4Extensions.FromHex(user.Colour) : colours.BlueDark;
BackgroundInactive = BackgroundActive.Darken(0.5f); BackgroundInactive = BackgroundActive.Darken(0.5f);
} }
} }

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

@ -10,7 +10,6 @@ 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.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osuTK; using osuTK;
@ -114,13 +113,13 @@ namespace osu.Game.Overlays.Dialog
new Box new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"221a21"), Colour = Color4Extensions.FromHex(@"221a21"),
}, },
new Triangles new Triangles
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
ColourLight = OsuColour.FromHex(@"271e26"), ColourLight = Color4Extensions.FromHex(@"271e26"),
ColourDark = OsuColour.FromHex(@"1e171e"), ColourDark = Color4Extensions.FromHex(@"1e171e"),
TriangleScale = 4, TriangleScale = 4,
}, },
}, },

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.Dialog namespace osu.Game.Overlays.Dialog
@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Dialog
public PopupDialogButton() public PopupDialogButton()
{ {
Height = 50; Height = 50;
BackgroundColour = OsuColour.FromHex(@"150e14"); BackgroundColour = Color4Extensions.FromHex(@"150e14");
TextSize = 18; TextSize = 18;
} }
} }

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