mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 12:32:56 +08:00
Merge branch 'master' into profile-page-corrections
This commit is contained in:
commit
c20b14868b
@ -44,6 +44,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
private const double time_during_slide_2 = 3000;
|
private const double time_during_slide_2 = 3000;
|
||||||
private const double time_during_slide_3 = 3500;
|
private const double time_during_slide_3 = 3500;
|
||||||
private const double time_during_slide_4 = 3800;
|
private const double time_during_slide_4 = 3800;
|
||||||
|
private const double time_slider_end = 4000;
|
||||||
|
|
||||||
private List<JudgementResult> judgementResults;
|
private List<JudgementResult> judgementResults;
|
||||||
private bool allJudgedFired;
|
private bool allJudgedFired;
|
||||||
@ -284,6 +285,48 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
AddAssert("Tracking acquired", assertMidSliderJudgements);
|
AddAssert("Tracking acquired", assertMidSliderJudgements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scenario:
|
||||||
|
/// - Press a key on the slider head
|
||||||
|
/// - While holding the key, move cursor close to the edge of tracking area
|
||||||
|
/// - Keep the cursor on the edge of tracking area until the slider ends
|
||||||
|
/// Expected Result:
|
||||||
|
/// A passing test case will have the slider track the cursor throughout the whole test.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestTrackingAreaEdge()
|
||||||
|
{
|
||||||
|
performTest(new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start },
|
||||||
|
new OsuReplayFrame { Position = new Vector2(0, OsuHitObject.OBJECT_RADIUS * 1.19f), Actions = { OsuAction.LeftButton }, Time = time_slider_start + 100 },
|
||||||
|
new OsuReplayFrame { Position = new Vector2(slider_path_length, OsuHitObject.OBJECT_RADIUS * 1.199f), Actions = { OsuAction.LeftButton }, Time = time_slider_end },
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Tracking kept", assertGreatJudge);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scenario:
|
||||||
|
/// - Press a key on the slider head
|
||||||
|
/// - While holding the key, move cursor just outside the tracking area
|
||||||
|
/// - Keep the cursor just outside the tracking area until the slider ends
|
||||||
|
/// Expected Result:
|
||||||
|
/// A passing test case will have the slider drop the tracking on frame 2.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestTrackingAreaOutsideEdge()
|
||||||
|
{
|
||||||
|
performTest(new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start },
|
||||||
|
new OsuReplayFrame { Position = new Vector2(0, OsuHitObject.OBJECT_RADIUS * 1.21f), Actions = { OsuAction.LeftButton }, Time = time_slider_start + 100 },
|
||||||
|
new OsuReplayFrame { Position = new Vector2(slider_path_length, OsuHitObject.OBJECT_RADIUS * 1.201f), Actions = { OsuAction.LeftButton }, Time = time_slider_end },
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Tracking dropped", assertMidSliderJudgementFail);
|
||||||
|
}
|
||||||
|
|
||||||
private bool assertGreatJudge() => judgementResults.Last().Type == HitResult.Great;
|
private bool assertGreatJudge() => judgementResults.Last().Type == HitResult.Great;
|
||||||
|
|
||||||
private bool assertHeadMissTailTracked() => judgementResults[^2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss;
|
private bool assertHeadMissTailTracked() => judgementResults[^2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss;
|
||||||
@ -294,6 +337,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
private ScoreAccessibleReplayPlayer currentPlayer;
|
private ScoreAccessibleReplayPlayer currentPlayer;
|
||||||
|
|
||||||
|
private const float slider_path_length = 25;
|
||||||
|
|
||||||
private void performTest(List<ReplayFrame> frames)
|
private void performTest(List<ReplayFrame> frames)
|
||||||
{
|
{
|
||||||
AddStep("load player", () =>
|
AddStep("load player", () =>
|
||||||
@ -309,8 +354,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
Path = new SliderPath(PathType.PerfectCurve, new[]
|
Path = new SliderPath(PathType.PerfectCurve, new[]
|
||||||
{
|
{
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
new Vector2(25, 0),
|
new Vector2(slider_path_length, 0),
|
||||||
}, 25),
|
}, slider_path_length),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BeatmapInfo =
|
BeatmapInfo =
|
||||||
|
@ -23,7 +23,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
public Func<OsuAction?> GetInitialHitAction;
|
public Func<OsuAction?> GetInitialHitAction;
|
||||||
|
|
||||||
private readonly Slider slider;
|
private readonly Slider slider;
|
||||||
public readonly Drawable FollowCircle;
|
private readonly Drawable followCircle;
|
||||||
|
private readonly Drawable trackingArea;
|
||||||
private readonly DrawableSlider drawableSlider;
|
private readonly DrawableSlider drawableSlider;
|
||||||
|
|
||||||
public SliderBall(Slider slider, DrawableSlider drawableSlider = null)
|
public SliderBall(Slider slider, DrawableSlider drawableSlider = null)
|
||||||
@ -38,7 +39,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
FollowCircle = new FollowCircleContainer
|
// This is separate from the visible followcircle to ensure consistent internal tracking area (needed to match osu-stable)
|
||||||
|
trackingArea = new CircularContainer
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
followCircle = new FollowCircleContainer
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
@ -95,8 +103,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
tracking = value;
|
tracking = value;
|
||||||
|
|
||||||
FollowCircle.ScaleTo(tracking ? 2f : 1, 300, Easing.OutQuint);
|
// Tracking area is bigger than the visible followcircle and scales instantly to match osu-stable
|
||||||
FollowCircle.FadeTo(tracking ? 1f : 0, 300, Easing.OutQuint);
|
trackingArea.ScaleTo(tracking ? 2.4f : 1f);
|
||||||
|
followCircle.ScaleTo(tracking ? 2f : 1f, 300, Easing.OutQuint);
|
||||||
|
followCircle.FadeTo(tracking ? 1f : 0, 300, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +159,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
// in valid time range
|
// in valid time range
|
||||||
Time.Current >= slider.StartTime && Time.Current < slider.EndTime &&
|
Time.Current >= slider.StartTime && Time.Current < slider.EndTime &&
|
||||||
// in valid position range
|
// in valid position range
|
||||||
lastScreenSpaceMousePosition.HasValue && FollowCircle.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) &&
|
lastScreenSpaceMousePosition.HasValue && trackingArea.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) &&
|
||||||
// valid action
|
// valid action
|
||||||
(actions?.Any(isValidTrackingAction) ?? false);
|
(actions?.Any(isValidTrackingAction) ?? false);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
typeof(SortTabControl),
|
typeof(SortTabControl),
|
||||||
typeof(ShowChildrenButton),
|
typeof(ShowChildrenButton),
|
||||||
typeof(DeletedCommentsCounter),
|
typeof(DeletedCommentsCounter),
|
||||||
typeof(VotePill)
|
typeof(VotePill),
|
||||||
|
typeof(CommentsPage),
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override bool UseOnlineAPI => true;
|
protected override bool UseOnlineAPI => true;
|
||||||
|
162
osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs
Normal file
162
osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
// 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.Game.Overlays.Comments;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Online
|
||||||
|
{
|
||||||
|
public class TestSceneCommentsPage : OsuTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(DrawableComment),
|
||||||
|
typeof(CommentsPage),
|
||||||
|
};
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||||
|
|
||||||
|
private readonly BindableBool showDeleted = new BindableBool();
|
||||||
|
private readonly Container content;
|
||||||
|
|
||||||
|
public TestSceneCommentsPage()
|
||||||
|
{
|
||||||
|
Add(new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 10),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Width = 200,
|
||||||
|
Child = new OsuCheckbox
|
||||||
|
{
|
||||||
|
Current = showDeleted,
|
||||||
|
LabelText = @"Show Deleted"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("load comments", () => createPage(comment_bundle));
|
||||||
|
AddStep("load empty comments", () => createPage(empty_comment_bundle));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createPage(CommentBundle commentBundle)
|
||||||
|
{
|
||||||
|
content.Clear();
|
||||||
|
content.Add(new CommentsPage(commentBundle)
|
||||||
|
{
|
||||||
|
ShowDeleted = { BindTarget = showDeleted }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly CommentBundle empty_comment_bundle = new CommentBundle
|
||||||
|
{
|
||||||
|
Comments = new List<Comment>(),
|
||||||
|
Total = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly CommentBundle comment_bundle = new CommentBundle
|
||||||
|
{
|
||||||
|
Comments = new List<Comment>
|
||||||
|
{
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Message = "Simple test comment",
|
||||||
|
LegacyName = "TestUser1",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
VotesCount = 5
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Message = "This comment has been deleted :( but visible for admins",
|
||||||
|
LegacyName = "TestUser2",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
DeletedAt = DateTimeOffset.Now,
|
||||||
|
VotesCount = 5
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 3,
|
||||||
|
Message = "This comment is a top level",
|
||||||
|
LegacyName = "TestUser3",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
RepliesCount = 2,
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 4,
|
||||||
|
ParentId = 3,
|
||||||
|
Message = "And this is a reply",
|
||||||
|
RepliesCount = 1,
|
||||||
|
LegacyName = "TestUser1",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 15,
|
||||||
|
ParentId = 4,
|
||||||
|
Message = "Reply to reply",
|
||||||
|
LegacyName = "TestUser1",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 6,
|
||||||
|
ParentId = 3,
|
||||||
|
LegacyName = "TestUser11515",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
DeletedAt = DateTimeOffset.Now,
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 5,
|
||||||
|
Message = "This comment is voted and edited",
|
||||||
|
LegacyName = "BigBrainUser",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
EditedAt = DateTimeOffset.Now,
|
||||||
|
VotesCount = 1000,
|
||||||
|
EditedById = 1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
IncludedComments = new List<Comment>(),
|
||||||
|
UserVotes = new List<long>
|
||||||
|
{
|
||||||
|
5
|
||||||
|
},
|
||||||
|
Users = new List<User>
|
||||||
|
{
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Username = "Good_Admin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TopLevelCount = 4,
|
||||||
|
Total = 7
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,6 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
typeof(HistoricalSection),
|
typeof(HistoricalSection),
|
||||||
typeof(PaginatedMostPlayedBeatmapContainer),
|
typeof(PaginatedMostPlayedBeatmapContainer),
|
||||||
typeof(DrawableMostPlayedBeatmap),
|
typeof(DrawableMostPlayedBeatmap),
|
||||||
typeof(DrawableProfileRow)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
@ -12,6 +13,7 @@ using osu.Game.Graphics;
|
|||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Profile.Sections;
|
using osu.Game.Overlays.Profile.Sections;
|
||||||
using osu.Game.Overlays.Profile.Sections.Recent;
|
using osu.Game.Overlays.Profile.Sections.Recent;
|
||||||
|
|
||||||
@ -28,6 +30,9 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
typeof(MedalIcon)
|
typeof(MedalIcon)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
|
||||||
|
|
||||||
public TestSceneUserProfileRecentSection()
|
public TestSceneUserProfileRecentSection()
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -131,6 +136,22 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
Beatmap = dummyBeatmap,
|
Beatmap = dummyBeatmap,
|
||||||
},
|
},
|
||||||
new APIRecentActivity
|
new APIRecentActivity
|
||||||
|
{
|
||||||
|
User = dummyUser,
|
||||||
|
Type = RecentActivityType.Rank,
|
||||||
|
Rank = 1,
|
||||||
|
Mode = "vitaru",
|
||||||
|
Beatmap = dummyBeatmap,
|
||||||
|
},
|
||||||
|
new APIRecentActivity
|
||||||
|
{
|
||||||
|
User = dummyUser,
|
||||||
|
Type = RecentActivityType.Rank,
|
||||||
|
Rank = 1,
|
||||||
|
Mode = "fruits",
|
||||||
|
Beatmap = dummyBeatmap,
|
||||||
|
},
|
||||||
|
new APIRecentActivity
|
||||||
{
|
{
|
||||||
User = dummyUser,
|
User = dummyUser,
|
||||||
Type = RecentActivityType.RankLost,
|
Type = RecentActivityType.RankLost,
|
||||||
|
175
osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs
Normal file
175
osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Screens.Select.Details;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.SongSelect
|
||||||
|
{
|
||||||
|
[System.ComponentModel.Description("Advanced beatmap statistics display")]
|
||||||
|
public class TestSceneAdvancedStats : OsuTestScene
|
||||||
|
{
|
||||||
|
private TestAdvancedStats advancedStats;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesets { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup() => Schedule(() => Child = advancedStats = new TestAdvancedStats
|
||||||
|
{
|
||||||
|
Width = 500
|
||||||
|
});
|
||||||
|
|
||||||
|
private BeatmapInfo exampleBeatmapInfo => new BeatmapInfo
|
||||||
|
{
|
||||||
|
RulesetID = 0,
|
||||||
|
Ruleset = rulesets.AvailableRulesets.First(),
|
||||||
|
BaseDifficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
CircleSize = 7.2f,
|
||||||
|
DrainRate = 3,
|
||||||
|
OverallDifficulty = 5.7f,
|
||||||
|
ApproachRate = 3.5f
|
||||||
|
},
|
||||||
|
StarDifficulty = 4.5f
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNoMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("no mods selected", () => SelectedMods.Value = Array.Empty<Mod>());
|
||||||
|
|
||||||
|
AddAssert("first bar text is Circle Size", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == "Circle Size");
|
||||||
|
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||||
|
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestManiaFirstBarText()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = new BeatmapInfo
|
||||||
|
{
|
||||||
|
Ruleset = rulesets.GetRuleset(3),
|
||||||
|
BaseDifficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
CircleSize = 5,
|
||||||
|
DrainRate = 4.3f,
|
||||||
|
OverallDifficulty = 4.5f,
|
||||||
|
ApproachRate = 3.1f
|
||||||
|
},
|
||||||
|
StarDifficulty = 8
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("first bar text is Key Count", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == "Key Count");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEasyMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("select EZ mod", () =>
|
||||||
|
{
|
||||||
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
|
SelectedMods.Value = new[] { ruleset.GetAllMods().OfType<ModEasy>().Single() };
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("circle size bar is blue", () => barIsBlue(advancedStats.FirstValue));
|
||||||
|
AddAssert("HP drain bar is blue", () => barIsBlue(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is blue", () => barIsBlue(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is blue", () => barIsBlue(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHardRockMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("select HR mod", () =>
|
||||||
|
{
|
||||||
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
|
SelectedMods.Value = new[] { ruleset.GetAllMods().OfType<ModHardRock>().Single() };
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("circle size bar is red", () => barIsRed(advancedStats.FirstValue));
|
||||||
|
AddAssert("HP drain bar is red", () => barIsRed(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is red", () => barIsRed(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestUnchangedDifficultyAdjustMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("select unchanged Difficulty Adjust mod", () =>
|
||||||
|
{
|
||||||
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
|
var difficultyAdjustMod = ruleset.GetAllMods().OfType<ModDifficultyAdjust>().Single();
|
||||||
|
difficultyAdjustMod.ReadFromDifficulty(advancedStats.Beatmap.BaseDifficulty);
|
||||||
|
SelectedMods.Value = new[] { difficultyAdjustMod };
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||||
|
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChangedDifficultyAdjustMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("select changed Difficulty Adjust mod", () =>
|
||||||
|
{
|
||||||
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
|
var difficultyAdjustMod = ruleset.GetAllMods().OfType<ModDifficultyAdjust>().Single();
|
||||||
|
var originalDifficulty = advancedStats.Beatmap.BaseDifficulty;
|
||||||
|
var adjustedDifficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
CircleSize = originalDifficulty.CircleSize,
|
||||||
|
DrainRate = originalDifficulty.DrainRate - 0.5f,
|
||||||
|
OverallDifficulty = originalDifficulty.OverallDifficulty,
|
||||||
|
ApproachRate = originalDifficulty.ApproachRate + 2.2f,
|
||||||
|
};
|
||||||
|
difficultyAdjustMod.ReadFromDifficulty(adjustedDifficulty);
|
||||||
|
SelectedMods.Value = new[] { difficultyAdjustMod };
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||||
|
AddAssert("drain rate bar is blue", () => barIsBlue(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool barIsWhite(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == Color4.White;
|
||||||
|
private bool barIsBlue(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == colours.BlueDark;
|
||||||
|
private bool barIsRed(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == colours.Red;
|
||||||
|
|
||||||
|
private class TestAdvancedStats : AdvancedStats
|
||||||
|
{
|
||||||
|
public new StatisticRow FirstValue => base.FirstValue;
|
||||||
|
public new StatisticRow HpDrain => base.HpDrain;
|
||||||
|
public new StatisticRow Accuracy => base.Accuracy;
|
||||||
|
public new StatisticRow ApproachRate => base.ApproachRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,14 +3,8 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.SongSelect
|
namespace osu.Game.Tests.Visual.SongSelect
|
||||||
@ -180,27 +174,5 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
OnlineBeatmapID = 162,
|
OnlineBeatmapID = 162,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private RulesetStore rulesets { get; set; }
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private OsuColour colours { get; set; }
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestModAdjustments()
|
|
||||||
{
|
|
||||||
TestAllMetrics();
|
|
||||||
|
|
||||||
Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance();
|
|
||||||
|
|
||||||
AddStep("with EZ mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) });
|
|
||||||
|
|
||||||
AddAssert("first bar coloured blue", () => details.ChildrenOfType<Bar>().Skip(1).First().AccentColour == colours.BlueDark);
|
|
||||||
|
|
||||||
AddStep("with HR mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) });
|
|
||||||
|
|
||||||
AddAssert("first bar coloured red", () => details.ChildrenOfType<Bar>().Skip(1).First().AccentColour == colours.Red);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,14 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
public ShowMoreButton()
|
public ShowMoreButton()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
Height = 30;
|
||||||
|
Width = 140;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Drawable CreateContent() => new CircularContainer
|
protected override Drawable CreateContent() => new CircularContainer
|
||||||
{
|
{
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Size = new Vector2(140, 30),
|
RelativeSizeAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
background = new Box
|
background = new Box
|
||||||
|
@ -6,8 +6,6 @@ using osu.Game.Users;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests.Responses
|
namespace osu.Game.Online.API.Requests.Responses
|
||||||
{
|
{
|
||||||
@ -70,12 +68,10 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
|
|
||||||
public bool IsDeleted => DeletedAt.HasValue;
|
public bool IsDeleted => DeletedAt.HasValue;
|
||||||
|
|
||||||
public bool HasMessage => !string.IsNullOrEmpty(MessageHtml);
|
public bool HasMessage => !string.IsNullOrEmpty(Message);
|
||||||
|
|
||||||
public bool IsVoted { get; set; }
|
public bool IsVoted { get; set; }
|
||||||
|
|
||||||
public string GetMessage => HasMessage ? WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)) : string.Empty;
|
|
||||||
|
|
||||||
public int DeletedChildrenCount => ChildComments.Count(c => c.IsDeleted);
|
public int DeletedChildrenCount => ChildComments.Count(c => c.IsDeleted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,17 +47,18 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
[JsonProperty(@"included_comments")]
|
[JsonProperty(@"included_comments")]
|
||||||
public List<Comment> IncludedComments { get; set; }
|
public List<Comment> IncludedComments { get; set; }
|
||||||
|
|
||||||
|
private List<long> userVotes;
|
||||||
|
|
||||||
[JsonProperty(@"user_votes")]
|
[JsonProperty(@"user_votes")]
|
||||||
private List<long> userVotes
|
public List<long> UserVotes
|
||||||
{
|
{
|
||||||
set => value.ForEach(v =>
|
get => userVotes;
|
||||||
|
set
|
||||||
{
|
{
|
||||||
Comments.ForEach(c =>
|
userVotes = value;
|
||||||
{
|
|
||||||
if (v == c.Id)
|
Comments.ForEach(c => c.IsVoted = value.Contains(c.Id));
|
||||||
c.IsVoted = true;
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<User> users;
|
private List<User> users;
|
||||||
|
@ -68,6 +68,7 @@ namespace osu.Game.Overlays.Comments
|
|||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
|
Name = @"Footer",
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -154,6 +155,7 @@ namespace osu.Game.Overlays.Comments
|
|||||||
{
|
{
|
||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
deletedCommentsCounter.Count.Value = 0;
|
deletedCommentsCounter.Count.Value = 0;
|
||||||
|
moreButton.Show();
|
||||||
moreButton.IsLoading = true;
|
moreButton.IsLoading = true;
|
||||||
content.Clear();
|
content.Clear();
|
||||||
}
|
}
|
||||||
@ -162,25 +164,10 @@ namespace osu.Game.Overlays.Comments
|
|||||||
{
|
{
|
||||||
loadCancellation = new CancellationTokenSource();
|
loadCancellation = new CancellationTokenSource();
|
||||||
|
|
||||||
var page = new FillFlowContainer
|
LoadComponentAsync(new CommentsPage(response)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
ShowDeleted = { BindTarget = ShowDeleted }
|
||||||
AutoSizeAxes = Axes.Y,
|
}, loaded =>
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var c in response.Comments)
|
|
||||||
{
|
|
||||||
if (c.IsTopLevel)
|
|
||||||
{
|
|
||||||
page.Add(new DrawableComment(c)
|
|
||||||
{
|
|
||||||
ShowDeleted = { BindTarget = ShowDeleted }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadComponentAsync(page, loaded =>
|
|
||||||
{
|
{
|
||||||
content.Add(loaded);
|
content.Add(loaded);
|
||||||
|
|
||||||
@ -194,10 +181,12 @@ namespace osu.Game.Overlays.Comments
|
|||||||
moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments;
|
moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments;
|
||||||
moreButton.IsLoading = false;
|
moreButton.IsLoading = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
moreButton.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
commentCounter.Current.Value = response.Total;
|
commentCounter.Current.Value = response.Total;
|
||||||
|
|
||||||
moreButton.FadeTo(response.HasMore ? 1 : 0);
|
|
||||||
}, loadCancellation.Token);
|
}, loadCancellation.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
92
osu.Game/Overlays/Comments/CommentsPage.cs
Normal file
92
osu.Game/Overlays/Comments/CommentsPage.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// 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.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Comments
|
||||||
|
{
|
||||||
|
public class CommentsPage : CompositeDrawable
|
||||||
|
{
|
||||||
|
public readonly BindableBool ShowDeleted = new BindableBool();
|
||||||
|
|
||||||
|
private readonly CommentBundle commentBundle;
|
||||||
|
|
||||||
|
public CommentsPage(CommentBundle commentBundle)
|
||||||
|
{
|
||||||
|
this.commentBundle = commentBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OverlayColourProvider colourProvider)
|
||||||
|
{
|
||||||
|
FillFlowContainer flow;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
AddRangeInternal(new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = colourProvider.Background5
|
||||||
|
},
|
||||||
|
flow = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!commentBundle.Comments.Any())
|
||||||
|
{
|
||||||
|
flow.Add(new NoCommentsPlaceholder());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var c in commentBundle.Comments)
|
||||||
|
{
|
||||||
|
if (c.IsTopLevel)
|
||||||
|
{
|
||||||
|
flow.Add(new DrawableComment(c)
|
||||||
|
{
|
||||||
|
ShowDeleted = { BindTarget = ShowDeleted }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NoCommentsPlaceholder : CompositeDrawable
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OverlayColourProvider colourProvider)
|
||||||
|
{
|
||||||
|
Height = 80;
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AddRangeInternal(new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = colourProvider.Background4
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Margin = new MarginPadding { Left = 50 },
|
||||||
|
Text = @"No comments yet."
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,8 @@ namespace osu.Game.Overlays.Comments
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OverlayColourProvider colourProvider)
|
private void load(OverlayColourProvider colourProvider)
|
||||||
{
|
{
|
||||||
|
Height = 20;
|
||||||
|
|
||||||
IdleColour = colourProvider.Background2;
|
IdleColour = colourProvider.Background2;
|
||||||
HoverColour = colourProvider.Background1;
|
HoverColour = colourProvider.Background1;
|
||||||
ChevronIconColour = colourProvider.Foreground1;
|
ChevronIconColour = colourProvider.Foreground1;
|
||||||
|
@ -213,7 +213,7 @@ namespace osu.Game.Overlays.Comments
|
|||||||
|
|
||||||
if (comment.HasMessage)
|
if (comment.HasMessage)
|
||||||
{
|
{
|
||||||
var formattedSource = MessageFormatter.FormatText(comment.GetMessage);
|
var formattedSource = MessageFormatter.FormatText(comment.Message);
|
||||||
message.AddLinks(formattedSource.Text, formattedSource.Links);
|
message.AddLinks(formattedSource.Text, formattedSource.Links);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +343,7 @@ namespace osu.Game.Overlays.Comments
|
|||||||
if (parentComment == null)
|
if (parentComment == null)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
|
||||||
return parentComment.HasMessage ? parentComment.GetMessage : parentComment.IsDeleted ? @"deleted" : string.Empty;
|
return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? @"deleted" : string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ using osu.Game.Graphics.Containers;
|
|||||||
namespace osu.Game.Overlays.Profile.Sections
|
namespace osu.Game.Overlays.Profile.Sections
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row (see <see cref="DrawableProfileRow"/>).
|
/// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BeatmapMetadataContainer : OsuHoverContainer
|
public abstract class BeatmapMetadataContainer : OsuHoverContainer
|
||||||
{
|
{
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
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.Framework.Input.Events;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Sections
|
|
||||||
{
|
|
||||||
public abstract class DrawableProfileRow : Container
|
|
||||||
{
|
|
||||||
private const int fade_duration = 200;
|
|
||||||
|
|
||||||
private Box underscoreLine;
|
|
||||||
private Box coloredBackground;
|
|
||||||
private Container background;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A visual element displayed to the left of <see cref="LeftFlowContainer"/> content.
|
|
||||||
/// </summary>
|
|
||||||
protected abstract Drawable CreateLeftVisual();
|
|
||||||
|
|
||||||
protected FillFlowContainer LeftFlowContainer { get; private set; }
|
|
||||||
protected FillFlowContainer RightFlowContainer { get; private set; }
|
|
||||||
|
|
||||||
protected override Container<Drawable> Content { get; }
|
|
||||||
|
|
||||||
protected DrawableProfileRow()
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X;
|
|
||||||
Height = 60;
|
|
||||||
|
|
||||||
Content = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Width = 0.97f,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
|
||||||
private void load(OsuColour colour)
|
|
||||||
{
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
background = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
CornerRadius = 3,
|
|
||||||
Alpha = 0,
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Offset = new Vector2(0f, 1f),
|
|
||||||
Radius = 1f,
|
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
|
||||||
},
|
|
||||||
Child = coloredBackground = new Box { RelativeSizeAxes = Axes.Both }
|
|
||||||
},
|
|
||||||
Content,
|
|
||||||
underscoreLine = new Box
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = 1,
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
CreateLeftVisual(),
|
|
||||||
LeftFlowContainer = new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
Margin = new MarginPadding { Left = 10 },
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RightFlowContainer = new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
coloredBackground.Colour = underscoreLine.Colour = colour.Gray4;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e) => true;
|
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
|
||||||
{
|
|
||||||
background.FadeIn(fade_duration, Easing.OutQuint);
|
|
||||||
underscoreLine.FadeOut(fade_duration, Easing.OutQuint);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
|
||||||
{
|
|
||||||
background.FadeOut(fade_duration, Easing.OutQuint);
|
|
||||||
underscoreLine.FadeIn(fade_duration, Easing.OutQuint);
|
|
||||||
base.OnHoverLost(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -44,8 +44,8 @@ namespace osu.Game.Overlays.Profile.Sections
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OverlayColourProvider colourProvider)
|
private void load(OverlayColourProvider colourProvider)
|
||||||
{
|
{
|
||||||
background.Colour = idleColour = colourProvider.Background4;
|
background.Colour = idleColour = colourProvider.Background3;
|
||||||
hoverColour = colourProvider.Background3;
|
hoverColour = colourProvider.Background2;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// 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 JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
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;
|
||||||
@ -16,14 +16,16 @@ using osu.Game.Online.Leaderboards;
|
|||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Sections.Ranks
|
namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||||
{
|
{
|
||||||
public class DrawableProfileScore : CompositeDrawable
|
public class DrawableProfileScore : CompositeDrawable
|
||||||
{
|
{
|
||||||
|
private const int height = 40;
|
||||||
private const int performance_width = 80;
|
private const int performance_width = 80;
|
||||||
private const int content_padding = 10;
|
|
||||||
|
private const float performance_background_shear = 0.45f;
|
||||||
|
private static readonly float performance_background_width = performance_width + (height / 4f * MathF.Tan(performance_background_shear));
|
||||||
|
|
||||||
protected readonly ScoreInfo Score;
|
protected readonly ScoreInfo Score;
|
||||||
|
|
||||||
@ -38,7 +40,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
Score = score;
|
Score = score;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = 40;
|
Height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -51,7 +53,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding { Left = content_padding, Right = performance_width + content_padding },
|
Padding = new MarginPadding { Left = 10, Right = performance_width + 30 },
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
@ -142,20 +144,26 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.TopRight,
|
||||||
Size = new Vector2(1, 0.5f),
|
Origin = Anchor.TopRight,
|
||||||
Colour = Color4.Black.Opacity(0.5f),
|
RelativeSizeAxes = Axes.Y,
|
||||||
Shear = new Vector2(-0.45f, 0),
|
Width = performance_background_width,
|
||||||
|
Height = 0.5f,
|
||||||
|
Colour = colourProvider.Background4,
|
||||||
|
Shear = new Vector2(-performance_background_shear, 0),
|
||||||
EdgeSmoothness = new Vector2(2, 0),
|
EdgeSmoothness = new Vector2(2, 0),
|
||||||
},
|
},
|
||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
RelativePositionAxes = Axes.Y,
|
RelativePositionAxes = Axes.Y,
|
||||||
Size = new Vector2(1, -0.5f),
|
Width = performance_background_width,
|
||||||
|
Height = -0.5f,
|
||||||
Position = new Vector2(0, 1),
|
Position = new Vector2(0, 1),
|
||||||
Colour = Color4.Black.Opacity(0.5f),
|
Colour = colourProvider.Background4,
|
||||||
Shear = new Vector2(0.45f, 0),
|
Shear = new Vector2(performance_background_shear, 0),
|
||||||
EdgeSmoothness = new Vector2(2, 0),
|
EdgeSmoothness = new Vector2(2, 0),
|
||||||
},
|
},
|
||||||
createDrawablePerformance().With(d =>
|
createDrawablePerformance().With(d =>
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
// 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.Linq;
|
||||||
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.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
@ -11,12 +13,19 @@ using osu.Game.Online.API.Requests;
|
|||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Chat;
|
using osu.Game.Online.Chat;
|
||||||
using osu.Game.Online.Leaderboards;
|
using osu.Game.Online.Leaderboards;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Sections.Recent
|
namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||||
{
|
{
|
||||||
public class DrawableRecentActivity : DrawableProfileRow
|
public class DrawableRecentActivity : CompositeDrawable
|
||||||
{
|
{
|
||||||
private IAPIProvider api;
|
private const int font_size = 14;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesets { get; set; }
|
||||||
|
|
||||||
private readonly APIRecentActivity activity;
|
private readonly APIRecentActivity activity;
|
||||||
|
|
||||||
@ -28,139 +37,191 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IAPIProvider api)
|
private void load(OverlayColourProvider colourProvider)
|
||||||
{
|
{
|
||||||
this.api = api;
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
LeftFlowContainer.Padding = new MarginPadding { Left = 10, Right = 160 };
|
AddInternal(new GridContainer
|
||||||
|
|
||||||
LeftFlowContainer.Add(content = new LinkFlowContainer
|
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
ColumnDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.Absolute, size: 28),
|
||||||
|
new Dimension(),
|
||||||
|
new Dimension(GridSizeMode.AutoSize)
|
||||||
|
},
|
||||||
|
RowDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.AutoSize)
|
||||||
|
},
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Child = createIcon().With(icon =>
|
||||||
|
{
|
||||||
|
icon.Anchor = Anchor.Centre;
|
||||||
|
icon.Origin = Anchor.Centre;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
content = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: font_size))
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
},
|
||||||
|
new DrawableDate(activity.CreatedAt)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Colour = colourProvider.Foreground1,
|
||||||
|
Font = OsuFont.GetFont(size: font_size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
RightFlowContainer.Add(new DrawableDate(activity.CreatedAt)
|
createMessage();
|
||||||
{
|
|
||||||
Font = OsuFont.GetFont(size: 13),
|
|
||||||
Colour = OsuColour.Gray(0xAA),
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
});
|
|
||||||
|
|
||||||
var formatted = createMessage();
|
|
||||||
|
|
||||||
content.AddLinks(formatted.Text, formatted.Links);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Drawable CreateLeftVisual()
|
private Drawable createIcon()
|
||||||
{
|
{
|
||||||
switch (activity.Type)
|
switch (activity.Type)
|
||||||
{
|
{
|
||||||
case RecentActivityType.Rank:
|
case RecentActivityType.Rank:
|
||||||
return new UpdateableRank(activity.ScoreRank)
|
return new UpdateableRank(activity.ScoreRank)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.X,
|
||||||
Width = 60,
|
Height = 11,
|
||||||
FillMode = FillMode.Fit,
|
FillMode = FillMode.Fit,
|
||||||
|
Margin = new MarginPadding { Top = 2 }
|
||||||
};
|
};
|
||||||
|
|
||||||
case RecentActivityType.Achievement:
|
case RecentActivityType.Achievement:
|
||||||
return new DelayedLoadWrapper(new MedalIcon(activity.Achievement.Slug)
|
return new DelayedLoadWrapper(new MedalIcon(activity.Achievement.Slug)
|
||||||
{
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit,
|
FillMode = FillMode.Fit,
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.X,
|
||||||
Width = 60,
|
Width = 0.5f,
|
||||||
|
Height = 18
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return new Container
|
return Empty();
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Width = 60,
|
|
||||||
FillMode = FillMode.Fit,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string toAbsoluteUrl(string url) => $"{api.Endpoint}{url}";
|
private void createMessage()
|
||||||
|
|
||||||
private MessageFormatter.MessageFormatterResult createMessage()
|
|
||||||
{
|
{
|
||||||
string userLinkTemplate() => $"[{toAbsoluteUrl(activity.User?.Url)} {activity.User?.Username}]";
|
|
||||||
string beatmapLinkTemplate() => $"[{toAbsoluteUrl(activity.Beatmap?.Url)} {activity.Beatmap?.Title}]";
|
|
||||||
string beatmapsetLinkTemplate() => $"[{toAbsoluteUrl(activity.Beatmapset?.Url)} {activity.Beatmapset?.Title}]";
|
|
||||||
|
|
||||||
string message;
|
|
||||||
|
|
||||||
switch (activity.Type)
|
switch (activity.Type)
|
||||||
{
|
{
|
||||||
case RecentActivityType.Achievement:
|
case RecentActivityType.Achievement:
|
||||||
message = $"{userLinkTemplate()} unlocked the {activity.Achievement.Name} medal!";
|
addUserLink();
|
||||||
|
addText($" unlocked the \"{activity.Achievement.Name}\" medal!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.BeatmapPlaycount:
|
case RecentActivityType.BeatmapPlaycount:
|
||||||
message = $"{beatmapLinkTemplate()} has been played {activity.Count} times!";
|
addBeatmapLink();
|
||||||
|
addText($" has been played {activity.Count} times!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.BeatmapsetApprove:
|
case RecentActivityType.BeatmapsetApprove:
|
||||||
message = $"{beatmapsetLinkTemplate()} has been {activity.Approval.ToString().ToLowerInvariant()}!";
|
addBeatmapsetLink();
|
||||||
|
addText($" has been {activity.Approval.ToString().ToLowerInvariant()}!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.BeatmapsetDelete:
|
case RecentActivityType.BeatmapsetDelete:
|
||||||
message = $"{beatmapsetLinkTemplate()} has been deleted.";
|
addBeatmapsetLink();
|
||||||
|
addText(" has been deleted.");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.BeatmapsetRevive:
|
case RecentActivityType.BeatmapsetRevive:
|
||||||
message = $"{beatmapsetLinkTemplate()} has been revived from eternal slumber by {userLinkTemplate()}.";
|
addBeatmapsetLink();
|
||||||
|
addText(" has been revived from eternal slumber by ");
|
||||||
|
addUserLink();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.BeatmapsetUpdate:
|
case RecentActivityType.BeatmapsetUpdate:
|
||||||
message = $"{userLinkTemplate()} has updated the beatmap {beatmapsetLinkTemplate()}!";
|
addUserLink();
|
||||||
|
addText(" has updated the beatmap ");
|
||||||
|
addBeatmapsetLink();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.BeatmapsetUpload:
|
case RecentActivityType.BeatmapsetUpload:
|
||||||
message = $"{userLinkTemplate()} has submitted a new beatmap {beatmapsetLinkTemplate()}!";
|
addUserLink();
|
||||||
|
addText(" has submitted a new beatmap ");
|
||||||
|
addBeatmapsetLink();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.Medal:
|
case RecentActivityType.Medal:
|
||||||
// apparently this shouldn't exist look at achievement instead (https://github.com/ppy/osu-web/blob/master/resources/assets/coffee/react/profile-page/recent-activity.coffee#L111)
|
// apparently this shouldn't exist look at achievement instead (https://github.com/ppy/osu-web/blob/master/resources/assets/coffee/react/profile-page/recent-activity.coffee#L111)
|
||||||
message = string.Empty;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.Rank:
|
case RecentActivityType.Rank:
|
||||||
message = $"{userLinkTemplate()} achieved rank #{activity.Rank} on {beatmapLinkTemplate()} ({activity.Mode}!)";
|
addUserLink();
|
||||||
|
addText($" achieved rank #{activity.Rank} on ");
|
||||||
|
addBeatmapLink();
|
||||||
|
addText($" ({getRulesetName()})");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.RankLost:
|
case RecentActivityType.RankLost:
|
||||||
message = $"{userLinkTemplate()} has lost first place on {beatmapLinkTemplate()} ({activity.Mode}!)";
|
addUserLink();
|
||||||
|
addText(" has lost first place on ");
|
||||||
|
addBeatmapLink();
|
||||||
|
addText($" ({getRulesetName()})");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.UserSupportAgain:
|
case RecentActivityType.UserSupportAgain:
|
||||||
message = $"{userLinkTemplate()} has once again chosen to support osu! - thanks for your generosity!";
|
addUserLink();
|
||||||
|
addText(" has once again chosen to support osu! - thanks for your generosity!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.UserSupportFirst:
|
case RecentActivityType.UserSupportFirst:
|
||||||
message = $"{userLinkTemplate()} has become an osu!supporter - thanks for your generosity!";
|
addUserLink();
|
||||||
|
addText(" has become an osu!supporter - thanks for your generosity!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.UserSupportGift:
|
case RecentActivityType.UserSupportGift:
|
||||||
message = $"{userLinkTemplate()} has received the gift of osu!supporter!";
|
addUserLink();
|
||||||
|
addText(" has received the gift of osu!supporter!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecentActivityType.UsernameChange:
|
case RecentActivityType.UsernameChange:
|
||||||
message = $"{activity.User?.PreviousUsername} has changed their username to {userLinkTemplate()}!";
|
addText($"{activity.User?.PreviousUsername} has changed their username to ");
|
||||||
break;
|
addUserLink();
|
||||||
|
|
||||||
default:
|
|
||||||
message = string.Empty;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MessageFormatter.FormatText(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string getRulesetName() =>
|
||||||
|
rulesets.AvailableRulesets.FirstOrDefault(r => r.ShortName == activity.Mode)?.Name ?? activity.Mode;
|
||||||
|
|
||||||
|
private void addUserLink()
|
||||||
|
=> content.AddLink(activity.User?.Username, LinkAction.OpenUserProfile, getLinkArgument(activity.User?.Url), creationParameters: t => t.Font = getLinkFont(FontWeight.Bold));
|
||||||
|
|
||||||
|
private void addBeatmapLink()
|
||||||
|
=> content.AddLink(activity.Beatmap?.Title, LinkAction.OpenBeatmap, getLinkArgument(activity.Beatmap?.Url), creationParameters: t => t.Font = getLinkFont());
|
||||||
|
|
||||||
|
private void addBeatmapsetLink()
|
||||||
|
=> content.AddLink(activity.Beatmapset?.Title, LinkAction.OpenBeatmapSet, getLinkArgument(activity.Beatmapset?.Url), creationParameters: t => t.Font = getLinkFont());
|
||||||
|
|
||||||
|
private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.Endpoint}{url}").Argument;
|
||||||
|
|
||||||
|
private FontUsage getLinkFont(FontWeight fontWeight = FontWeight.Regular)
|
||||||
|
=> OsuFont.GetFont(size: font_size, weight: fontWeight, italics: true);
|
||||||
|
|
||||||
|
private void addText(string text)
|
||||||
|
=> content.AddText(text, t => t.Font = OsuFont.GetFont(size: font_size, weight: FontWeight.SemiBold));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
|||||||
|
|
||||||
Child = sprite = new Sprite
|
Child = sprite = new Sprite
|
||||||
{
|
{
|
||||||
Height = 40,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Width = 40,
|
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Sections.Recent
|
namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||||
{
|
{
|
||||||
@ -16,7 +17,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
|||||||
public PaginatedRecentActivityContainer(Bindable<User> user, string header, string missing)
|
public PaginatedRecentActivityContainer(Bindable<User> user, string header, string missing)
|
||||||
: base(user, header, missing)
|
: base(user, header, missing)
|
||||||
{
|
{
|
||||||
ItemsPerPage = 5;
|
ItemsPerPage = 10;
|
||||||
|
ItemsContainer.Spacing = new Vector2(0, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override APIRequest<List<APIRecentActivity>> CreateRequest() =>
|
protected override APIRequest<List<APIRecentActivity>> CreateRequest() =>
|
||||||
|
@ -16,6 +16,7 @@ using System.Collections.Generic;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Overlays.Settings;
|
using osu.Game.Overlays.Settings;
|
||||||
|
|
||||||
@ -26,7 +27,8 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private IBindable<IReadOnlyList<Mod>> mods { get; set; }
|
private IBindable<IReadOnlyList<Mod>> mods { get; set; }
|
||||||
|
|
||||||
private readonly StatisticRow firstValue, hpDrain, accuracy, approachRate, starDifficulty;
|
protected readonly StatisticRow FirstValue, HpDrain, Accuracy, ApproachRate;
|
||||||
|
private readonly StatisticRow starDifficulty;
|
||||||
|
|
||||||
private BeatmapInfo beatmap;
|
private BeatmapInfo beatmap;
|
||||||
|
|
||||||
@ -52,10 +54,10 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
Spacing = new Vector2(4f),
|
Spacing = new Vector2(4f),
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
firstValue = new StatisticRow(), //circle size/key amount
|
FirstValue = new StatisticRow(), //circle size/key amount
|
||||||
hpDrain = new StatisticRow { Title = "HP Drain" },
|
HpDrain = new StatisticRow { Title = "HP Drain" },
|
||||||
accuracy = new StatisticRow { Title = "Accuracy" },
|
Accuracy = new StatisticRow { Title = "Accuracy" },
|
||||||
approachRate = new StatisticRow { Title = "Approach Rate" },
|
ApproachRate = new StatisticRow { Title = "Approach Rate" },
|
||||||
starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" },
|
starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -122,24 +124,24 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
case 3:
|
case 3:
|
||||||
// Account for mania differences locally for now
|
// Account for mania differences locally for now
|
||||||
// Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes
|
// Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes
|
||||||
firstValue.Title = "Key Count";
|
FirstValue.Title = "Key Count";
|
||||||
firstValue.Value = (baseDifficulty?.CircleSize ?? 0, null);
|
FirstValue.Value = (baseDifficulty?.CircleSize ?? 0, null);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
firstValue.Title = "Circle Size";
|
FirstValue.Title = "Circle Size";
|
||||||
firstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize);
|
FirstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
starDifficulty.Value = ((float)(Beatmap?.StarDifficulty ?? 0), null);
|
starDifficulty.Value = ((float)(Beatmap?.StarDifficulty ?? 0), null);
|
||||||
|
|
||||||
hpDrain.Value = (baseDifficulty?.DrainRate ?? 0, adjustedDifficulty?.DrainRate);
|
HpDrain.Value = (baseDifficulty?.DrainRate ?? 0, adjustedDifficulty?.DrainRate);
|
||||||
accuracy.Value = (baseDifficulty?.OverallDifficulty ?? 0, adjustedDifficulty?.OverallDifficulty);
|
Accuracy.Value = (baseDifficulty?.OverallDifficulty ?? 0, adjustedDifficulty?.OverallDifficulty);
|
||||||
approachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate);
|
ApproachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StatisticRow : Container, IHasAccentColour
|
public class StatisticRow : Container, IHasAccentColour
|
||||||
{
|
{
|
||||||
private const float value_width = 25;
|
private const float value_width = 25;
|
||||||
private const float name_width = 70;
|
private const float name_width = 70;
|
||||||
@ -147,7 +149,8 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
private readonly float maxValue;
|
private readonly float maxValue;
|
||||||
private readonly bool forceDecimalPlaces;
|
private readonly bool forceDecimalPlaces;
|
||||||
private readonly OsuSpriteText name, valueText;
|
private readonly OsuSpriteText name, valueText;
|
||||||
private readonly Bar bar, modBar;
|
private readonly Bar bar;
|
||||||
|
public readonly Bar ModBar;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuColour colours { get; set; }
|
private OsuColour colours { get; set; }
|
||||||
@ -173,14 +176,14 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
bar.Length = value.baseValue / maxValue;
|
bar.Length = value.baseValue / maxValue;
|
||||||
|
|
||||||
valueText.Text = (value.adjustedValue ?? value.baseValue).ToString(forceDecimalPlaces ? "0.00" : "0.##");
|
valueText.Text = (value.adjustedValue ?? value.baseValue).ToString(forceDecimalPlaces ? "0.00" : "0.##");
|
||||||
modBar.Length = (value.adjustedValue ?? 0) / maxValue;
|
ModBar.Length = (value.adjustedValue ?? 0) / maxValue;
|
||||||
|
|
||||||
if (value.adjustedValue > value.baseValue)
|
if (Precision.AlmostEquals(value.baseValue, value.adjustedValue ?? value.baseValue, 0.05f))
|
||||||
modBar.AccentColour = valueText.Colour = colours.Red;
|
ModBar.AccentColour = valueText.Colour = Color4.White;
|
||||||
|
else if (value.adjustedValue > value.baseValue)
|
||||||
|
ModBar.AccentColour = valueText.Colour = colours.Red;
|
||||||
else if (value.adjustedValue < value.baseValue)
|
else if (value.adjustedValue < value.baseValue)
|
||||||
modBar.AccentColour = valueText.Colour = colours.BlueDark;
|
ModBar.AccentColour = valueText.Colour = colours.BlueDark;
|
||||||
else
|
|
||||||
modBar.AccentColour = valueText.Colour = Color4.White;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +220,7 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
BackgroundColour = Color4.White.Opacity(0.5f),
|
BackgroundColour = Color4.White.Opacity(0.5f),
|
||||||
Padding = new MarginPadding { Left = name_width + 10, Right = value_width + 10 },
|
Padding = new MarginPadding { Left = name_width + 10, Right = value_width + 10 },
|
||||||
},
|
},
|
||||||
modBar = new Bar
|
ModBar = new Bar
|
||||||
{
|
{
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Loading…
Reference in New Issue
Block a user