mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 12:17:26 +08:00
Merge branch 'user-status-wiring' into discord-rich-presence
This commit is contained in:
commit
ebd66a1e21
@ -1,13 +1,11 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
@ -25,15 +23,13 @@ namespace osu.Desktop.Overlays
|
||||
private OsuConfigManager config;
|
||||
private OsuGameBase game;
|
||||
private NotificationOverlay notificationOverlay;
|
||||
private GameHost host;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host)
|
||||
private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config)
|
||||
{
|
||||
notificationOverlay = notification;
|
||||
this.config = config;
|
||||
this.game = game;
|
||||
this.host = host;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.BottomCentre;
|
||||
@ -102,27 +98,31 @@ namespace osu.Desktop.Overlays
|
||||
|
||||
// only show a notification if we've previously saved a version to the config file (ie. not the first run).
|
||||
if (!string.IsNullOrEmpty(lastVersion))
|
||||
notificationOverlay.Post(new UpdateCompleteNotification(version, host.OpenUrlExternally));
|
||||
notificationOverlay.Post(new UpdateCompleteNotification(version));
|
||||
}
|
||||
}
|
||||
|
||||
private class UpdateCompleteNotification : SimpleNotification
|
||||
{
|
||||
public UpdateCompleteNotification(string version, Action<string> openUrl = null)
|
||||
private readonly string version;
|
||||
|
||||
public UpdateCompleteNotification(string version)
|
||||
{
|
||||
this.version = version;
|
||||
Text = $"You are now running osu!lazer {version}.\nClick to see what's new!";
|
||||
Icon = FontAwesome.Solid.CheckSquare;
|
||||
Activated = delegate
|
||||
{
|
||||
openUrl?.Invoke($"https://osu.ppy.sh/home/changelog/lazer/{version}");
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OsuColour colours, ChangelogOverlay changelog)
|
||||
{
|
||||
Icon = FontAwesome.Solid.CheckSquare;
|
||||
IconBackgound.Colour = colours.BlueDark;
|
||||
|
||||
Activated = delegate
|
||||
{
|
||||
changelog.ShowBuild("lazer", version);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
70
osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs
Normal file
70
osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs
Normal file
@ -0,0 +1,70 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Changelog;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneChangelogOverlay : OsuTestScene
|
||||
{
|
||||
private ChangelogOverlay changelog;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(UpdateStreamBadgeArea),
|
||||
typeof(UpdateStreamBadge),
|
||||
typeof(ChangelogHeader),
|
||||
typeof(ChangelogContent),
|
||||
typeof(ChangelogListing),
|
||||
typeof(ChangelogSingleBuild),
|
||||
typeof(ChangelogBuild),
|
||||
};
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Add(changelog = new ChangelogOverlay());
|
||||
AddStep(@"Show", changelog.Show);
|
||||
AddStep(@"Hide", changelog.Hide);
|
||||
|
||||
AddWaitStep("wait for hide", 3);
|
||||
|
||||
AddStep(@"Show with Lazer 2018.712.0", () =>
|
||||
{
|
||||
changelog.ShowBuild(new APIChangelogBuild
|
||||
{
|
||||
Version = "2018.712.0",
|
||||
DisplayVersion = "2018.712.0",
|
||||
UpdateStream = new APIUpdateStream { Name = "lazer" },
|
||||
ChangelogEntries = new List<APIChangelogEntry>
|
||||
{
|
||||
new APIChangelogEntry
|
||||
{
|
||||
Category = "Test",
|
||||
Title = "Title",
|
||||
MessageHtml = "Message",
|
||||
}
|
||||
}
|
||||
});
|
||||
changelog.Show();
|
||||
});
|
||||
|
||||
AddWaitStep("wait for show", 3);
|
||||
AddStep(@"Hide", changelog.Hide);
|
||||
AddWaitStep("wait for hide", 3);
|
||||
|
||||
AddStep(@"Show with listing", () =>
|
||||
{
|
||||
changelog.ShowListing();
|
||||
changelog.Show();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
@ -19,6 +20,8 @@ namespace osu.Game.Configuration
|
||||
|
||||
private readonly RulesetInfo ruleset;
|
||||
|
||||
private readonly bool legacySettingsExist;
|
||||
|
||||
protected DatabasedConfigManager(SettingsStore settings, RulesetInfo ruleset = null, int? variant = null)
|
||||
{
|
||||
this.settings = settings;
|
||||
@ -26,6 +29,7 @@ namespace osu.Game.Configuration
|
||||
this.variant = variant;
|
||||
|
||||
databasedSettings = settings.Query(ruleset?.ID, variant);
|
||||
legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out var _));
|
||||
|
||||
InitialiseDefaults();
|
||||
}
|
||||
@ -43,7 +47,18 @@ namespace osu.Game.Configuration
|
||||
{
|
||||
base.AddBindable(lookup, bindable);
|
||||
|
||||
var setting = databasedSettings.Find(s => (int)s.Key == (int)(object)lookup);
|
||||
if (legacySettingsExist)
|
||||
{
|
||||
var legacySetting = databasedSettings.Find(s => s.Key == ((int)(object)lookup).ToString());
|
||||
|
||||
if (legacySetting != null)
|
||||
{
|
||||
bindable.Parse(legacySetting.Value);
|
||||
settings.Delete(legacySetting);
|
||||
}
|
||||
}
|
||||
|
||||
var setting = databasedSettings.Find(s => s.Key == lookup.ToString());
|
||||
|
||||
if (setting != null)
|
||||
{
|
||||
@ -53,7 +68,7 @@ namespace osu.Game.Configuration
|
||||
{
|
||||
settings.Update(setting = new DatabasedSetting
|
||||
{
|
||||
Key = lookup,
|
||||
Key = lookup.ToString(),
|
||||
Value = bindable.Value,
|
||||
RulesetID = ruleset?.ID,
|
||||
Variant = variant,
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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.
|
||||
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
@ -16,11 +16,7 @@ namespace osu.Game.Configuration
|
||||
public int? Variant { get; set; }
|
||||
|
||||
[Column("Key")]
|
||||
public int IntKey
|
||||
{
|
||||
get => (int)Key;
|
||||
private set => Key = value;
|
||||
}
|
||||
public string Key { get; set; }
|
||||
|
||||
[Column("Value")]
|
||||
public string StringValue
|
||||
@ -29,10 +25,9 @@ namespace osu.Game.Configuration
|
||||
set => Value = value;
|
||||
}
|
||||
|
||||
public object Key;
|
||||
public object Value;
|
||||
|
||||
public DatabasedSetting(object key, object value)
|
||||
public DatabasedSetting(string key, object value)
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
|
@ -37,5 +37,11 @@ namespace osu.Game.Configuration
|
||||
|
||||
SettingChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void Delete(DatabasedSetting setting)
|
||||
{
|
||||
using (var usage = ContextFactory.GetForWrite())
|
||||
usage.Context.Remove(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,8 +40,10 @@ namespace osu.Game.Graphics
|
||||
// See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less
|
||||
public readonly Color4 PurpleLighter = FromHex(@"eeeeff");
|
||||
public readonly Color4 PurpleLight = FromHex(@"aa88ff");
|
||||
public readonly Color4 PurpleLightAlternative = FromHex(@"cba4da");
|
||||
public readonly Color4 Purple = FromHex(@"8866ee");
|
||||
public readonly Color4 PurpleDark = FromHex(@"6644cc");
|
||||
public readonly Color4 PurpleDarkAlternative = FromHex(@"312436");
|
||||
public readonly Color4 PurpleDarker = FromHex(@"441188");
|
||||
|
||||
public readonly Color4 PinkLighter = FromHex(@"ffddee");
|
||||
|
@ -78,7 +78,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
Current.DisabledChanged += disabled =>
|
||||
{
|
||||
Alpha = disabled ? 0.3f : 1;
|
||||
labelSpriteText.Alpha = Nub.Alpha = disabled ? 0.3f : 1;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -76,11 +76,11 @@ namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
titleText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 25),
|
||||
Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light),
|
||||
},
|
||||
pageText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 25),
|
||||
Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Migrations
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Key = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Key = table.Column<int>(type: "TEXT", nullable: false),
|
||||
RulesetID = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
Value = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Variant = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Migrations
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.1-servicing-10028");
|
||||
.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||
{
|
||||
@ -198,7 +198,7 @@ namespace osu.Game.Migrations
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntKey")
|
||||
b.Property<string>("Key")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
21
osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs
Normal file
21
osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class GetChangelogBuildRequest : APIRequest<APIChangelogBuild>
|
||||
{
|
||||
private readonly string name;
|
||||
private readonly string version;
|
||||
|
||||
public GetChangelogBuildRequest(string streamName, string buildVersion)
|
||||
{
|
||||
name = streamName;
|
||||
version = buildVersion;
|
||||
}
|
||||
|
||||
protected override string Target => $@"changelog/{name}/{version}";
|
||||
}
|
||||
}
|
12
osu.Game/Online/API/Requests/GetChangelogRequest.cs
Normal file
12
osu.Game/Online/API/Requests/GetChangelogRequest.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// 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.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class GetChangelogRequest : APIRequest<APIChangelogIndex>
|
||||
{
|
||||
protected override string Target => @"changelog";
|
||||
}
|
||||
}
|
49
osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs
Normal file
49
osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs
Normal file
@ -0,0 +1,49 @@
|
||||
// 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 Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APIChangelogBuild : IEquatable<APIChangelogBuild>
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public long Id { get; set; }
|
||||
|
||||
[JsonProperty("version")]
|
||||
public string Version { get; set; }
|
||||
|
||||
[JsonProperty("display_version")]
|
||||
public string DisplayVersion { get; set; }
|
||||
|
||||
[JsonProperty("users")]
|
||||
public long Users { get; set; }
|
||||
|
||||
[JsonProperty("created_at")]
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
[JsonProperty("update_stream")]
|
||||
public APIUpdateStream UpdateStream { get; set; }
|
||||
|
||||
[JsonProperty("changelog_entries")]
|
||||
public List<APIChangelogEntry> ChangelogEntries { get; set; }
|
||||
|
||||
[JsonProperty("versions")]
|
||||
public VersionNatigation Versions { get; set; }
|
||||
|
||||
public class VersionNatigation
|
||||
{
|
||||
[JsonProperty("next")]
|
||||
public APIChangelogBuild Next { get; set; }
|
||||
|
||||
[JsonProperty("previous")]
|
||||
public APIChangelogBuild Previous { get; set; }
|
||||
}
|
||||
|
||||
public bool Equals(APIChangelogBuild other) => Id == other?.Id;
|
||||
|
||||
public override string ToString() => $"{UpdateStream.DisplayName} {DisplayVersion}";
|
||||
}
|
||||
}
|
47
osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs
Normal file
47
osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs
Normal 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 System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APIChangelogEntry
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public long? Id { get; set; }
|
||||
|
||||
[JsonProperty("repository")]
|
||||
public string Repository { get; set; }
|
||||
|
||||
[JsonProperty("github_pull_request_id")]
|
||||
public long? GithubPullRequestId { get; set; }
|
||||
|
||||
[JsonProperty("github_url")]
|
||||
public string GithubUrl { get; set; }
|
||||
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("category")]
|
||||
public string Category { get; set; }
|
||||
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
|
||||
[JsonProperty("message_html")]
|
||||
public string MessageHtml { get; set; }
|
||||
|
||||
[JsonProperty("major")]
|
||||
public bool? Major { get; set; }
|
||||
|
||||
[JsonProperty("created_at")]
|
||||
public DateTimeOffset? CreatedAt { get; set; }
|
||||
|
||||
[JsonProperty("github_user")]
|
||||
public APIChangelogUser GithubUser { get; set; }
|
||||
}
|
||||
}
|
17
osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs
Normal file
17
osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APIChangelogIndex
|
||||
{
|
||||
[JsonProperty]
|
||||
public List<APIChangelogBuild> Builds;
|
||||
|
||||
[JsonProperty]
|
||||
public List<APIUpdateStream> Streams;
|
||||
}
|
||||
}
|
28
osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs
Normal file
28
osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs
Normal file
@ -0,0 +1,28 @@
|
||||
// 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 Newtonsoft.Json;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APIChangelogUser
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public long? Id { get; set; }
|
||||
|
||||
[JsonProperty("display_name")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[JsonProperty("github_url")]
|
||||
public string GithubUrl { get; set; }
|
||||
|
||||
[JsonProperty("osu_username")]
|
||||
public string OsuUsername { get; set; }
|
||||
|
||||
[JsonProperty("user_id")]
|
||||
public long? UserId { get; set; }
|
||||
|
||||
[JsonProperty("user_url")]
|
||||
public string UserUrl { get; set; }
|
||||
}
|
||||
}
|
60
osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs
Normal file
60
osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs
Normal 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 System;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APIUpdateStream : IEquatable<APIUpdateStream>
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public long Id { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("is_featured")]
|
||||
public bool IsFeatured { get; set; }
|
||||
|
||||
[JsonProperty("display_name")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[JsonProperty("latest_build")]
|
||||
public APIChangelogBuild LatestBuild { get; set; }
|
||||
|
||||
public bool Equals(APIUpdateStream other) => Id == other?.Id;
|
||||
|
||||
public ColourInfo Colour
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Name)
|
||||
{
|
||||
case "stable40":
|
||||
return new Color4(102, 204, 255, 255);
|
||||
|
||||
case "stable":
|
||||
return new Color4(34, 153, 187, 255);
|
||||
|
||||
case "beta40":
|
||||
return new Color4(255, 221, 85, 255);
|
||||
|
||||
case "cuttingedge":
|
||||
return new Color4(238, 170, 0, 255);
|
||||
|
||||
case "lazer":
|
||||
return new Color4(237, 18, 33, 255);
|
||||
|
||||
case "web":
|
||||
return new Color4(136, 102, 238, 255);
|
||||
|
||||
default:
|
||||
return new Color4(0, 0, 0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -435,6 +435,7 @@ namespace osu.Game
|
||||
loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal, true);
|
||||
loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add, true);
|
||||
loadComponentSingleFile(settings = new SettingsOverlay { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add, true);
|
||||
var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true);
|
||||
loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true);
|
||||
loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true);
|
||||
|
||||
@ -492,7 +493,7 @@ namespace osu.Game
|
||||
}
|
||||
|
||||
// ensure only one of these overlays are open at once.
|
||||
var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct };
|
||||
var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct, changelogOverlay };
|
||||
overlays.AddRange(singleDisplayOverlays);
|
||||
|
||||
foreach (var overlay in singleDisplayOverlays)
|
||||
|
167
osu.Game/Overlays/Changelog/ChangelogBuild.cs
Normal file
167
osu.Game/Overlays/Changelog/ChangelogBuild.cs
Normal file
@ -0,0 +1,167 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
public class ChangelogBuild : FillFlowContainer
|
||||
{
|
||||
public const float HORIZONTAL_PADDING = 70;
|
||||
|
||||
public Action<APIChangelogBuild> SelectBuild;
|
||||
|
||||
protected readonly APIChangelogBuild Build;
|
||||
|
||||
public readonly FillFlowContainer ChangelogEntries;
|
||||
|
||||
public ChangelogBuild(APIChangelogBuild build)
|
||||
{
|
||||
Build = build;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Direction = FillDirection.Vertical;
|
||||
Padding = new MarginPadding { Horizontal = HORIZONTAL_PADDING };
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
CreateHeader(),
|
||||
ChangelogEntries = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
},
|
||||
};
|
||||
|
||||
foreach (var categoryEntries in build.ChangelogEntries.GroupBy(b => b.Category).OrderBy(c => c.Key))
|
||||
{
|
||||
ChangelogEntries.Add(new OsuSpriteText
|
||||
{
|
||||
Text = categoryEntries.Key,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24),
|
||||
Margin = new MarginPadding { Top = 35, Bottom = 15 },
|
||||
});
|
||||
|
||||
var fontLarge = OsuFont.GetFont(size: 18);
|
||||
var fontMedium = OsuFont.GetFont(size: 14);
|
||||
var fontSmall = OsuFont.GetFont(size: 12);
|
||||
|
||||
foreach (APIChangelogEntry entry in categoryEntries)
|
||||
{
|
||||
LinkFlowContainer title = new LinkFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Full,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Margin = new MarginPadding { Vertical = 5 },
|
||||
};
|
||||
|
||||
title.AddIcon(FontAwesome.Solid.Check, t =>
|
||||
{
|
||||
t.Font = fontSmall;
|
||||
t.Padding = new MarginPadding { Left = -17, Right = 5 };
|
||||
});
|
||||
|
||||
title.AddText(entry.Title, t => { t.Font = fontLarge; });
|
||||
|
||||
if (!string.IsNullOrEmpty(entry.Repository))
|
||||
{
|
||||
title.AddText(" (", t => t.Font = fontLarge);
|
||||
title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External,
|
||||
creationParameters: t => { t.Font = fontLarge; });
|
||||
title.AddText(")", t => t.Font = fontLarge);
|
||||
}
|
||||
|
||||
title.AddText(" by ", t => t.Font = fontMedium);
|
||||
|
||||
if (entry.GithubUser.UserId != null)
|
||||
title.AddUserLink(new User
|
||||
{
|
||||
Username = entry.GithubUser.OsuUsername,
|
||||
Id = entry.GithubUser.UserId.Value
|
||||
}, t => t.Font = fontMedium);
|
||||
else if (entry.GithubUser.GithubUrl != null)
|
||||
title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => t.Font = fontMedium);
|
||||
else
|
||||
title.AddText(entry.GithubUser.DisplayName, t => t.Font = fontSmall);
|
||||
|
||||
ChangelogEntries.Add(title);
|
||||
|
||||
if (!string.IsNullOrEmpty(entry.MessageHtml))
|
||||
{
|
||||
TextFlowContainer message = new TextFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
};
|
||||
|
||||
// todo: use markdown parsing once API returns markdown
|
||||
message.AddText(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty), t =>
|
||||
{
|
||||
t.Font = fontSmall;
|
||||
t.Colour = new Color4(235, 184, 254, 255);
|
||||
});
|
||||
|
||||
ChangelogEntries.Add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual FillFlowContainer CreateHeader() => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Margin = new MarginPadding { Top = 20 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuHoverContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Action = () => SelectBuild?.Invoke(Build),
|
||||
Child = new FillFlowContainer<SpriteText>
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Horizontal = 40 },
|
||||
Children = new[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = Build.UpdateStream.DisplayName,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 19),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = " ",
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 19),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = Build.DisplayVersion,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Light, size: 19),
|
||||
Colour = Build.UpdateStream.Colour,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
25
osu.Game/Overlays/Changelog/ChangelogContent.cs
Normal file
25
osu.Game/Overlays/Changelog/ChangelogContent.cs
Normal 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.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
public class ChangelogContent : FillFlowContainer
|
||||
{
|
||||
public Action<APIChangelogBuild> BuildSelected;
|
||||
|
||||
public void SelectBuild(APIChangelogBuild build) => BuildSelected?.Invoke(build);
|
||||
|
||||
public ChangelogContent()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Direction = FillDirection.Vertical;
|
||||
Padding = new MarginPadding { Bottom = 100 };
|
||||
}
|
||||
}
|
||||
}
|
170
osu.Game/Overlays/Changelog/ChangelogHeader.cs
Normal file
170
osu.Game/Overlays/Changelog/ChangelogHeader.cs
Normal file
@ -0,0 +1,170 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
public class ChangelogHeader : OverlayHeader
|
||||
{
|
||||
public readonly Bindable<APIChangelogBuild> Current = new Bindable<APIChangelogBuild>();
|
||||
|
||||
public Action ListingSelected;
|
||||
|
||||
public UpdateStreamBadgeArea Streams;
|
||||
|
||||
private const string listing_string = "Listing";
|
||||
|
||||
public ChangelogHeader()
|
||||
{
|
||||
TabControl.AddItem(listing_string);
|
||||
TabControl.Current.ValueChanged += e =>
|
||||
{
|
||||
if (e.NewValue == listing_string)
|
||||
ListingSelected?.Invoke();
|
||||
};
|
||||
|
||||
Current.ValueChanged += showBuild;
|
||||
|
||||
Streams.Current.ValueChanged += e =>
|
||||
{
|
||||
if (e.NewValue?.LatestBuild != null && e.NewValue != Current.Value?.UpdateStream)
|
||||
Current.Value = e.NewValue.LatestBuild;
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
TabControl.AccentColour = colours.Violet;
|
||||
}
|
||||
|
||||
private ChangelogHeaderTitle title;
|
||||
|
||||
private void showBuild(ValueChangedEvent<APIChangelogBuild> e)
|
||||
{
|
||||
if (e.OldValue != null)
|
||||
TabControl.RemoveItem(e.OldValue.ToString());
|
||||
|
||||
if (e.NewValue != null)
|
||||
{
|
||||
TabControl.AddItem(e.NewValue.ToString());
|
||||
TabControl.Current.Value = e.NewValue.ToString();
|
||||
|
||||
Streams.Current.Value = Streams.Items.FirstOrDefault(s => s.Name == e.NewValue.UpdateStream.Name);
|
||||
|
||||
title.Version = e.NewValue.UpdateStream.DisplayName;
|
||||
}
|
||||
else
|
||||
{
|
||||
TabControl.Current.Value = listing_string;
|
||||
Streams.Current.Value = null;
|
||||
title.Version = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Drawable CreateBackground() => new HeaderBackground();
|
||||
|
||||
protected override Drawable CreateContent() => new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Streams = new UpdateStreamBadgeArea(),
|
||||
}
|
||||
};
|
||||
|
||||
protected override ScreenTitle CreateTitle() => title = new ChangelogHeaderTitle();
|
||||
|
||||
public class HeaderBackground : Sprite
|
||||
{
|
||||
public HeaderBackground()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
FillMode = FillMode.Fill;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Texture = textures.Get(@"Headers/changelog");
|
||||
}
|
||||
}
|
||||
|
||||
private class ChangelogHeaderTitle : ScreenTitle
|
||||
{
|
||||
public string Version
|
||||
{
|
||||
set => Section = value ?? listing_string;
|
||||
}
|
||||
|
||||
public ChangelogHeaderTitle()
|
||||
{
|
||||
Title = "Changelog";
|
||||
Version = null;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
AccentColour = colours.Violet;
|
||||
}
|
||||
|
||||
protected override Drawable CreateIcon() => new ChangelogIcon();
|
||||
|
||||
internal class ChangelogIcon : CompositeDrawable
|
||||
{
|
||||
private const float circle_allowance = 0.8f;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures, OsuColour colours)
|
||||
{
|
||||
Size = new Vector2(ICON_SIZE / circle_allowance);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new CircularContainer
|
||||
{
|
||||
Masking = true,
|
||||
BorderColour = colours.Violet,
|
||||
BorderThickness = 3,
|
||||
MaskingSmoothness = 1,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Texture = textures.Get(@"Icons/changelog"),
|
||||
Size = new Vector2(circle_allowance),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colours.Violet,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
80
osu.Game/Overlays/Changelog/ChangelogListing.cs
Normal file
80
osu.Game/Overlays/Changelog/ChangelogListing.cs
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
public class ChangelogListing : ChangelogContent
|
||||
{
|
||||
private readonly List<APIChangelogBuild> entries;
|
||||
|
||||
public ChangelogListing(List<APIChangelogBuild> entries)
|
||||
{
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
DateTime currentDate = DateTime.MinValue;
|
||||
|
||||
if (entries == null) return;
|
||||
|
||||
foreach (APIChangelogBuild build in entries)
|
||||
{
|
||||
if (build.CreatedAt.Date != currentDate)
|
||||
{
|
||||
if (Children.Count != 0)
|
||||
{
|
||||
Add(new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 2,
|
||||
Colour = new Color4(17, 17, 17, 255),
|
||||
Margin = new MarginPadding { Top = 30 },
|
||||
});
|
||||
}
|
||||
|
||||
Add(new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Margin = new MarginPadding { Top = 15 },
|
||||
Text = build.CreatedAt.Date.ToString("dd MMM yyyy"),
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 24),
|
||||
Colour = OsuColour.FromHex(@"FD5"),
|
||||
});
|
||||
|
||||
currentDate = build.CreatedAt.Date;
|
||||
}
|
||||
else
|
||||
{
|
||||
Add(new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
Padding = new MarginPadding { Horizontal = ChangelogBuild.HORIZONTAL_PADDING },
|
||||
Margin = new MarginPadding { Top = 30 },
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = new Color4(32, 24, 35, 255),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Add(new ChangelogBuild(build) { SelectBuild = SelectBuild });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
142
osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs
Normal file
142
osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs
Normal file
@ -0,0 +1,142 @@
|
||||
// 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 System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
public class ChangelogSingleBuild : ChangelogContent
|
||||
{
|
||||
private APIChangelogBuild build;
|
||||
|
||||
public ChangelogSingleBuild(APIChangelogBuild build)
|
||||
{
|
||||
this.build = build;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(CancellationToken? cancellation, IAPIProvider api)
|
||||
{
|
||||
bool complete = false;
|
||||
|
||||
var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version);
|
||||
req.Success += res =>
|
||||
{
|
||||
build = res;
|
||||
complete = true;
|
||||
};
|
||||
req.Failure += _ => complete = true;
|
||||
|
||||
// This is done on a separate thread to support cancellation below
|
||||
Task.Run(() => req.Perform(api));
|
||||
|
||||
while (!complete)
|
||||
{
|
||||
if (cancellation?.IsCancellationRequested == true)
|
||||
{
|
||||
req.Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
|
||||
if (build != null)
|
||||
Child = new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild };
|
||||
}
|
||||
|
||||
public class ChangelogBuildWithNavigation : ChangelogBuild
|
||||
{
|
||||
public ChangelogBuildWithNavigation(APIChangelogBuild build)
|
||||
: base(build)
|
||||
{
|
||||
}
|
||||
|
||||
protected override FillFlowContainer CreateHeader()
|
||||
{
|
||||
var fill = base.CreateHeader();
|
||||
|
||||
foreach (var existing in fill.Children.OfType<OsuHoverContainer>())
|
||||
{
|
||||
existing.Scale = new Vector2(1.25f);
|
||||
existing.Action = null;
|
||||
|
||||
existing.Add(new OsuSpriteText
|
||||
{
|
||||
Text = Build.CreatedAt.Date.ToString("dd MMM yyyy"),
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 14),
|
||||
Colour = OsuColour.FromHex(@"FD5"),
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Margin = new MarginPadding { Top = 5 },
|
||||
});
|
||||
}
|
||||
|
||||
NavigationIconButton left, right;
|
||||
|
||||
fill.AddRange(new[]
|
||||
{
|
||||
left = new NavigationIconButton(Build.Versions?.Previous)
|
||||
{
|
||||
Icon = FontAwesome.Solid.ChevronLeft,
|
||||
SelectBuild = b => SelectBuild(b)
|
||||
},
|
||||
right = new NavigationIconButton(Build.Versions?.Next)
|
||||
{
|
||||
Icon = FontAwesome.Solid.ChevronRight,
|
||||
SelectBuild = b => SelectBuild(b)
|
||||
},
|
||||
});
|
||||
|
||||
fill.SetLayoutPosition(left, -1);
|
||||
fill.SetLayoutPosition(right, 1);
|
||||
|
||||
return fill;
|
||||
}
|
||||
}
|
||||
|
||||
private class NavigationIconButton : IconButton
|
||||
{
|
||||
public Action<APIChangelogBuild> SelectBuild;
|
||||
|
||||
public NavigationIconButton(APIChangelogBuild build)
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
if (build == null) return;
|
||||
|
||||
TooltipText = build.DisplayVersion;
|
||||
|
||||
Action = () =>
|
||||
{
|
||||
SelectBuild?.Invoke(build);
|
||||
Enabled.Value = false;
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
HoverColour = colours.GreyVioletLight.Opacity(0.6f);
|
||||
FlashColour = colours.GreyVioletLighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
157
osu.Game/Overlays/Changelog/UpdateStreamBadge.cs
Normal file
157
osu.Game/Overlays/Changelog/UpdateStreamBadge.cs
Normal file
@ -0,0 +1,157 @@
|
||||
// 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 Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
public class UpdateStreamBadge : TabItem<APIUpdateStream>
|
||||
{
|
||||
private const float badge_height = 66.5f;
|
||||
private const float badge_width = 100;
|
||||
private const float transition_duration = 100;
|
||||
|
||||
private readonly ExpandingBar expandingBar;
|
||||
private SampleChannel sampleClick;
|
||||
private SampleChannel sampleHover;
|
||||
|
||||
private readonly FillFlowContainer<SpriteText> text;
|
||||
|
||||
public readonly Bindable<APIUpdateStream> SelectedTab = new Bindable<APIUpdateStream>();
|
||||
|
||||
private readonly Container fadeContainer;
|
||||
|
||||
public UpdateStreamBadge(APIUpdateStream stream)
|
||||
: base(stream)
|
||||
{
|
||||
Size = new Vector2(stream.IsFeatured ? badge_width * 2 : badge_width, badge_height);
|
||||
Padding = new MarginPadding(5);
|
||||
|
||||
Child = fadeContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
text = new FillFlowContainer<SpriteText>
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = stream.DisplayName,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12),
|
||||
Margin = new MarginPadding { Top = 6 },
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = stream.LatestBuild.DisplayVersion,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Light, size: 16),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = stream.LatestBuild.Users > 0 ? $"{stream.LatestBuild.Users:N0} {"user".Pluralize(stream.LatestBuild.Users == 1)} online" : null,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 10),
|
||||
Colour = new Color4(203, 164, 218, 255),
|
||||
},
|
||||
}
|
||||
},
|
||||
expandingBar = new ExpandingBar
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Colour = stream.Colour,
|
||||
ExpandedSize = 4,
|
||||
CollapsedSize = 2,
|
||||
IsCollapsed = true
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
SelectedTab.BindValueChanged(_ => updateState(), true);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleClick = audio.Sample.Get(@"UI/generic-select-soft");
|
||||
sampleHover = audio.Sample.Get(@"UI/generic-hover-soft");
|
||||
}
|
||||
|
||||
protected override void OnActivated() => updateState();
|
||||
|
||||
protected override void OnDeactivated() => updateState();
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
sampleClick?.Play();
|
||||
return base.OnClick(e);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
sampleHover?.Play();
|
||||
updateState();
|
||||
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateState();
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
// Expand based on the local state
|
||||
bool shouldExpand = Active.Value || IsHovered;
|
||||
|
||||
// Expand based on whether no build is selected and the badge area is hovered
|
||||
shouldExpand |= SelectedTab.Value == null && !externalDimRequested;
|
||||
|
||||
if (shouldExpand)
|
||||
{
|
||||
expandingBar.Expand();
|
||||
fadeContainer.FadeTo(1, transition_duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
expandingBar.Collapse();
|
||||
fadeContainer.FadeTo(0.5f, transition_duration);
|
||||
}
|
||||
|
||||
text.FadeTo(externalDimRequested && !IsHovered ? 0.5f : 1, transition_duration);
|
||||
}
|
||||
|
||||
private bool externalDimRequested;
|
||||
|
||||
public void EnableDim()
|
||||
{
|
||||
externalDimRequested = true;
|
||||
updateState();
|
||||
}
|
||||
|
||||
public void DisableDim()
|
||||
{
|
||||
externalDimRequested = false;
|
||||
updateState();
|
||||
}
|
||||
}
|
||||
}
|
75
osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs
Normal file
75
osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs
Normal file
@ -0,0 +1,75 @@
|
||||
// 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.Input.Events;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
public class UpdateStreamBadgeArea : TabControl<APIUpdateStream>
|
||||
{
|
||||
public UpdateStreamBadgeArea()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
AddInternal(new Box
|
||||
{
|
||||
Colour = Color4.Black,
|
||||
Alpha = 0.12f,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
}
|
||||
|
||||
public void Populate(List<APIUpdateStream> streams)
|
||||
{
|
||||
Current.Value = null;
|
||||
|
||||
foreach (APIUpdateStream updateStream in streams)
|
||||
AddItem(updateStream);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
foreach (UpdateStreamBadge streamBadge in TabContainer.Children.OfType<UpdateStreamBadge>())
|
||||
streamBadge.EnableDim();
|
||||
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
foreach (UpdateStreamBadge streamBadge in TabContainer.Children.OfType<UpdateStreamBadge>())
|
||||
streamBadge.DisableDim();
|
||||
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
protected override TabFillFlowContainer CreateTabFlow()
|
||||
{
|
||||
var flow = base.CreateTabFlow();
|
||||
|
||||
flow.RelativeSizeAxes = Axes.X;
|
||||
flow.AutoSizeAxes = Axes.Y;
|
||||
flow.AllowMultiline = true;
|
||||
flow.Padding = new MarginPadding
|
||||
{
|
||||
Vertical = 20,
|
||||
Horizontal = 85,
|
||||
};
|
||||
|
||||
return flow;
|
||||
}
|
||||
|
||||
protected override Dropdown<APIUpdateStream> CreateDropdown() => null;
|
||||
|
||||
protected override TabItem<APIUpdateStream> CreateTabItem(APIUpdateStream value) =>
|
||||
new UpdateStreamBadge(value) { SelectedTab = { BindTarget = Current } };
|
||||
}
|
||||
}
|
210
osu.Game/Overlays/ChangelogOverlay.cs
Normal file
210
osu.Game/Overlays/ChangelogOverlay.cs
Normal file
@ -0,0 +1,210 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays.Changelog;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
public class ChangelogOverlay : FullscreenOverlay
|
||||
{
|
||||
public readonly Bindable<APIChangelogBuild> Current = new Bindable<APIChangelogBuild>();
|
||||
|
||||
private ChangelogHeader header;
|
||||
|
||||
private Container<ChangelogContent> content;
|
||||
|
||||
private SampleChannel sampleBack;
|
||||
|
||||
private List<APIChangelogBuild> builds;
|
||||
|
||||
private List<APIUpdateStream> streams;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, OsuColour colour)
|
||||
{
|
||||
Waves.FirstWaveColour = colour.GreyVioletLight;
|
||||
Waves.SecondWaveColour = colour.GreyViolet;
|
||||
Waves.ThirdWaveColour = colour.GreyVioletDark;
|
||||
Waves.FourthWaveColour = colour.GreyVioletDarker;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colour.PurpleDarkAlternative,
|
||||
},
|
||||
new ScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ScrollbarVisible = false,
|
||||
Child = new ReverseChildIDFillFlowContainer<Drawable>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
header = new ChangelogHeader
|
||||
{
|
||||
ListingSelected = ShowListing,
|
||||
},
|
||||
content = new Container<ChangelogContent>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
sampleBack = audio.Sample.Get(@"UI/generic-select-soft");
|
||||
|
||||
header.Current.BindTo(Current);
|
||||
|
||||
Current.BindValueChanged(e =>
|
||||
{
|
||||
if (e.NewValue != null)
|
||||
loadContent(new ChangelogSingleBuild(e.NewValue));
|
||||
else
|
||||
loadContent(new ChangelogListing(builds));
|
||||
});
|
||||
}
|
||||
|
||||
public void ShowListing()
|
||||
{
|
||||
Current.Value = null;
|
||||
State = Visibility.Visible;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches and shows a specific build from a specific update stream.
|
||||
/// </summary>
|
||||
/// <param name="build">Must contain at least <see cref="APIUpdateStream.Name"/> and
|
||||
/// <see cref="APIChangelogBuild.Version"/>. If <see cref="APIUpdateStream.DisplayName"/> and
|
||||
/// <see cref="APIChangelogBuild.DisplayVersion"/> are specified, the header will instantly display them.</param>
|
||||
public void ShowBuild([NotNull] APIChangelogBuild build)
|
||||
{
|
||||
if (build == null) throw new ArgumentNullException(nameof(build));
|
||||
|
||||
Current.Value = build;
|
||||
State = Visibility.Visible;
|
||||
}
|
||||
|
||||
public void ShowBuild([NotNull] string updateStream, [NotNull] string version)
|
||||
{
|
||||
if (updateStream == null) throw new ArgumentNullException(nameof(updateStream));
|
||||
if (version == null) throw new ArgumentNullException(nameof(version));
|
||||
|
||||
performAfterFetch(() =>
|
||||
{
|
||||
var build = builds.Find(b => b.Version == version && b.UpdateStream.Name == updateStream)
|
||||
?? streams.Find(s => s.Name == updateStream)?.LatestBuild;
|
||||
|
||||
if (build != null)
|
||||
ShowBuild(build);
|
||||
});
|
||||
|
||||
State = Visibility.Visible;
|
||||
}
|
||||
|
||||
public override bool OnPressed(GlobalAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.Back:
|
||||
if (Current.Value == null)
|
||||
{
|
||||
State = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
Current.Value = null;
|
||||
sampleBack?.Play();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
base.PopIn();
|
||||
|
||||
if (initialFetchTask == null)
|
||||
// fetch and refresh to show listing, if no other request was made via Show methods
|
||||
performAfterFetch(() => Current.TriggerChange());
|
||||
}
|
||||
|
||||
private Task initialFetchTask;
|
||||
|
||||
private void performAfterFetch(Action action) => fetchListing()?.ContinueWith(_ => Schedule(action));
|
||||
|
||||
private Task fetchListing()
|
||||
{
|
||||
if (initialFetchTask != null)
|
||||
return initialFetchTask;
|
||||
|
||||
return initialFetchTask = Task.Run(async () =>
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
var req = new GetChangelogRequest();
|
||||
req.Success += res =>
|
||||
{
|
||||
// remap streams to builds to ensure model equality
|
||||
res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id));
|
||||
res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id));
|
||||
|
||||
builds = res.Builds;
|
||||
streams = res.Streams;
|
||||
|
||||
header.Streams.Populate(res.Streams);
|
||||
|
||||
tcs.SetResult(true);
|
||||
};
|
||||
req.Failure += _ => initialFetchTask = null;
|
||||
req.Perform(API);
|
||||
|
||||
await tcs.Task;
|
||||
});
|
||||
}
|
||||
|
||||
private CancellationTokenSource loadContentCancellation;
|
||||
|
||||
private void loadContent(ChangelogContent newContent)
|
||||
{
|
||||
content.FadeTo(0.2f, 300, Easing.OutQuint);
|
||||
|
||||
loadContentCancellation?.Cancel();
|
||||
|
||||
LoadComponentAsync(newContent, c =>
|
||||
{
|
||||
content.FadeIn(300, Easing.OutQuint);
|
||||
|
||||
c.BuildSelected = ShowBuild;
|
||||
content.Child = c;
|
||||
}, (loadContentCancellation = new CancellationTokenSource()).Token);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,22 +3,14 @@
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays.KeyBinding;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
public class KeyBindingPanel : SettingsPanel
|
||||
public class KeyBindingPanel : SettingsSubPanel
|
||||
{
|
||||
protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!");
|
||||
|
||||
@ -29,84 +21,6 @@ namespace osu.Game.Overlays
|
||||
|
||||
foreach (var ruleset in rulesets.AvailableRulesets)
|
||||
AddSection(new RulesetBindingsSection(ruleset));
|
||||
|
||||
AddInternal(new BackButton
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Action = Hide
|
||||
});
|
||||
}
|
||||
|
||||
public KeyBindingPanel()
|
||||
: base(true)
|
||||
{
|
||||
}
|
||||
|
||||
private class BackButton : OsuClickableContainer, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
private AspectContainer aspect;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Size = new Vector2(Sidebar.DEFAULT_WIDTH);
|
||||
Children = new Drawable[]
|
||||
{
|
||||
aspect = new AspectContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Y = -15,
|
||||
Size = new Vector2(15),
|
||||
Shadow = true,
|
||||
Icon = FontAwesome.Solid.ChevronLeft
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Y = 15,
|
||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold),
|
||||
Text = @"back",
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
aspect.ScaleTo(0.75f, 2000, Easing.OutQuint);
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
aspect.ScaleTo(1, 1000, Easing.OutElastic);
|
||||
return base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.Back:
|
||||
Click();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(GlobalAction action) => false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,17 +3,15 @@
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
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 osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Users;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Overlays.Profile.Sections.Kudosu
|
||||
{
|
||||
@ -24,46 +22,27 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu
|
||||
public KudosuInfo(Bindable<User> user)
|
||||
{
|
||||
this.user.BindTo(user);
|
||||
|
||||
CountSection total;
|
||||
CountSection avaliable;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Masking = true;
|
||||
CornerRadius = 3;
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Offset = new Vector2(0f, 1f),
|
||||
Radius = 3f,
|
||||
Colour = Color4.Black.Opacity(0.2f),
|
||||
};
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.2f)
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5, 0),
|
||||
Children = new[]
|
||||
{
|
||||
total = new CountSection(
|
||||
"Total Kudosu Earned",
|
||||
"Based on how much of a contribution the user has made to beatmap moderation. See this link for more information."
|
||||
),
|
||||
avaliable = new CountSection(
|
||||
"Kudosu Avaliable",
|
||||
"Kudosu can be traded for kudosu stars, which will help your beatmap get more attention. This is the number of kudosu you haven't traded in yet."
|
||||
),
|
||||
total = new CountTotal(),
|
||||
avaliable = new CountAvailable()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.user.ValueChanged += u =>
|
||||
{
|
||||
total.Count = u.NewValue?.Kudosu.Total ?? 0;
|
||||
@ -73,21 +52,43 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu
|
||||
|
||||
protected override bool OnClick(ClickEvent e) => true;
|
||||
|
||||
private class CountAvailable : CountSection
|
||||
{
|
||||
public CountAvailable()
|
||||
: base("Kudosu Avaliable")
|
||||
{
|
||||
DescriptionText.Text = "Kudosu can be traded for kudosu stars, which will help your beatmap get more attention. This is the number of kudosu you haven't traded in yet.";
|
||||
}
|
||||
}
|
||||
|
||||
private class CountTotal : CountSection
|
||||
{
|
||||
public CountTotal()
|
||||
: base("Total Kudosu Earned")
|
||||
{
|
||||
DescriptionText.AddText("Based on how much of a contribution the user has made to beatmap moderation. See ");
|
||||
DescriptionText.AddLink("this link", "https://osu.ppy.sh/wiki/Kudosu");
|
||||
DescriptionText.AddText(" for more information.");
|
||||
}
|
||||
}
|
||||
|
||||
private class CountSection : Container
|
||||
{
|
||||
private readonly OsuSpriteText valueText;
|
||||
protected readonly LinkFlowContainer DescriptionText;
|
||||
private readonly Box lineBackground;
|
||||
|
||||
public new int Count
|
||||
{
|
||||
set => valueText.Text = value.ToString();
|
||||
}
|
||||
|
||||
public CountSection(string header, string description)
|
||||
public CountSection(string header)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Width = 0.5f;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Padding = new MarginPadding { Horizontal = 10, Top = 10, Bottom = 20 };
|
||||
Padding = new MarginPadding { Top = 10, Bottom = 20 };
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
@ -96,39 +97,42 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
new CircularContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5, 0),
|
||||
Children = new Drawable[]
|
||||
Masking = true,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 5,
|
||||
Child = lineBackground = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Text = header + ":",
|
||||
Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular, italics: true)
|
||||
Text = header,
|
||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold)
|
||||
},
|
||||
valueText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Text = "0",
|
||||
Font = OsuFont.GetFont(size: 40, weight: FontWeight.Regular, italics: true),
|
||||
Font = OsuFont.GetFont(size: 40, weight: FontWeight.Light),
|
||||
UseFullGlyphHeight = false,
|
||||
}
|
||||
}
|
||||
},
|
||||
new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 19))
|
||||
DescriptionText = new LinkFlowContainer(t => t.Font = t.Font.With(size: 14))
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Text = description
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
lineBackground.Colour = colours.Yellow;
|
||||
DescriptionText.Colour = colours.GreySeafoamLighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,12 @@ using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Overlays.Settings.Sections;
|
||||
using osuTK.Graphics;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
public class SettingsOverlay : SettingsPanel
|
||||
{
|
||||
private readonly KeyBindingPanel keyBindingPanel;
|
||||
|
||||
protected override IEnumerable<SettingsSection> CreateSections() => new SettingsSection[]
|
||||
{
|
||||
new GeneralSection(),
|
||||
@ -22,29 +21,37 @@ namespace osu.Game.Overlays
|
||||
new GameplaySection(),
|
||||
new AudioSection(),
|
||||
new SkinSection(),
|
||||
new InputSection(keyBindingPanel),
|
||||
new InputSection(createSubPanel(new KeyBindingPanel())),
|
||||
new OnlineSection(),
|
||||
new MaintenanceSection(),
|
||||
new DebugSection(),
|
||||
};
|
||||
|
||||
private readonly List<SettingsSubPanel> subPanels = new List<SettingsSubPanel>();
|
||||
|
||||
protected override Drawable CreateHeader() => new SettingsHeader("settings", "Change the way osu! behaves");
|
||||
protected override Drawable CreateFooter() => new SettingsFooter();
|
||||
|
||||
public SettingsOverlay()
|
||||
: base(true)
|
||||
{
|
||||
keyBindingPanel = new KeyBindingPanel
|
||||
{
|
||||
Depth = 1,
|
||||
Anchor = Anchor.TopRight,
|
||||
};
|
||||
keyBindingPanel.StateChanged += keyBindingPanelStateChanged;
|
||||
}
|
||||
|
||||
public override bool AcceptsFocus => keyBindingPanel.State != Visibility.Visible;
|
||||
public override bool AcceptsFocus => subPanels.All(s => s.State != Visibility.Visible);
|
||||
|
||||
private void keyBindingPanelStateChanged(Visibility visibility)
|
||||
private T createSubPanel<T>(T subPanel)
|
||||
where T : SettingsSubPanel
|
||||
{
|
||||
subPanel.Depth = 1;
|
||||
subPanel.Anchor = Anchor.TopRight;
|
||||
subPanel.StateChanged += subPanelStateChanged;
|
||||
|
||||
subPanels.Add(subPanel);
|
||||
|
||||
return subPanel;
|
||||
}
|
||||
|
||||
private void subPanelStateChanged(Visibility visibility)
|
||||
{
|
||||
switch (visibility)
|
||||
{
|
||||
@ -66,12 +73,13 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
}
|
||||
|
||||
protected override float ExpandedPosition => keyBindingPanel.State == Visibility.Visible ? -WIDTH : base.ExpandedPosition;
|
||||
protected override float ExpandedPosition => subPanels.Any(s => s.State == Visibility.Visible) ? -WIDTH : base.ExpandedPosition;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ContentContainer.Add(keyBindingPanel);
|
||||
foreach (var s in subPanels)
|
||||
ContentContainer.Add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,6 @@ namespace osu.Game.Overlays
|
||||
|
||||
protected const float WIDTH = 400;
|
||||
|
||||
private const float sidebar_padding = 10;
|
||||
|
||||
protected Container<Drawable> ContentContainer;
|
||||
|
||||
protected override Container<Drawable> Content => ContentContainer;
|
||||
|
103
osu.Game/Overlays/SettingsSubPanel.cs
Normal file
103
osu.Game/Overlays/SettingsSubPanel.cs
Normal 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.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
public abstract class SettingsSubPanel : SettingsPanel
|
||||
{
|
||||
protected SettingsSubPanel()
|
||||
: base(true)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddInternal(new BackButton
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Action = Hide
|
||||
});
|
||||
}
|
||||
|
||||
private class BackButton : OsuClickableContainer, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
private AspectContainer aspect;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Size = new Vector2(Sidebar.DEFAULT_WIDTH);
|
||||
Children = new Drawable[]
|
||||
{
|
||||
aspect = new AspectContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Y = -15,
|
||||
Size = new Vector2(15),
|
||||
Shadow = true,
|
||||
Icon = FontAwesome.Solid.ChevronLeft
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Y = 15,
|
||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold),
|
||||
Text = @"back",
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
aspect.ScaleTo(0.75f, 2000, Easing.OutQuint);
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
aspect.ScaleTo(1, 1000, Easing.OutElastic);
|
||||
return base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.Back:
|
||||
Click();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(GlobalAction action) => false;
|
||||
}
|
||||
}
|
||||
}
|
@ -69,6 +69,7 @@ namespace osu.Game.Overlays.Toolbar
|
||||
AutoSizeAxes = Axes.X,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ToolbarChangelogButton(),
|
||||
new ToolbarDirectButton(),
|
||||
new ToolbarChatButton(),
|
||||
new ToolbarSocialButton(),
|
||||
|
22
osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs
Normal file
22
osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs
Normal file
@ -0,0 +1,22 @@
|
||||
// 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.Sprites;
|
||||
|
||||
namespace osu.Game.Overlays.Toolbar
|
||||
{
|
||||
public class ToolbarChangelogButton : ToolbarOverlayToggleButton
|
||||
{
|
||||
public ToolbarChangelogButton()
|
||||
{
|
||||
SetIcon(FontAwesome.Solid.Bullhorn);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(ChangelogOverlay changelog)
|
||||
{
|
||||
StateContainer = changelog;
|
||||
}
|
||||
}
|
||||
}
|
@ -176,7 +176,7 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
private void updateIdleState(bool isIdle)
|
||||
{
|
||||
if (isIdle && State != ButtonSystemState.Exit)
|
||||
if (isIdle && State != ButtonSystemState.Exit && State != ButtonSystemState.EnteringMode)
|
||||
State = ButtonSystemState.Initial;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user