mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 16:12:57 +08:00
Merge branch 'master' into reduce-skin-lookup-overhead
This commit is contained in:
commit
5c59818b03
@ -5,23 +5,23 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Desktop.Windows
|
||||
{
|
||||
public class GameplayWinKeyBlocker : Component
|
||||
{
|
||||
private Bindable<bool> disableWinKey;
|
||||
private Bindable<bool> localUserPlaying;
|
||||
private IBindable<bool> localUserPlaying;
|
||||
|
||||
[Resolved]
|
||||
private GameHost host { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGame game, OsuConfigManager config)
|
||||
private void load(ILocalUserPlayInfo localUserInfo, OsuConfigManager config)
|
||||
{
|
||||
localUserPlaying = game.LocalUserPlaying.GetBoundCopy();
|
||||
localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy();
|
||||
localUserPlaying.BindValueChanged(_ => updateBlocking());
|
||||
|
||||
disableWinKey = config.GetBindable<bool>(OsuSetting.GameplayDisableWinKey);
|
||||
|
@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
||||
{
|
||||
public class Movement : StrainSkill
|
||||
public class Movement : StrainDecaySkill
|
||||
{
|
||||
private const float absolute_player_positioning_error = 16f;
|
||||
private const float normalized_hitobject_radius = 41.0f;
|
||||
|
@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
||||
{
|
||||
public class Strain : StrainSkill
|
||||
public class Strain : StrainDecaySkill
|
||||
{
|
||||
private const double individual_decay_base = 0.125;
|
||||
private const double overall_decay_base = 0.30;
|
||||
@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
||||
return individualStrain + overallStrain - CurrentStrain;
|
||||
}
|
||||
|
||||
protected override double GetPeakStrain(double offset)
|
||||
protected override double CalculateInitialStrain(double offset)
|
||||
=> applyDecay(individualStrain, offset - Previous[0].StartTime, individual_decay_base)
|
||||
+ applyDecay(overallStrain, offset - Previous[0].StartTime, overall_decay_base);
|
||||
|
||||
|
@ -10,7 +10,7 @@ using osu.Framework.Utils;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
{
|
||||
public abstract class OsuStrainSkill : StrainSkill
|
||||
public abstract class OsuStrainSkill : StrainDecaySkill
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of sections with the highest strains, which the peak strain reductions will apply to.
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
|
||||
/// <summary>
|
||||
/// Calculates the colour coefficient of taiko difficulty.
|
||||
/// </summary>
|
||||
public class Colour : StrainSkill
|
||||
public class Colour : StrainDecaySkill
|
||||
{
|
||||
protected override double SkillMultiplier => 1;
|
||||
protected override double StrainDecayBase => 0.4;
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
|
||||
/// <summary>
|
||||
/// Calculates the rhythm coefficient of taiko difficulty.
|
||||
/// </summary>
|
||||
public class Rhythm : StrainSkill
|
||||
public class Rhythm : StrainDecaySkill
|
||||
{
|
||||
protected override double SkillMultiplier => 10;
|
||||
protected override double StrainDecayBase => 0;
|
||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
|
||||
/// <remarks>
|
||||
/// The reference play style chosen uses two hands, with full alternating (the hand changes after every hit).
|
||||
/// </remarks>
|
||||
public class Stamina : StrainSkill
|
||||
public class Stamina : StrainDecaySkill
|
||||
{
|
||||
protected override double SkillMultiplier => 1;
|
||||
protected override double StrainDecayBase => 0.4;
|
||||
|
@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
var room = RoomManager.Rooms[1];
|
||||
|
||||
RoomManager.RemoveRoom(room);
|
||||
RoomManager.AddRoom(room);
|
||||
RoomManager.AddOrUpdateRoom(room);
|
||||
});
|
||||
|
||||
AddAssert("no selection", () => checkRoomSelected(null));
|
||||
@ -115,11 +115,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
AddUntilStep("4 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 4);
|
||||
|
||||
AddStep("filter one room", () => container.Filter(new FilterCriteria { SearchString = "1" }));
|
||||
AddStep("filter one room", () => container.Filter.Value = new FilterCriteria { SearchString = "1" });
|
||||
|
||||
AddUntilStep("1 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 1);
|
||||
|
||||
AddStep("remove filter", () => container.Filter(null));
|
||||
AddStep("remove filter", () => container.Filter.Value = null);
|
||||
|
||||
AddUntilStep("4 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 4);
|
||||
}
|
||||
@ -131,13 +131,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("add rooms", () => RoomManager.AddRooms(3, new CatchRuleset().RulesetInfo));
|
||||
|
||||
// Todo: What even is this case...?
|
||||
AddStep("set empty filter criteria", () => container.Filter(null));
|
||||
AddStep("set empty filter criteria", () => container.Filter.Value = null);
|
||||
AddUntilStep("5 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 5);
|
||||
|
||||
AddStep("filter osu! rooms", () => container.Filter(new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo }));
|
||||
AddStep("filter osu! rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo });
|
||||
AddUntilStep("2 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 2);
|
||||
|
||||
AddStep("filter catch rooms", () => container.Filter(new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo }));
|
||||
AddStep("filter catch rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo });
|
||||
AddUntilStep("3 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 3);
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,17 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osu.Game.Users;
|
||||
|
||||
@ -23,6 +27,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Resolved]
|
||||
private OsuGameBase game { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private OsuConfigManager config { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
|
||||
@ -80,6 +87,32 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddWaitStep("wait a bit", 20);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSpectatorPlayerInteractiveElementsHidden()
|
||||
{
|
||||
HUDVisibilityMode originalConfigValue = default;
|
||||
|
||||
AddStep("get original config hud visibility", () => originalConfigValue = config.Get<HUDVisibilityMode>(OsuSetting.HUDVisibilityMode));
|
||||
AddStep("set config hud visibility to always", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always));
|
||||
|
||||
start(new[] { PLAYER_1_ID, PLAYER_2_ID });
|
||||
loadSpectateScreen(false);
|
||||
|
||||
AddUntilStep("wait for player loaders", () => this.ChildrenOfType<PlayerLoader>().Count() == 2);
|
||||
AddAssert("all player loader settings hidden", () => this.ChildrenOfType<PlayerLoader>().All(l => !l.ChildrenOfType<FillFlowContainer<PlayerSettingsGroup>>().Any()));
|
||||
|
||||
AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded);
|
||||
|
||||
// components wrapped in skinnable target containers load asynchronously, potentially taking more than one frame to load.
|
||||
// therefore use until step rather than direct assert to account for that.
|
||||
AddUntilStep("all interactive elements removed", () => this.ChildrenOfType<Player>().All(p =>
|
||||
!p.ChildrenOfType<PlayerSettingsOverlay>().Any() &&
|
||||
!p.ChildrenOfType<HoldForMenuButton>().Any() &&
|
||||
p.ChildrenOfType<SongProgressBar>().SingleOrDefault()?.ShowHandle == false));
|
||||
|
||||
AddStep("restore config hud visibility", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTeamDisplay()
|
||||
{
|
||||
|
@ -44,6 +44,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
private TestMultiplayer multiplayerScreen;
|
||||
private TestMultiplayerClient client;
|
||||
|
||||
private TestRequestHandlingMultiplayerRoomManager roomManager => multiplayerScreen.RoomManager;
|
||||
|
||||
[Cached(typeof(UserLookupCache))]
|
||||
private UserLookupCache lookupCache = new TestUserLookupCache();
|
||||
|
||||
@ -68,7 +70,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
AddStep("load dependencies", () =>
|
||||
{
|
||||
client = new TestMultiplayerClient(multiplayerScreen.RoomManager);
|
||||
client = new TestMultiplayerClient(roomManager);
|
||||
|
||||
// The screen gets suspended so it stops receiving updates.
|
||||
Child = client;
|
||||
@ -132,39 +134,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Test]
|
||||
public void TestExitMidJoin()
|
||||
{
|
||||
Room room = null;
|
||||
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
room = new Room
|
||||
{
|
||||
Name = { Value = "Test Room" },
|
||||
Playlist =
|
||||
{
|
||||
new PlaylistItem
|
||||
{
|
||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo },
|
||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria());
|
||||
AddStep("select room", () => InputManager.Key(Key.Down));
|
||||
AddStep("join room and immediately exit", () =>
|
||||
{
|
||||
multiplayerScreen.ChildrenOfType<LoungeSubScreen>().Single().Open(room);
|
||||
Schedule(() => Stack.CurrentScreen.Exit());
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestJoinRoomWithoutPassword()
|
||||
{
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
multiplayerScreen.RoomManager.AddRoom(new Room
|
||||
roomManager.AddServerSideRoom(new Room
|
||||
{
|
||||
Name = { Value = "Test Room" },
|
||||
Playlist =
|
||||
@ -178,7 +150,39 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria());
|
||||
AddStep("refresh rooms", () => this.ChildrenOfType<LoungeSubScreen>().Single().UpdateFilter());
|
||||
AddUntilStep("wait for room", () => this.ChildrenOfType<DrawableRoom>().Any());
|
||||
|
||||
AddStep("select room", () => InputManager.Key(Key.Down));
|
||||
AddStep("join room and immediately exit select", () =>
|
||||
{
|
||||
InputManager.Key(Key.Enter);
|
||||
Schedule(() => Stack.CurrentScreen.Exit());
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestJoinRoomWithoutPassword()
|
||||
{
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
roomManager.AddServerSideRoom(new Room
|
||||
{
|
||||
Name = { Value = "Test Room" },
|
||||
Playlist =
|
||||
{
|
||||
new PlaylistItem
|
||||
{
|
||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo },
|
||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("refresh rooms", () => this.ChildrenOfType<LoungeSubScreen>().Single().UpdateFilter());
|
||||
AddUntilStep("wait for room", () => this.ChildrenOfType<DrawableRoom>().Any());
|
||||
|
||||
AddStep("select room", () => InputManager.Key(Key.Down));
|
||||
AddStep("join room", () => InputManager.Key(Key.Enter));
|
||||
|
||||
@ -211,7 +215,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
multiplayerScreen.RoomManager.AddRoom(new Room
|
||||
roomManager.AddServerSideRoom(new Room
|
||||
{
|
||||
Name = { Value = "Test Room" },
|
||||
Password = { Value = "password" },
|
||||
@ -226,7 +230,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria());
|
||||
AddStep("refresh rooms", () => this.ChildrenOfType<LoungeSubScreen>().Single().UpdateFilter());
|
||||
AddUntilStep("wait for room", () => this.ChildrenOfType<DrawableRoom>().Any());
|
||||
|
||||
AddStep("select room", () => InputManager.Key(Key.Down));
|
||||
AddStep("join room", () => InputManager.Key(Key.Enter));
|
||||
|
||||
|
@ -1,157 +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 System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
[HeadlessTest]
|
||||
public class TestSceneMultiplayerRoomManager : MultiplayerTestScene
|
||||
{
|
||||
protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies();
|
||||
|
||||
public TestSceneMultiplayerRoomManager()
|
||||
: base(false)
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPollsInitially()
|
||||
{
|
||||
AddStep("create room manager with a few rooms", () =>
|
||||
{
|
||||
RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1"));
|
||||
RoomManager.PartRoom();
|
||||
RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2"));
|
||||
RoomManager.PartRoom();
|
||||
RoomManager.ClearRooms();
|
||||
});
|
||||
|
||||
AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2);
|
||||
AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRoomsClearedOnDisconnection()
|
||||
{
|
||||
AddStep("create room manager with a few rooms", () =>
|
||||
{
|
||||
RoomManager.CreateRoom(createRoom());
|
||||
RoomManager.PartRoom();
|
||||
RoomManager.CreateRoom(createRoom());
|
||||
RoomManager.PartRoom();
|
||||
});
|
||||
|
||||
AddStep("disconnect", () => Client.Disconnect());
|
||||
|
||||
AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0);
|
||||
AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRoomsPolledOnReconnect()
|
||||
{
|
||||
AddStep("create room manager with a few rooms", () =>
|
||||
{
|
||||
RoomManager.CreateRoom(createRoom());
|
||||
RoomManager.PartRoom();
|
||||
RoomManager.CreateRoom(createRoom());
|
||||
RoomManager.PartRoom();
|
||||
});
|
||||
|
||||
AddStep("disconnect", () => Client.Disconnect());
|
||||
AddStep("connect", () => Client.Connect());
|
||||
|
||||
AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2);
|
||||
AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRoomsNotPolledWhenJoined()
|
||||
{
|
||||
AddStep("create room manager with a room", () =>
|
||||
{
|
||||
RoomManager.CreateRoom(createRoom());
|
||||
RoomManager.ClearRooms();
|
||||
});
|
||||
|
||||
AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0);
|
||||
AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultiplayerRoomJoinedWhenCreated()
|
||||
{
|
||||
AddStep("create room manager with a room", () =>
|
||||
{
|
||||
RoomManager.CreateRoom(createRoom());
|
||||
});
|
||||
|
||||
AddUntilStep("multiplayer room joined", () => Client.Room != null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultiplayerRoomPartedWhenAPIRoomParted()
|
||||
{
|
||||
AddStep("create room manager with a room", () =>
|
||||
{
|
||||
RoomManager.CreateRoom(createRoom());
|
||||
RoomManager.PartRoom();
|
||||
});
|
||||
|
||||
AddAssert("multiplayer room parted", () => Client.Room == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultiplayerRoomJoinedWhenAPIRoomJoined()
|
||||
{
|
||||
AddStep("create room manager with a room", () =>
|
||||
{
|
||||
var r = createRoom();
|
||||
RoomManager.CreateRoom(r);
|
||||
RoomManager.PartRoom();
|
||||
RoomManager.JoinRoom(r);
|
||||
});
|
||||
|
||||
AddUntilStep("multiplayer room joined", () => Client.Room != null);
|
||||
}
|
||||
|
||||
private Room createRoom(Action<Room> initFunc = null)
|
||||
{
|
||||
var room = new Room
|
||||
{
|
||||
Name =
|
||||
{
|
||||
Value = "test room"
|
||||
},
|
||||
Playlist =
|
||||
{
|
||||
new PlaylistItem
|
||||
{
|
||||
Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
|
||||
Ruleset = { Value = Ruleset.Value }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
initFunc?.Invoke(room);
|
||||
return room;
|
||||
}
|
||||
|
||||
private class TestDependencies : MultiplayerTestSceneDependencies
|
||||
{
|
||||
public TestDependencies()
|
||||
{
|
||||
// Need to set these values as early as possible.
|
||||
RoomManager.TimeBetweenListingPolls.Value = 1;
|
||||
RoomManager.TimeBetweenSelectionPolls.Value = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -141,6 +141,12 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
|
||||
public IBindableList<Room> Rooms => null;
|
||||
|
||||
public void AddOrUpdateRoom(Room room) => throw new NotImplementedException();
|
||||
|
||||
public void RemoveRoom(Room room) => throw new NotImplementedException();
|
||||
|
||||
public void ClearRooms() => throw new NotImplementedException();
|
||||
|
||||
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
{
|
||||
if (CreateRequested == null)
|
||||
|
@ -1,8 +1,10 @@
|
||||
// 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 System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -174,6 +176,60 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
checkBindableAtValue("Circle Size", null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestModSettingChangeTracker()
|
||||
{
|
||||
ModSettingChangeTracker tracker = null;
|
||||
Queue<Mod> settingsChangedQueue = null;
|
||||
|
||||
setBeatmapWithDifficultyParameters(5);
|
||||
|
||||
AddStep("add mod settings change tracker", () =>
|
||||
{
|
||||
settingsChangedQueue = new Queue<Mod>();
|
||||
|
||||
tracker = new ModSettingChangeTracker(modDifficultyAdjust.Yield())
|
||||
{
|
||||
SettingChanged = settingsChangedQueue.Enqueue
|
||||
};
|
||||
});
|
||||
|
||||
AddAssert("no settings changed", () => settingsChangedQueue.Count == 0);
|
||||
|
||||
setSliderValue("Circle Size", 3);
|
||||
|
||||
settingsChangedFired();
|
||||
|
||||
setSliderValue("Circle Size", 5);
|
||||
checkBindableAtValue("Circle Size", 5);
|
||||
|
||||
settingsChangedFired();
|
||||
|
||||
AddStep("reset mod settings", () => modDifficultyAdjust.CircleSize.SetDefault());
|
||||
checkBindableAtValue("Circle Size", null);
|
||||
|
||||
settingsChangedFired();
|
||||
|
||||
setExtendedLimits(true);
|
||||
|
||||
settingsChangedFired();
|
||||
|
||||
AddStep("dispose tracker", () =>
|
||||
{
|
||||
tracker.Dispose();
|
||||
tracker = null;
|
||||
});
|
||||
|
||||
void settingsChangedFired()
|
||||
{
|
||||
AddAssert("setting changed event fired", () =>
|
||||
{
|
||||
settingsChangedQueue.Dequeue();
|
||||
return settingsChangedQueue.Count == 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void resetToDefault(string name)
|
||||
{
|
||||
AddStep($"Reset {name} to default", () =>
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Input
|
||||
{
|
||||
@ -24,14 +25,14 @@ namespace osu.Game.Input
|
||||
private IBindable<bool> localUserPlaying;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGame game, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager)
|
||||
private void load(ILocalUserPlayInfo localUserInfo, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager)
|
||||
{
|
||||
frameworkConfineMode = frameworkConfigManager.GetBindable<ConfineMouseMode>(FrameworkSetting.ConfineMouseMode);
|
||||
frameworkWindowMode = frameworkConfigManager.GetBindable<WindowMode>(FrameworkSetting.WindowMode);
|
||||
frameworkWindowMode.BindValueChanged(_ => updateConfineMode());
|
||||
|
||||
osuConfineMode = osuConfigManager.GetBindable<OsuConfineMouseMode>(OsuSetting.ConfineMouseMode);
|
||||
localUserPlaying = game.LocalUserPlaying.GetBoundCopy();
|
||||
localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy();
|
||||
|
||||
osuConfineMode.ValueChanged += _ => updateConfineMode();
|
||||
localUserPlaying.BindValueChanged(_ => updateConfineMode(), true);
|
||||
|
64
osu.Game/Localisation/AudioSettingsStrings.cs
Normal file
64
osu.Game/Localisation/AudioSettingsStrings.cs
Normal file
@ -0,0 +1,64 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class AudioSettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.AudioSettings";
|
||||
|
||||
/// <summary>
|
||||
/// "Audio"
|
||||
/// </summary>
|
||||
public static LocalisableString AudioSectionHeader => new TranslatableString(getKey(@"audio_section_header"), @"Audio");
|
||||
|
||||
/// <summary>
|
||||
/// "Devices"
|
||||
/// </summary>
|
||||
public static LocalisableString AudioDevicesHeader => new TranslatableString(getKey(@"audio_devices_header"), @"Devices");
|
||||
|
||||
/// <summary>
|
||||
/// "Volume"
|
||||
/// </summary>
|
||||
public static LocalisableString VolumeHeader => new TranslatableString(getKey(@"volume_header"), @"Volume");
|
||||
|
||||
/// <summary>
|
||||
/// "Master"
|
||||
/// </summary>
|
||||
public static LocalisableString MasterVolume => new TranslatableString(getKey(@"master_volume"), @"Master");
|
||||
|
||||
/// <summary>
|
||||
/// "Master (window inactive)"
|
||||
/// </summary>
|
||||
public static LocalisableString MasterVolumeInactive => new TranslatableString(getKey(@"master_volume_inactive"), @"Master (window inactive)");
|
||||
|
||||
/// <summary>
|
||||
/// "Effect"
|
||||
/// </summary>
|
||||
public static LocalisableString EffectVolume => new TranslatableString(getKey(@"effect_volume"), @"Effect");
|
||||
|
||||
/// <summary>
|
||||
/// "Music"
|
||||
/// </summary>
|
||||
public static LocalisableString MusicVolume => new TranslatableString(getKey(@"music_volume"), @"Music");
|
||||
|
||||
/// <summary>
|
||||
/// "Offset Adjustment"
|
||||
/// </summary>
|
||||
public static LocalisableString OffsetHeader => new TranslatableString(getKey(@"offset_header"), @"Offset Adjustment");
|
||||
|
||||
/// <summary>
|
||||
/// "Audio offset"
|
||||
/// </summary>
|
||||
public static LocalisableString AudioOffset => new TranslatableString(getKey(@"audio_offset"), @"Audio offset");
|
||||
|
||||
/// <summary>
|
||||
/// "Offset wizard"
|
||||
/// </summary>
|
||||
public static LocalisableString OffsetWizard => new TranslatableString(getKey(@"offset_wizard"), @"Offset wizard");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
@ -14,11 +14,21 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString Cancel => new TranslatableString(getKey(@"cancel"), @"Cancel");
|
||||
|
||||
/// <summary>
|
||||
/// "Clear"
|
||||
/// </summary>
|
||||
public static LocalisableString Clear => new TranslatableString(getKey(@"clear"), @"Clear");
|
||||
|
||||
/// <summary>
|
||||
/// "Enabled"
|
||||
/// </summary>
|
||||
public static LocalisableString Enabled => new TranslatableString(getKey(@"enabled"), @"Enabled");
|
||||
|
||||
/// <summary>
|
||||
/// "Default"
|
||||
/// </summary>
|
||||
public static LocalisableString Default => new TranslatableString(getKey(@"default"), @"Default");
|
||||
|
||||
/// <summary>
|
||||
/// "Width"
|
||||
/// </summary>
|
||||
@ -31,4 +41,4 @@ namespace osu.Game.Localisation
|
||||
|
||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
49
osu.Game/Localisation/DebugSettingsStrings.cs
Normal file
49
osu.Game/Localisation/DebugSettingsStrings.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 osu.Framework.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class DebugSettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.DebugSettings";
|
||||
|
||||
/// <summary>
|
||||
/// "Debug"
|
||||
/// </summary>
|
||||
public static LocalisableString DebugSectionHeader => new TranslatableString(getKey(@"debug_section_header"), @"Debug");
|
||||
|
||||
/// <summary>
|
||||
/// "General"
|
||||
/// </summary>
|
||||
public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General");
|
||||
|
||||
/// <summary>
|
||||
/// "Show log overlay"
|
||||
/// </summary>
|
||||
public static LocalisableString ShowLogOverlay => new TranslatableString(getKey(@"show_log_overlay"), @"Show log overlay");
|
||||
|
||||
/// <summary>
|
||||
/// "Bypass front-to-back render pass"
|
||||
/// </summary>
|
||||
public static LocalisableString BypassFrontToBackPass => new TranslatableString(getKey(@"bypass_front_to_back_pass"), @"Bypass front-to-back render pass");
|
||||
|
||||
/// <summary>
|
||||
/// "Import files"
|
||||
/// </summary>
|
||||
public static LocalisableString ImportFiles => new TranslatableString(getKey(@"import_files"), @"Import files");
|
||||
|
||||
/// <summary>
|
||||
/// "Memory"
|
||||
/// </summary>
|
||||
public static LocalisableString MemoryHeader => new TranslatableString(getKey(@"memory_header"), @"Memory");
|
||||
|
||||
/// <summary>
|
||||
/// "Clear all caches"
|
||||
/// </summary>
|
||||
public static LocalisableString ClearAllCaches => new TranslatableString(getKey(@"clear_all_caches"), @"Clear all caches");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
94
osu.Game/Localisation/GameplaySettingsStrings.cs
Normal file
94
osu.Game/Localisation/GameplaySettingsStrings.cs
Normal file
@ -0,0 +1,94 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class GameplaySettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.GameplaySettings";
|
||||
|
||||
/// <summary>
|
||||
/// "Gameplay"
|
||||
/// </summary>
|
||||
public static LocalisableString GameplaySectionHeader => new TranslatableString(getKey(@"gameplay_section_header"), @"Gameplay");
|
||||
|
||||
/// <summary>
|
||||
/// "General"
|
||||
/// </summary>
|
||||
public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General");
|
||||
|
||||
/// <summary>
|
||||
/// "Background dim"
|
||||
/// </summary>
|
||||
public static LocalisableString BackgroundDim => new TranslatableString(getKey(@"dim"), @"Background dim");
|
||||
|
||||
/// <summary>
|
||||
/// "Background blur"
|
||||
/// </summary>
|
||||
public static LocalisableString BackgroundBlur => new TranslatableString(getKey(@"blur"), @"Background blur");
|
||||
|
||||
/// <summary>
|
||||
/// "Lighten playfield during breaks"
|
||||
/// </summary>
|
||||
public static LocalisableString LightenDuringBreaks => new TranslatableString(getKey(@"lighten_during_breaks"), @"Lighten playfield during breaks");
|
||||
|
||||
/// <summary>
|
||||
/// "HUD overlay visibility mode"
|
||||
/// </summary>
|
||||
public static LocalisableString HUDVisibilityMode => new TranslatableString(getKey(@"hud_visibility_mode"), @"HUD overlay visibility mode");
|
||||
|
||||
/// <summary>
|
||||
/// "Show difficulty graph on progress bar"
|
||||
/// </summary>
|
||||
public static LocalisableString ShowDifficultyGraph => new TranslatableString(getKey(@"show_difficulty_graph"), @"Show difficulty graph on progress bar");
|
||||
|
||||
/// <summary>
|
||||
/// "Show health display even when you can't fail"
|
||||
/// </summary>
|
||||
public static LocalisableString ShowHealthDisplayWhenCantFail => new TranslatableString(getKey(@"show_health_display_when_cant_fail"), @"Show health display even when you can't fail");
|
||||
|
||||
/// <summary>
|
||||
/// "Fade playfield to red when health is low"
|
||||
/// </summary>
|
||||
public static LocalisableString FadePlayfieldWhenHealthLow => new TranslatableString(getKey(@"fade_playfield_when_health_low"), @"Fade playfield to red when health is low");
|
||||
|
||||
/// <summary>
|
||||
/// "Always show key overlay"
|
||||
/// </summary>
|
||||
public static LocalisableString AlwaysShowKeyOverlay => new TranslatableString(getKey(@"key_overlay"), @"Always show key overlay");
|
||||
|
||||
/// <summary>
|
||||
/// "Positional hitsounds"
|
||||
/// </summary>
|
||||
public static LocalisableString PositionalHitsounds => new TranslatableString(getKey(@"positional_hitsounds"), @"Positional hitsounds");
|
||||
|
||||
/// <summary>
|
||||
/// "Always play first combo break sound"
|
||||
/// </summary>
|
||||
public static LocalisableString AlwaysPlayFirstComboBreak => new TranslatableString(getKey(@"always_play_first_combo_break"), @"Always play first combo break sound");
|
||||
|
||||
/// <summary>
|
||||
/// "Score display mode"
|
||||
/// </summary>
|
||||
public static LocalisableString ScoreDisplayMode => new TranslatableString(getKey(@"score_display_mode"), @"Score display mode");
|
||||
|
||||
/// <summary>
|
||||
/// "Disable Windows key during gameplay"
|
||||
/// </summary>
|
||||
public static LocalisableString DisableWinKey => new TranslatableString(getKey(@"disable_win_key"), @"Disable Windows key during gameplay");
|
||||
|
||||
/// <summary>
|
||||
/// "Mods"
|
||||
/// </summary>
|
||||
public static LocalisableString ModsHeader => new TranslatableString(getKey(@"mods_header"), @"Mods");
|
||||
|
||||
/// <summary>
|
||||
/// "Increase visibility of first object when visual impairment mods are enabled"
|
||||
/// </summary>
|
||||
public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
59
osu.Game/Localisation/GeneralSettingsStrings.cs
Normal file
59
osu.Game/Localisation/GeneralSettingsStrings.cs
Normal file
@ -0,0 +1,59 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class GeneralSettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.GeneralSettings";
|
||||
|
||||
/// <summary>
|
||||
/// "General"
|
||||
/// </summary>
|
||||
public static LocalisableString GeneralSectionHeader => new TranslatableString(getKey(@"general_section_header"), @"General");
|
||||
|
||||
/// <summary>
|
||||
/// "Language"
|
||||
/// </summary>
|
||||
public static LocalisableString LanguageHeader => new TranslatableString(getKey(@"language_header"), @"Language");
|
||||
|
||||
/// <summary>
|
||||
/// "Language"
|
||||
/// </summary>
|
||||
public static LocalisableString LanguageDropdown => new TranslatableString(getKey(@"language_dropdown"), @"Language");
|
||||
|
||||
/// <summary>
|
||||
/// "Prefer metadata in original language"
|
||||
/// </summary>
|
||||
public static LocalisableString PreferOriginalMetadataLanguage => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language");
|
||||
|
||||
/// <summary>
|
||||
/// "Updates"
|
||||
/// </summary>
|
||||
public static LocalisableString UpdateHeader => new TranslatableString(getKey(@"update_header"), @"Updates");
|
||||
|
||||
/// <summary>
|
||||
/// "Release stream"
|
||||
/// </summary>
|
||||
public static LocalisableString ReleaseStream => new TranslatableString(getKey(@"release_stream"), @"Release stream");
|
||||
|
||||
/// <summary>
|
||||
/// "Check for updates"
|
||||
/// </summary>
|
||||
public static LocalisableString CheckUpdate => new TranslatableString(getKey(@"check_update"), @"Check for updates");
|
||||
|
||||
/// <summary>
|
||||
/// "Open osu! folder"
|
||||
/// </summary>
|
||||
public static LocalisableString OpenOsuFolder => new TranslatableString(getKey(@"open_osu_folder"), @"Open osu! folder");
|
||||
|
||||
/// <summary>
|
||||
/// "Change folder location..."
|
||||
/// </summary>
|
||||
public static LocalisableString ChangeFolderLocation => new TranslatableString(getKey(@"change_folder_location"), @"Change folder location...");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
119
osu.Game/Localisation/GraphicsSettingsStrings.cs
Normal file
119
osu.Game/Localisation/GraphicsSettingsStrings.cs
Normal file
@ -0,0 +1,119 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class GraphicsSettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.GraphicsSettings";
|
||||
|
||||
/// <summary>
|
||||
/// "Graphics"
|
||||
/// </summary>
|
||||
public static LocalisableString GraphicsSectionHeader => new TranslatableString(getKey(@"graphics_section_header"), @"Graphics");
|
||||
|
||||
/// <summary>
|
||||
/// "Renderer"
|
||||
/// </summary>
|
||||
public static LocalisableString RendererHeader => new TranslatableString(getKey(@"renderer_header"), @"Renderer");
|
||||
|
||||
/// <summary>
|
||||
/// "Frame limiter"
|
||||
/// </summary>
|
||||
public static LocalisableString FrameLimiter => new TranslatableString(getKey(@"frame_limiter"), @"Frame limiter");
|
||||
|
||||
/// <summary>
|
||||
/// "Threading mode"
|
||||
/// </summary>
|
||||
public static LocalisableString ThreadingMode => new TranslatableString(getKey(@"threading_mode"), @"Threading mode");
|
||||
|
||||
/// <summary>
|
||||
/// "Show FPS"
|
||||
/// </summary>
|
||||
public static LocalisableString ShowFPS => new TranslatableString(getKey(@"show_fps"), @"Show FPS");
|
||||
|
||||
/// <summary>
|
||||
/// "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. "2x refresh rate" is recommended."
|
||||
/// </summary>
|
||||
public static LocalisableString UnlimitedFramesNote => new TranslatableString(getKey(@"unlimited_frames_note"), @"Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. ""2x refresh rate"" is recommended.");
|
||||
|
||||
/// <summary>
|
||||
/// "Layout"
|
||||
/// </summary>
|
||||
public static LocalisableString LayoutHeader => new TranslatableString(getKey(@"layout_header"), @"Layout");
|
||||
|
||||
/// <summary>
|
||||
/// "Screen mode"
|
||||
/// </summary>
|
||||
public static LocalisableString ScreenMode => new TranslatableString(getKey(@"screen_mode"), @"Screen mode");
|
||||
|
||||
/// <summary>
|
||||
/// "Resolution"
|
||||
/// </summary>
|
||||
public static LocalisableString Resolution => new TranslatableString(getKey(@"resolution"), @"Resolution");
|
||||
|
||||
/// <summary>
|
||||
/// "UI scaling"
|
||||
/// </summary>
|
||||
public static LocalisableString UIScaling => new TranslatableString(getKey(@"ui_scaling"), @"UI scaling");
|
||||
|
||||
/// <summary>
|
||||
/// "Screen scaling"
|
||||
/// </summary>
|
||||
public static LocalisableString ScreenScaling => new TranslatableString(getKey(@"screen_scaling"), @"Screen scaling");
|
||||
|
||||
/// <summary>
|
||||
/// "Horizontal position"
|
||||
/// </summary>
|
||||
public static LocalisableString HorizontalPosition => new TranslatableString(getKey(@"horizontal_position"), @"Horizontal position");
|
||||
|
||||
/// <summary>
|
||||
/// "Vertical position"
|
||||
/// </summary>
|
||||
public static LocalisableString VerticalPosition => new TranslatableString(getKey(@"vertical_position"), @"Vertical position");
|
||||
|
||||
/// <summary>
|
||||
/// "Horizontal scale"
|
||||
/// </summary>
|
||||
public static LocalisableString HorizontalScale => new TranslatableString(getKey(@"horizontal_scale"), @"Horizontal scale");
|
||||
|
||||
/// <summary>
|
||||
/// "Vertical scale"
|
||||
/// </summary>
|
||||
public static LocalisableString VerticalScale => new TranslatableString(getKey(@"vertical_scale"), @"Vertical scale");
|
||||
|
||||
/// <summary>
|
||||
/// "Running without fullscreen mode will increase your input latency!"
|
||||
/// </summary>
|
||||
public static LocalisableString NotFullscreenNote => new TranslatableString(getKey(@"not_fullscreen_note"), @"Running without fullscreen mode will increase your input latency!");
|
||||
|
||||
/// <summary>
|
||||
/// "Detail Settings"
|
||||
/// </summary>
|
||||
public static LocalisableString DetailSettingsHeader => new TranslatableString(getKey(@"detail_settings_header"), @"Detail Settings");
|
||||
|
||||
/// <summary>
|
||||
/// "Storyboard / video"
|
||||
/// </summary>
|
||||
public static LocalisableString StoryboardVideo => new TranslatableString(getKey(@"storyboard_video"), @"Storyboard / video");
|
||||
|
||||
/// <summary>
|
||||
/// "Hit lighting"
|
||||
/// </summary>
|
||||
public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit lighting");
|
||||
|
||||
/// <summary>
|
||||
/// "Screenshot format"
|
||||
/// </summary>
|
||||
public static LocalisableString ScreenshotFormat => new TranslatableString(getKey(@"screenshot_format"), @"Screenshot format");
|
||||
|
||||
/// <summary>
|
||||
/// "Show menu cursor in screenshots"
|
||||
/// </summary>
|
||||
public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@"show_cursor_in_screenshots"), @"Show menu cursor in screenshots");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
59
osu.Game/Localisation/InputSettingsStrings.cs
Normal file
59
osu.Game/Localisation/InputSettingsStrings.cs
Normal file
@ -0,0 +1,59 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class InputSettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.InputSettings";
|
||||
|
||||
/// <summary>
|
||||
/// "Input"
|
||||
/// </summary>
|
||||
public static LocalisableString InputSectionHeader => new TranslatableString(getKey(@"input_section_header"), @"Input");
|
||||
|
||||
/// <summary>
|
||||
/// "Global"
|
||||
/// </summary>
|
||||
public static LocalisableString GlobalKeyBindingHeader => new TranslatableString(getKey(@"global_key_binding_header"), @"Global");
|
||||
|
||||
/// <summary>
|
||||
/// "Song Select"
|
||||
/// </summary>
|
||||
public static LocalisableString SongSelectSection => new TranslatableString(getKey(@"song_select_section"), @"Song Select");
|
||||
|
||||
/// <summary>
|
||||
/// "In Game"
|
||||
/// </summary>
|
||||
public static LocalisableString InGameSection => new TranslatableString(getKey(@"in_game_section"), @"In Game");
|
||||
|
||||
/// <summary>
|
||||
/// "Audio"
|
||||
/// </summary>
|
||||
public static LocalisableString AudioSection => new TranslatableString(getKey(@"audio_section"), @"Audio");
|
||||
|
||||
/// <summary>
|
||||
/// "Editor"
|
||||
/// </summary>
|
||||
public static LocalisableString EditorSection => new TranslatableString(getKey(@"editor_section"), @"Editor");
|
||||
|
||||
/// <summary>
|
||||
/// "Reset all bindings in section"
|
||||
/// </summary>
|
||||
public static LocalisableString ResetSectionButton => new TranslatableString(getKey(@"reset_section_button"), @"Reset all bindings in section");
|
||||
|
||||
/// <summary>
|
||||
/// "key configuration"
|
||||
/// </summary>
|
||||
public static LocalisableString KeyBindingPanelHeader => new TranslatableString(getKey(@"key_binding_panel_header"), @"key configuration");
|
||||
|
||||
/// <summary>
|
||||
/// "Customise your keys!"
|
||||
/// </summary>
|
||||
public static LocalisableString KeyBindingPanelDescription => new TranslatableString(getKey(@"key_binding_panel_description"), @"Customise your keys!");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
74
osu.Game/Localisation/MaintenanceSettingsStrings.cs
Normal file
74
osu.Game/Localisation/MaintenanceSettingsStrings.cs
Normal file
@ -0,0 +1,74 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class MaintenanceSettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.MaintenanceSettings";
|
||||
|
||||
/// <summary>
|
||||
/// "Maintenance"
|
||||
/// </summary>
|
||||
public static LocalisableString MaintenanceSectionHeader => new TranslatableString(getKey(@"maintenance_section_header"), @"Maintenance");
|
||||
|
||||
/// <summary>
|
||||
/// "Select directory"
|
||||
/// </summary>
|
||||
public static LocalisableString SelectDirectory => new TranslatableString(getKey(@"select_directory"), @"Select directory");
|
||||
|
||||
/// <summary>
|
||||
/// "Import beatmaps from stable"
|
||||
/// </summary>
|
||||
public static LocalisableString ImportBeatmapsFromStable => new TranslatableString(getKey(@"import_beatmaps_from_stable"), @"Import beatmaps from stable");
|
||||
|
||||
/// <summary>
|
||||
/// "Delete ALL beatmaps"
|
||||
/// </summary>
|
||||
public static LocalisableString DeleteAllBeatmaps => new TranslatableString(getKey(@"delete_all_beatmaps"), @"Delete ALL beatmaps");
|
||||
|
||||
/// <summary>
|
||||
/// "Import scores from stable"
|
||||
/// </summary>
|
||||
public static LocalisableString ImportScoresFromStable => new TranslatableString(getKey(@"import_scores_from_stable"), @"Import scores from stable");
|
||||
|
||||
/// <summary>
|
||||
/// "Delete ALL scores"
|
||||
/// </summary>
|
||||
public static LocalisableString DeleteAllScores => new TranslatableString(getKey(@"delete_all_scores"), @"Delete ALL scores");
|
||||
|
||||
/// <summary>
|
||||
/// "Import skins from stable"
|
||||
/// </summary>
|
||||
public static LocalisableString ImportSkinsFromStable => new TranslatableString(getKey(@"import_skins_from_stable"), @"Import skins from stable");
|
||||
|
||||
/// <summary>
|
||||
/// "Delete ALL skins"
|
||||
/// </summary>
|
||||
public static LocalisableString DeleteAllSkins => new TranslatableString(getKey(@"delete_all_skins"), @"Delete ALL skins");
|
||||
|
||||
/// <summary>
|
||||
/// "Import collections from stable"
|
||||
/// </summary>
|
||||
public static LocalisableString ImportCollectionsFromStable => new TranslatableString(getKey(@"import_collections_from_stable"), @"Import collections from stable");
|
||||
|
||||
/// <summary>
|
||||
/// "Delete ALL collections"
|
||||
/// </summary>
|
||||
public static LocalisableString DeleteAllCollections => new TranslatableString(getKey(@"delete_all_collections"), @"Delete ALL collections");
|
||||
|
||||
/// <summary>
|
||||
/// "Restore all hidden difficulties"
|
||||
/// </summary>
|
||||
public static LocalisableString RestoreAllHiddenDifficulties => new TranslatableString(getKey(@"restore_all_hidden_difficulties"), @"Restore all hidden difficulties");
|
||||
|
||||
/// <summary>
|
||||
/// "Restore all recently deleted beatmaps"
|
||||
/// </summary>
|
||||
public static LocalisableString RestoreAllRecentlyDeletedBeatmaps => new TranslatableString(getKey(@"restore_all_recently_deleted_beatmaps"), @"Restore all recently deleted beatmaps");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
69
osu.Game/Localisation/OnlineSettingsStrings.cs
Normal file
69
osu.Game/Localisation/OnlineSettingsStrings.cs
Normal file
@ -0,0 +1,69 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class OnlineSettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.OnlineSettings";
|
||||
|
||||
/// <summary>
|
||||
/// "Online"
|
||||
/// </summary>
|
||||
public static LocalisableString OnlineSectionHeader => new TranslatableString(getKey(@"online_section_header"), @"Online");
|
||||
|
||||
/// <summary>
|
||||
/// "Alerts and Privacy"
|
||||
/// </summary>
|
||||
public static LocalisableString AlertsAndPrivacyHeader => new TranslatableString(getKey(@"alerts_and_privacy_header"), @"Alerts and Privacy");
|
||||
|
||||
/// <summary>
|
||||
/// "Show a notification when someone mentions your name"
|
||||
/// </summary>
|
||||
public static LocalisableString NotifyOnMentioned => new TranslatableString(getKey(@"notify_on_mentioned"), @"Show a notification when someone mentions your name");
|
||||
|
||||
/// <summary>
|
||||
/// "Show a notification when you receive a private message"
|
||||
/// </summary>
|
||||
public static LocalisableString NotifyOnPrivateMessage => new TranslatableString(getKey(@"notify_on_private_message"), @"Show a notification when you receive a private message");
|
||||
|
||||
/// <summary>
|
||||
/// "Integrations"
|
||||
/// </summary>
|
||||
public static LocalisableString IntegrationsHeader => new TranslatableString(getKey(@"integrations_header"), @"Integrations");
|
||||
|
||||
/// <summary>
|
||||
/// "Discord Rich Presence"
|
||||
/// </summary>
|
||||
public static LocalisableString DiscordRichPresence => new TranslatableString(getKey(@"discord_rich_presence"), @"Discord Rich Presence");
|
||||
|
||||
/// <summary>
|
||||
/// "Web"
|
||||
/// </summary>
|
||||
public static LocalisableString WebHeader => new TranslatableString(getKey(@"web_header"), @"Web");
|
||||
|
||||
/// <summary>
|
||||
/// "Warn about opening external links"
|
||||
/// </summary>
|
||||
public static LocalisableString ExternalLinkWarning => new TranslatableString(getKey(@"external_link_warning"), @"Warn about opening external links");
|
||||
|
||||
/// <summary>
|
||||
/// "Prefer downloads without video"
|
||||
/// </summary>
|
||||
public static LocalisableString PreferNoVideo => new TranslatableString(getKey(@"prefer_no_video"), @"Prefer downloads without video");
|
||||
|
||||
/// <summary>
|
||||
/// "Automatically download beatmaps when spectating"
|
||||
/// </summary>
|
||||
public static LocalisableString AutomaticallyDownloadWhenSpectating => new TranslatableString(getKey(@"automatically_download_when_spectating"), @"Automatically download beatmaps when spectating");
|
||||
|
||||
/// <summary>
|
||||
/// "Show explicit content in search results"
|
||||
/// </summary>
|
||||
public static LocalisableString ShowExplicitContent => new TranslatableString(getKey(@"show_explicit_content"), @"Show explicit content in search results");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
54
osu.Game/Localisation/SkinSettingsStrings.cs
Normal file
54
osu.Game/Localisation/SkinSettingsStrings.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class SkinSettingsStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.SkinSettings";
|
||||
|
||||
/// <summary>
|
||||
/// "Skin"
|
||||
/// </summary>
|
||||
public static LocalisableString SkinSectionHeader => new TranslatableString(getKey(@"skin_section_header"), @"Skin");
|
||||
|
||||
/// <summary>
|
||||
/// "Skin layout editor"
|
||||
/// </summary>
|
||||
public static LocalisableString SkinLayoutEditor => new TranslatableString(getKey(@"skin_layout_editor"), @"Skin layout editor");
|
||||
|
||||
/// <summary>
|
||||
/// "Gameplay cursor size"
|
||||
/// </summary>
|
||||
public static LocalisableString GameplayCursorSize => new TranslatableString(getKey(@"gameplay_cursor_size"), @"Gameplay cursor size");
|
||||
|
||||
/// <summary>
|
||||
/// "Adjust gameplay cursor size based on current beatmap"
|
||||
/// </summary>
|
||||
public static LocalisableString AutoCursorSize => new TranslatableString(getKey(@"auto_cursor_size"), @"Adjust gameplay cursor size based on current beatmap");
|
||||
|
||||
/// <summary>
|
||||
/// "Beatmap skins"
|
||||
/// </summary>
|
||||
public static LocalisableString BeatmapSkins => new TranslatableString(getKey(@"beatmap_skins"), @"Beatmap skins");
|
||||
|
||||
/// <summary>
|
||||
/// "Beatmap colours"
|
||||
/// </summary>
|
||||
public static LocalisableString BeatmapColours => new TranslatableString(getKey(@"beatmap_colours"), @"Beatmap colours");
|
||||
|
||||
/// <summary>
|
||||
/// "Beatmap hitsounds"
|
||||
/// </summary>
|
||||
public static LocalisableString BeatmapHitsounds => new TranslatableString(getKey(@"beatmap_hitsounds"), @"Beatmap hitsounds");
|
||||
|
||||
/// <summary>
|
||||
/// "Export selected skin"
|
||||
/// </summary>
|
||||
public static LocalisableString ExportSkinButton => new TranslatableString(getKey(@"export_skin_button"), @"Export selected skin");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
114
osu.Game/Localisation/UserInterfaceStrings.cs
Normal file
114
osu.Game/Localisation/UserInterfaceStrings.cs
Normal file
@ -0,0 +1,114 @@
|
||||
// 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.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class UserInterfaceStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.UserInterface";
|
||||
|
||||
/// <summary>
|
||||
/// "User Interface"
|
||||
/// </summary>
|
||||
public static LocalisableString UserInterfaceSectionHeader => new TranslatableString(getKey(@"user_interface_section_header"), @"User Interface");
|
||||
|
||||
/// <summary>
|
||||
/// "General"
|
||||
/// </summary>
|
||||
public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General");
|
||||
|
||||
/// <summary>
|
||||
/// "Rotate cursor when dragging"
|
||||
/// </summary>
|
||||
public static LocalisableString CursorRotation => new TranslatableString(getKey(@"cursor_rotation"), @"Rotate cursor when dragging");
|
||||
|
||||
/// <summary>
|
||||
/// "Menu cursor size"
|
||||
/// </summary>
|
||||
public static LocalisableString MenuCursorSize => new TranslatableString(getKey(@"menu_cursor_size"), @"Menu cursor size");
|
||||
|
||||
/// <summary>
|
||||
/// "Parallax"
|
||||
/// </summary>
|
||||
public static LocalisableString Parallax => new TranslatableString(getKey(@"parallax"), @"Parallax");
|
||||
|
||||
/// <summary>
|
||||
/// "Hold-to-confirm activation time"
|
||||
/// </summary>
|
||||
public static LocalisableString HoldToConfirmActivationTime => new TranslatableString(getKey(@"hold_to_confirm_activation_time"), @"Hold-to-confirm activation time");
|
||||
|
||||
/// <summary>
|
||||
/// "Main Menu"
|
||||
/// </summary>
|
||||
public static LocalisableString MainMenuHeader => new TranslatableString(getKey(@"main_menu_header"), @"Main Menu");
|
||||
|
||||
/// <summary>
|
||||
/// "Interface voices"
|
||||
/// </summary>
|
||||
public static LocalisableString InterfaceVoices => new TranslatableString(getKey(@"interface_voices"), @"Interface voices");
|
||||
|
||||
/// <summary>
|
||||
/// "osu! music theme"
|
||||
/// </summary>
|
||||
public static LocalisableString OsuMusicTheme => new TranslatableString(getKey(@"osu_music_theme"), @"osu! music theme");
|
||||
|
||||
/// <summary>
|
||||
/// "Intro sequence"
|
||||
/// </summary>
|
||||
public static LocalisableString IntroSequence => new TranslatableString(getKey(@"intro_sequence"), @"Intro sequence");
|
||||
|
||||
/// <summary>
|
||||
/// "Background source"
|
||||
/// </summary>
|
||||
public static LocalisableString BackgroundSource => new TranslatableString(getKey(@"background_source"), @"Background source");
|
||||
|
||||
/// <summary>
|
||||
/// "Seasonal backgrounds"
|
||||
/// </summary>
|
||||
public static LocalisableString SeasonalBackgrounds => new TranslatableString(getKey(@"seasonal_backgrounds"), @"Seasonal backgrounds");
|
||||
|
||||
/// <summary>
|
||||
/// "Changes to this setting will only apply with an active osu!supporter tag."
|
||||
/// </summary>
|
||||
public static LocalisableString NotSupporterNote => new TranslatableString(getKey(@"not_supporter_note"), @"Changes to this setting will only apply with an active osu!supporter tag.");
|
||||
|
||||
/// <summary>
|
||||
/// "Song Select"
|
||||
/// </summary>
|
||||
public static LocalisableString SongSelectHeader => new TranslatableString(getKey(@"song_select_header"), @"Song Select");
|
||||
|
||||
/// <summary>
|
||||
/// "Right mouse drag to absolute scroll"
|
||||
/// </summary>
|
||||
public static LocalisableString RightMouseScroll => new TranslatableString(getKey(@"right_mouse_scroll"), @"Right mouse drag to absolute scroll");
|
||||
|
||||
/// <summary>
|
||||
/// "Show converted beatmaps"
|
||||
/// </summary>
|
||||
public static LocalisableString ShowConvertedBeatmaps => new TranslatableString(getKey(@"show_converted_beatmaps"), @"Show converted beatmaps");
|
||||
|
||||
/// <summary>
|
||||
/// "Display beatmaps from"
|
||||
/// </summary>
|
||||
public static LocalisableString StarsMinimum => new TranslatableString(getKey(@"stars_minimum"), @"Display beatmaps from");
|
||||
|
||||
/// <summary>
|
||||
/// "up to"
|
||||
/// </summary>
|
||||
public static LocalisableString StarsMaximum => new TranslatableString(getKey(@"stars_maximum"), @"up to");
|
||||
|
||||
/// <summary>
|
||||
/// "Random selection algorithm"
|
||||
/// </summary>
|
||||
public static LocalisableString RandomSelectionAlgorithm => new TranslatableString(getKey(@"random_selection_algorithm"), @"Random selection algorithm");
|
||||
|
||||
/// <summary>
|
||||
/// "no limit"
|
||||
/// </summary>
|
||||
public static LocalisableString NoLimit => new TranslatableString(getKey(@"no_limit"), @"no limit");
|
||||
|
||||
private static string getKey(string key) => $"{prefix}:{key}";
|
||||
}
|
||||
}
|
@ -47,39 +47,13 @@ namespace osu.Game.Online
|
||||
pollIfNecessary();
|
||||
}
|
||||
|
||||
private bool pollIfNecessary()
|
||||
/// <summary>
|
||||
/// Immediately performs a <see cref="Poll"/>.
|
||||
/// </summary>
|
||||
public void PollImmediately()
|
||||
{
|
||||
// we must be loaded so we have access to clock.
|
||||
if (!IsLoaded) return false;
|
||||
|
||||
// there's already a poll process running.
|
||||
if (pollingActive) return false;
|
||||
|
||||
// don't try polling if the time between polls hasn't been set.
|
||||
if (TimeBetweenPolls.Value == 0) return false;
|
||||
|
||||
if (!lastTimePolled.HasValue)
|
||||
{
|
||||
doPoll();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Time.Current - lastTimePolled.Value > TimeBetweenPolls.Value)
|
||||
{
|
||||
doPoll();
|
||||
return true;
|
||||
}
|
||||
|
||||
// not enough time has passed since the last poll. we do want to schedule a poll to happen, though.
|
||||
lastTimePolled = Time.Current - TimeBetweenPolls.Value;
|
||||
scheduleNextPoll();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void doPoll()
|
||||
{
|
||||
scheduledPoll = null;
|
||||
pollingActive = true;
|
||||
Poll().ContinueWith(_ => pollComplete());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -90,13 +64,11 @@ namespace osu.Game.Online
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Immediately performs a <see cref="Poll"/>.
|
||||
/// </summary>
|
||||
public void PollImmediately()
|
||||
private void doPoll()
|
||||
{
|
||||
lastTimePolled = Time.Current - TimeBetweenPolls.Value;
|
||||
scheduleNextPoll();
|
||||
scheduledPoll = null;
|
||||
pollingActive = true;
|
||||
Poll().ContinueWith(_ => pollComplete());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -111,6 +83,33 @@ namespace osu.Game.Online
|
||||
pollIfNecessary();
|
||||
}
|
||||
|
||||
private void pollIfNecessary()
|
||||
{
|
||||
// we must be loaded so we have access to clock.
|
||||
if (!IsLoaded) return;
|
||||
|
||||
// there's already a poll process running.
|
||||
if (pollingActive) return;
|
||||
|
||||
// don't try polling if the time between polls hasn't been set.
|
||||
if (TimeBetweenPolls.Value == 0) return;
|
||||
|
||||
if (!lastTimePolled.HasValue)
|
||||
{
|
||||
doPoll();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Time.Current - lastTimePolled.Value > TimeBetweenPolls.Value)
|
||||
{
|
||||
doPoll();
|
||||
return;
|
||||
}
|
||||
|
||||
// not enough time has passed since the last poll. we do want to schedule a poll to happen, though.
|
||||
scheduleNextPoll();
|
||||
}
|
||||
|
||||
private void scheduleNextPoll()
|
||||
{
|
||||
scheduledPoll?.Cancel();
|
||||
|
@ -134,7 +134,7 @@ namespace osu.Game.Online.Rooms
|
||||
/// The position of this <see cref="Room"/> in the list. This is not read from or written to the API.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<int> Position = new Bindable<int>(-1);
|
||||
public readonly Bindable<long> Position = new Bindable<long>(-1); // Todo: This does not need to exist.
|
||||
|
||||
public Room()
|
||||
{
|
||||
|
@ -62,7 +62,7 @@ namespace osu.Game
|
||||
/// The full osu! experience. Builds on top of <see cref="OsuGameBase"/> to add menus and binding logic
|
||||
/// for initial components that are generally retrieved via DI.
|
||||
/// </summary>
|
||||
public class OsuGame : OsuGameBase, IKeyBindingHandler<GlobalAction>
|
||||
public class OsuGame : OsuGameBase, IKeyBindingHandler<GlobalAction>, ILocalUserPlayInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications).
|
||||
@ -1085,5 +1085,7 @@ namespace osu.Game
|
||||
if (newScreen == null)
|
||||
Exit();
|
||||
}
|
||||
|
||||
IBindable<bool> ILocalUserPlayInfo.IsPlaying => LocalUserPlaying;
|
||||
}
|
||||
}
|
||||
|
@ -139,19 +139,24 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
||||
|
||||
LoadComponentAsync(Preview = previewTrackManager.Get(beatmapSet), preview =>
|
||||
{
|
||||
// beatmapset may have changed.
|
||||
if (Preview != preview)
|
||||
return;
|
||||
// Make sure that we schedule to after the next audio frame to fix crashes in single-threaded execution.
|
||||
// See: https://github.com/ppy/osu-framework/issues/4692
|
||||
Schedule(() =>
|
||||
{
|
||||
// beatmapset may have changed.
|
||||
if (Preview != preview)
|
||||
return;
|
||||
|
||||
AddInternal(preview);
|
||||
loading = false;
|
||||
// make sure that the update of value of Playing (and the ensuing value change callbacks)
|
||||
// are marshaled back to the update thread.
|
||||
preview.Stopped += () => Schedule(() => playing.Value = false);
|
||||
AddInternal(preview);
|
||||
loading = false;
|
||||
// make sure that the update of value of Playing (and the ensuing value change callbacks)
|
||||
// are marshaled back to the update thread.
|
||||
preview.Stopped += () => Schedule(() => playing.Value = false);
|
||||
|
||||
// user may have changed their mind.
|
||||
if (playing.Value)
|
||||
attemptStart();
|
||||
// user may have changed their mind.
|
||||
if (playing.Value)
|
||||
attemptStart();
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -24,6 +24,7 @@ namespace osu.Game.Overlays.Changelog
|
||||
public class ChangelogSupporterPromo : CompositeDrawable
|
||||
{
|
||||
private const float image_container_width = 164;
|
||||
private const float heart_size = 75;
|
||||
|
||||
private readonly FillFlowContainer textContainer;
|
||||
private readonly Container imageContainer;
|
||||
@ -134,18 +135,30 @@ namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Margin = new MarginPadding { Bottom = 28 },
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fill,
|
||||
Texture = textures.Get(@"Online/supporter-pippi"),
|
||||
},
|
||||
new Sprite
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Width = 75,
|
||||
Height = 75,
|
||||
Size = new Vector2(heart_size),
|
||||
Margin = new MarginPadding { Top = 70 },
|
||||
Texture = textures.Get(@"Online/supporter-heart"),
|
||||
Masking = true,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = colour.Pink,
|
||||
Radius = 10,
|
||||
Roundness = heart_size / 2,
|
||||
},
|
||||
Child = new Sprite
|
||||
{
|
||||
Size = new Vector2(heart_size),
|
||||
Texture = textures.Get(@"Online/supporter-heart"),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -8,12 +8,13 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
{
|
||||
public class AudioDevicesSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Devices";
|
||||
protected override LocalisableString Header => AudioSettingsStrings.AudioDevicesHeader;
|
||||
|
||||
[Resolved]
|
||||
private AudioManager audio { get; set; }
|
||||
@ -78,7 +79,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
private class AudioDeviceDropdownControl : DropdownControl
|
||||
{
|
||||
protected override LocalisableString GenerateItemText(string item)
|
||||
=> string.IsNullOrEmpty(item) ? "Default" : base.GenerateItemText(item);
|
||||
=> string.IsNullOrEmpty(item) ? CommonStrings.Default : base.GenerateItemText(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
{
|
||||
public class OffsetSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Offset Adjustment";
|
||||
protected override LocalisableString Header => AudioSettingsStrings.OffsetHeader;
|
||||
|
||||
public override IEnumerable<string> FilterTerms => base.FilterTerms.Concat(new[] { "universal", "uo", "timing" });
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -20,13 +25,13 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
{
|
||||
new SettingsSlider<double, OffsetSlider>
|
||||
{
|
||||
LabelText = "Audio offset",
|
||||
LabelText = AudioSettingsStrings.AudioOffset,
|
||||
Current = config.GetBindable<double>(OsuSetting.AudioOffset),
|
||||
KeyboardStep = 1f
|
||||
},
|
||||
new SettingsButton
|
||||
{
|
||||
Text = "Offset wizard"
|
||||
Text = AudioSettingsStrings.OffsetWizard
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -6,12 +6,13 @@ using osu.Framework.Audio;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
{
|
||||
public class VolumeSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Volume";
|
||||
protected override LocalisableString Header => AudioSettingsStrings.VolumeHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, OsuConfigManager config)
|
||||
@ -20,28 +21,28 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
{
|
||||
new SettingsSlider<double>
|
||||
{
|
||||
LabelText = "Master",
|
||||
LabelText = AudioSettingsStrings.MasterVolume,
|
||||
Current = audio.Volume,
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsSlider<double>
|
||||
{
|
||||
LabelText = "Master (window inactive)",
|
||||
LabelText = AudioSettingsStrings.MasterVolumeInactive,
|
||||
Current = config.GetBindable<double>(OsuSetting.VolumeInactive),
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsSlider<double>
|
||||
{
|
||||
LabelText = "Effect",
|
||||
LabelText = AudioSettingsStrings.EffectVolume,
|
||||
Current = audio.VolumeSample,
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsSlider<double>
|
||||
{
|
||||
LabelText = "Music",
|
||||
LabelText = AudioSettingsStrings.MusicVolume,
|
||||
Current = audio.VolumeTrack,
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
|
@ -3,15 +3,17 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings.Sections.Audio;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class AudioSection : SettingsSection
|
||||
{
|
||||
public override string Header => "Audio";
|
||||
public override LocalisableString Header => AudioSettingsStrings.AudioSectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
|
@ -6,13 +6,14 @@ using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Screens.Import;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Debug
|
||||
{
|
||||
public class GeneralSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "General";
|
||||
protected override LocalisableString Header => DebugSettingsStrings.GeneralHeader;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig, OsuGame game)
|
||||
@ -21,18 +22,18 @@ namespace osu.Game.Overlays.Settings.Sections.Debug
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show log overlay",
|
||||
LabelText = DebugSettingsStrings.ShowLogOverlay,
|
||||
Current = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowLogOverlay)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Bypass front-to-back render pass",
|
||||
LabelText = DebugSettingsStrings.BypassFrontToBackPass,
|
||||
Current = config.GetBindable<bool>(DebugSetting.BypassFrontToBackPass)
|
||||
}
|
||||
};
|
||||
Add(new SettingsButton
|
||||
{
|
||||
Text = "Import files",
|
||||
Text = DebugSettingsStrings.ImportFiles,
|
||||
Action = () => game?.PerformFromScreen(menu => menu.Push(new FileImportScreen()))
|
||||
});
|
||||
}
|
||||
|
@ -6,12 +6,13 @@ using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Debug
|
||||
{
|
||||
public class MemorySettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Memory";
|
||||
protected override LocalisableString Header => DebugSettingsStrings.MemoryHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(FrameworkDebugConfigManager config, GameHost host)
|
||||
@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug
|
||||
{
|
||||
new SettingsButton
|
||||
{
|
||||
Text = "Clear all caches",
|
||||
Text = DebugSettingsStrings.ClearAllCaches,
|
||||
Action = host.Collect
|
||||
},
|
||||
};
|
||||
|
@ -3,13 +3,15 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings.Sections.Debug;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class DebugSection : SettingsSection
|
||||
{
|
||||
public override string Header => "Debug";
|
||||
public override LocalisableString Header => DebugSettingsStrings.DebugSectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
|
@ -6,13 +6,14 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
{
|
||||
public class GeneralSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "General";
|
||||
protected override LocalisableString Header => GameplaySettingsStrings.GeneralHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -21,62 +22,62 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
{
|
||||
new SettingsSlider<double>
|
||||
{
|
||||
LabelText = "Background dim",
|
||||
LabelText = GameplaySettingsStrings.BackgroundDim,
|
||||
Current = config.GetBindable<double>(OsuSetting.DimLevel),
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsSlider<double>
|
||||
{
|
||||
LabelText = "Background blur",
|
||||
LabelText = GameplaySettingsStrings.BackgroundBlur,
|
||||
Current = config.GetBindable<double>(OsuSetting.BlurLevel),
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Lighten playfield during breaks",
|
||||
LabelText = GameplaySettingsStrings.LightenDuringBreaks,
|
||||
Current = config.GetBindable<bool>(OsuSetting.LightenDuringBreaks)
|
||||
},
|
||||
new SettingsEnumDropdown<HUDVisibilityMode>
|
||||
{
|
||||
LabelText = "HUD overlay visibility mode",
|
||||
LabelText = GameplaySettingsStrings.HUDVisibilityMode,
|
||||
Current = config.GetBindable<HUDVisibilityMode>(OsuSetting.HUDVisibilityMode)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show difficulty graph on progress bar",
|
||||
LabelText = GameplaySettingsStrings.ShowDifficultyGraph,
|
||||
Current = config.GetBindable<bool>(OsuSetting.ShowProgressGraph)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show health display even when you can't fail",
|
||||
LabelText = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail,
|
||||
Current = config.GetBindable<bool>(OsuSetting.ShowHealthDisplayWhenCantFail),
|
||||
Keywords = new[] { "hp", "bar" }
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Fade playfield to red when health is low",
|
||||
LabelText = GameplaySettingsStrings.FadePlayfieldWhenHealthLow,
|
||||
Current = config.GetBindable<bool>(OsuSetting.FadePlayfieldWhenHealthLow),
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Always show key overlay",
|
||||
LabelText = GameplaySettingsStrings.AlwaysShowKeyOverlay,
|
||||
Current = config.GetBindable<bool>(OsuSetting.KeyOverlay)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Positional hitsounds",
|
||||
LabelText = GameplaySettingsStrings.PositionalHitsounds,
|
||||
Current = config.GetBindable<bool>(OsuSetting.PositionalHitSounds)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Always play first combo break sound",
|
||||
LabelText = GameplaySettingsStrings.AlwaysPlayFirstComboBreak,
|
||||
Current = config.GetBindable<bool>(OsuSetting.AlwaysPlayFirstComboBreak)
|
||||
},
|
||||
new SettingsEnumDropdown<ScoringMode>
|
||||
{
|
||||
LabelText = "Score display mode",
|
||||
LabelText = GameplaySettingsStrings.ScoreDisplayMode,
|
||||
Current = config.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode),
|
||||
Keywords = new[] { "scoring" }
|
||||
},
|
||||
@ -86,7 +87,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
{
|
||||
Add(new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Disable Windows key during gameplay",
|
||||
LabelText = GameplaySettingsStrings.DisableWinKey,
|
||||
Current = config.GetBindable<bool>(OsuSetting.GameplayDisableWinKey)
|
||||
});
|
||||
}
|
||||
|
@ -6,12 +6,13 @@ using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
{
|
||||
public class ModsSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Mods";
|
||||
protected override LocalisableString Header => GameplaySettingsStrings.ModsHeader;
|
||||
|
||||
public override IEnumerable<string> FilterTerms => base.FilterTerms.Concat(new[] { "mod" });
|
||||
|
||||
@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Increase visibility of first object when visual impairment mods are enabled",
|
||||
LabelText = GameplaySettingsStrings.IncreaseFirstObjectVisibility,
|
||||
Current = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility),
|
||||
},
|
||||
};
|
||||
|
@ -9,12 +9,14 @@ using osu.Game.Rulesets;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class GameplaySection : SettingsSection
|
||||
{
|
||||
public override string Header => "Gameplay";
|
||||
public override LocalisableString Header => GameplaySettingsStrings.GameplaySectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
private SettingsDropdown<Language> languageSelection;
|
||||
private Bindable<string> frameworkLocale;
|
||||
|
||||
protected override LocalisableString Header => "Language";
|
||||
protected override LocalisableString Header => GeneralSettingsStrings.LanguageHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(FrameworkConfigManager frameworkConfig)
|
||||
@ -27,11 +27,11 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
{
|
||||
languageSelection = new SettingsEnumDropdown<Language>
|
||||
{
|
||||
LabelText = "Language",
|
||||
LabelText = GeneralSettingsStrings.LanguageDropdown,
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Prefer metadata in original language",
|
||||
LabelText = GeneralSettingsStrings.PreferOriginalMetadataLanguage,
|
||||
Current = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowUnicode)
|
||||
},
|
||||
};
|
||||
|
@ -9,6 +9,7 @@ using osu.Framework.Localisation;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Overlays.Settings.Sections.Maintenance;
|
||||
using osu.Game.Updater;
|
||||
@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
[Resolved(CanBeNull = true)]
|
||||
private UpdateManager updateManager { get; set; }
|
||||
|
||||
protected override LocalisableString Header => "Updates";
|
||||
protected override LocalisableString Header => GeneralSettingsStrings.UpdateHeader;
|
||||
|
||||
private SettingsButton checkForUpdatesButton;
|
||||
|
||||
@ -32,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
{
|
||||
Add(new SettingsEnumDropdown<ReleaseStream>
|
||||
{
|
||||
LabelText = "Release stream",
|
||||
LabelText = GeneralSettingsStrings.ReleaseStream,
|
||||
Current = config.GetBindable<ReleaseStream>(OsuSetting.ReleaseStream),
|
||||
});
|
||||
|
||||
@ -40,7 +41,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
{
|
||||
Add(checkForUpdatesButton = new SettingsButton
|
||||
{
|
||||
Text = "Check for updates",
|
||||
Text = GeneralSettingsStrings.CheckUpdate,
|
||||
Action = () =>
|
||||
{
|
||||
checkForUpdatesButton.Enabled.Value = false;
|
||||
@ -65,13 +66,13 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
{
|
||||
Add(new SettingsButton
|
||||
{
|
||||
Text = "Open osu! folder",
|
||||
Text = GeneralSettingsStrings.OpenOsuFolder,
|
||||
Action = storage.OpenInNativeExplorer,
|
||||
});
|
||||
|
||||
Add(new SettingsButton
|
||||
{
|
||||
Text = "Change folder location...",
|
||||
Text = GeneralSettingsStrings.ChangeFolderLocation,
|
||||
Action = () => game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen()))
|
||||
});
|
||||
}
|
||||
|
@ -3,13 +3,15 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings.Sections.General;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class GeneralSection : SettingsSection
|
||||
{
|
||||
public override string Header => "General";
|
||||
public override LocalisableString Header => GeneralSettingsStrings.GeneralSectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
|
@ -5,12 +5,13 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
{
|
||||
public class DetailSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Detail Settings";
|
||||
protected override LocalisableString Header => GraphicsSettingsStrings.DetailSettingsHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -19,22 +20,22 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Storyboard / Video",
|
||||
LabelText = GraphicsSettingsStrings.StoryboardVideo,
|
||||
Current = config.GetBindable<bool>(OsuSetting.ShowStoryboard)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Hit Lighting",
|
||||
LabelText = GraphicsSettingsStrings.HitLighting,
|
||||
Current = config.GetBindable<bool>(OsuSetting.HitLighting)
|
||||
},
|
||||
new SettingsEnumDropdown<ScreenshotFormat>
|
||||
{
|
||||
LabelText = "Screenshot format",
|
||||
LabelText = GraphicsSettingsStrings.ScreenshotFormat,
|
||||
Current = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show menu cursor in screenshots",
|
||||
LabelText = GraphicsSettingsStrings.ShowCursorInScreenshots,
|
||||
Current = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor)
|
||||
}
|
||||
};
|
||||
|
@ -16,13 +16,14 @@ using osu.Framework.Platform;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
{
|
||||
public class LayoutSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Layout";
|
||||
protected override LocalisableString Header => GraphicsSettingsStrings.LayoutHeader;
|
||||
|
||||
private FillFlowContainer<SettingsSlider<float>> scalingSettings;
|
||||
|
||||
@ -67,20 +68,20 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
{
|
||||
windowModeDropdown = new SettingsDropdown<WindowMode>
|
||||
{
|
||||
LabelText = "Screen mode",
|
||||
LabelText = GraphicsSettingsStrings.ScreenMode,
|
||||
ItemSource = windowModes,
|
||||
Current = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
|
||||
},
|
||||
resolutionDropdown = new ResolutionSettingsDropdown
|
||||
{
|
||||
LabelText = "Resolution",
|
||||
LabelText = GraphicsSettingsStrings.Resolution,
|
||||
ShowsDefaultIndicator = false,
|
||||
ItemSource = resolutions,
|
||||
Current = sizeFullscreen
|
||||
},
|
||||
new SettingsSlider<float, UIScaleSlider>
|
||||
{
|
||||
LabelText = "UI Scaling",
|
||||
LabelText = GraphicsSettingsStrings.UIScaling,
|
||||
TransferValueOnCommit = true,
|
||||
Current = osuConfig.GetBindable<float>(OsuSetting.UIScale),
|
||||
KeyboardStep = 0.01f,
|
||||
@ -88,7 +89,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
},
|
||||
new SettingsEnumDropdown<ScalingMode>
|
||||
{
|
||||
LabelText = "Screen Scaling",
|
||||
LabelText = GraphicsSettingsStrings.ScreenScaling,
|
||||
Current = osuConfig.GetBindable<ScalingMode>(OsuSetting.Scaling),
|
||||
Keywords = new[] { "scale", "letterbox" },
|
||||
},
|
||||
@ -104,28 +105,28 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
{
|
||||
new SettingsSlider<float>
|
||||
{
|
||||
LabelText = "Horizontal position",
|
||||
LabelText = GraphicsSettingsStrings.HorizontalPosition,
|
||||
Current = scalingPositionX,
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsSlider<float>
|
||||
{
|
||||
LabelText = "Vertical position",
|
||||
LabelText = GraphicsSettingsStrings.VerticalPosition,
|
||||
Current = scalingPositionY,
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsSlider<float>
|
||||
{
|
||||
LabelText = "Horizontal scale",
|
||||
LabelText = GraphicsSettingsStrings.HorizontalScale,
|
||||
Current = scalingSizeX,
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsSlider<float>
|
||||
{
|
||||
LabelText = "Vertical scale",
|
||||
LabelText = GraphicsSettingsStrings.VerticalScale,
|
||||
Current = scalingSizeY,
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
@ -145,9 +146,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
{
|
||||
updateResolutionDropdown();
|
||||
|
||||
const string not_fullscreen_note = "Running without fullscreen mode will increase your input latency!";
|
||||
|
||||
windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? not_fullscreen_note : string.Empty;
|
||||
windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : default;
|
||||
}, true);
|
||||
|
||||
windowModes.BindCollectionChanged((sender, args) =>
|
||||
@ -245,7 +244,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
protected override LocalisableString GenerateItemText(Size item)
|
||||
{
|
||||
if (item == new Size(9999, 9999))
|
||||
return "Default";
|
||||
return CommonStrings.Default;
|
||||
|
||||
return $"{item.Width}x{item.Height}";
|
||||
}
|
||||
|
@ -7,12 +7,13 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
{
|
||||
public class RendererSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Renderer";
|
||||
protected override LocalisableString Header => GraphicsSettingsStrings.RendererHeader;
|
||||
|
||||
private SettingsEnumDropdown<FrameSync> frameLimiterDropdown;
|
||||
|
||||
@ -25,17 +26,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
// TODO: this needs to be a custom dropdown at some point
|
||||
frameLimiterDropdown = new SettingsEnumDropdown<FrameSync>
|
||||
{
|
||||
LabelText = "Frame limiter",
|
||||
LabelText = GraphicsSettingsStrings.FrameLimiter,
|
||||
Current = config.GetBindable<FrameSync>(FrameworkSetting.FrameSync)
|
||||
},
|
||||
new SettingsEnumDropdown<ExecutionMode>
|
||||
{
|
||||
LabelText = "Threading mode",
|
||||
LabelText = GraphicsSettingsStrings.ThreadingMode,
|
||||
Current = config.GetBindable<ExecutionMode>(FrameworkSetting.ExecutionMode)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show FPS",
|
||||
LabelText = GraphicsSettingsStrings.ShowFPS,
|
||||
Current = osuConfig.GetBindable<bool>(OsuSetting.ShowFpsDisplay)
|
||||
},
|
||||
};
|
||||
@ -47,9 +48,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
|
||||
frameLimiterDropdown.Current.BindValueChanged(limit =>
|
||||
{
|
||||
const string unlimited_frames_note = "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. \"2x refresh rate\" is recommended.";
|
||||
|
||||
frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? unlimited_frames_note : string.Empty;
|
||||
frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? GraphicsSettingsStrings.UnlimitedFramesNote : default;
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,15 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings.Sections.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class GraphicsSection : SettingsSection
|
||||
{
|
||||
public override string Header => "Graphics";
|
||||
public override LocalisableString Header => GraphicsSettingsStrings.GraphicsSectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
{
|
||||
@ -15,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
Icon = FontAwesome.Solid.Globe
|
||||
};
|
||||
|
||||
public override string Header => "Global";
|
||||
public override LocalisableString Header => InputSettingsStrings.GlobalKeyBindingHeader;
|
||||
|
||||
public GlobalKeyBindingsSection(GlobalActionContainer manager)
|
||||
{
|
||||
@ -39,7 +40,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
|
||||
private class SongSelectKeyBindingSubsection : KeyBindingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Song Select";
|
||||
protected override LocalisableString Header => InputSettingsStrings.SongSelectSection;
|
||||
|
||||
public SongSelectKeyBindingSubsection(GlobalActionContainer manager)
|
||||
: base(null)
|
||||
@ -50,7 +51,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
|
||||
private class InGameKeyBindingsSubsection : KeyBindingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "In Game";
|
||||
protected override LocalisableString Header => InputSettingsStrings.InGameSection;
|
||||
|
||||
public InGameKeyBindingsSubsection(GlobalActionContainer manager)
|
||||
: base(null)
|
||||
@ -61,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
|
||||
private class AudioControlKeyBindingsSubsection : KeyBindingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Audio";
|
||||
protected override LocalisableString Header => InputSettingsStrings.AudioSection;
|
||||
|
||||
public AudioControlKeyBindingsSubsection(GlobalActionContainer manager)
|
||||
: base(null)
|
||||
@ -72,7 +73,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
|
||||
private class EditorKeyBindingsSubsection : KeyBindingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Editor";
|
||||
protected override LocalisableString Header => InputSettingsStrings.EditorSection;
|
||||
|
||||
public EditorKeyBindingsSubsection(GlobalActionContainer manager)
|
||||
: base(null)
|
||||
|
@ -4,13 +4,14 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
{
|
||||
public class KeyBindingPanel : SettingsSubPanel
|
||||
{
|
||||
protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!");
|
||||
protected override Drawable CreateHeader() => new SettingsHeader(InputSettingsStrings.KeyBindingPanelHeader, InputSettingsStrings.KeyBindingPanelDescription);
|
||||
|
||||
[BackgroundDependencyLoader(permitNulls: true)]
|
||||
private void load(RulesetStore rulesets, GlobalActionContainer global)
|
||||
|
@ -20,6 +20,7 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Localisation;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
@ -385,7 +386,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
{
|
||||
public CancelButton()
|
||||
{
|
||||
Text = "Cancel";
|
||||
Text = CommonStrings.Cancel;
|
||||
Size = new Vector2(80, 20);
|
||||
}
|
||||
}
|
||||
@ -394,7 +395,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
{
|
||||
public ClearButton()
|
||||
{
|
||||
Text = "Clear";
|
||||
Text = CommonStrings.Clear;
|
||||
Size = new Vector2(80, 20);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ using osu.Game.Database;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Localisation;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
@ -64,7 +65,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Text = "Reset all bindings in section";
|
||||
Text = InputSettingsStrings.ResetSectionButton;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Width = 0.5f;
|
||||
Anchor = Anchor.TopCentre;
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets;
|
||||
|
||||
@ -15,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
Icon = OsuIcon.Hot
|
||||
};
|
||||
|
||||
public override string Header => ruleset.Name;
|
||||
public override LocalisableString Header => ruleset.Name;
|
||||
|
||||
private readonly RulesetInfo ruleset;
|
||||
|
||||
|
@ -22,6 +22,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
{
|
||||
private readonly ITabletHandler tabletHandler;
|
||||
|
||||
private readonly Bindable<bool> enabled = new BindableBool(true);
|
||||
|
||||
private readonly Bindable<Vector2> areaOffset = new Bindable<Vector2>();
|
||||
private readonly Bindable<Vector2> areaSize = new Bindable<Vector2>();
|
||||
private readonly IBindable<TabletInfo> tablet = new Bindable<TabletInfo>();
|
||||
@ -74,7 +76,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
LabelText = CommonStrings.Enabled,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Current = tabletHandler.Enabled
|
||||
Current = enabled,
|
||||
},
|
||||
noTabletMessage = new FillFlowContainer
|
||||
{
|
||||
@ -194,6 +196,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
enabled.BindTo(tabletHandler.Enabled);
|
||||
enabled.BindValueChanged(_ => Scheduler.AddOnce(updateVisibility));
|
||||
|
||||
rotation.BindTo(tabletHandler.Rotation);
|
||||
|
||||
areaOffset.BindTo(tabletHandler.AreaOffset);
|
||||
@ -239,7 +244,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
tablet.BindTo(tabletHandler.Tablet);
|
||||
tablet.BindValueChanged(val =>
|
||||
{
|
||||
Scheduler.AddOnce(toggleVisibility);
|
||||
Scheduler.AddOnce(updateVisibility);
|
||||
|
||||
var tab = val.NewValue;
|
||||
|
||||
@ -259,19 +264,18 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void toggleVisibility()
|
||||
private void updateVisibility()
|
||||
{
|
||||
bool tabletFound = tablet.Value != null;
|
||||
|
||||
if (!tabletFound)
|
||||
{
|
||||
mainSettings.Hide();
|
||||
noTabletMessage.Show();
|
||||
return;
|
||||
}
|
||||
|
||||
mainSettings.Show();
|
||||
mainSettings.Hide();
|
||||
noTabletMessage.Hide();
|
||||
|
||||
if (!tabletHandler.Enabled.Value)
|
||||
return;
|
||||
|
||||
if (tablet.Value != null)
|
||||
mainSettings.Show();
|
||||
else
|
||||
noTabletMessage.Show();
|
||||
}
|
||||
|
||||
private void applyAspectRatio(BindableNumber<float> sizeChanged)
|
||||
|
@ -11,6 +11,7 @@ using osu.Framework.Input.Handlers.Mouse;
|
||||
using osu.Framework.Input.Handlers.Tablet;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings.Sections.Input;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
private readonly KeyBindingPanel keyConfig;
|
||||
|
||||
public override string Header => "Input";
|
||||
public override LocalisableString Header => InputSettingsStrings.InputSectionHeader;
|
||||
|
||||
[Resolved]
|
||||
private GameHost host { get; set; }
|
||||
@ -95,7 +96,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Enabled",
|
||||
LabelText = CommonStrings.Enabled,
|
||||
Current = handler.Enabled
|
||||
},
|
||||
};
|
||||
|
@ -14,6 +14,7 @@ using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
{
|
||||
@ -104,7 +105,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
Origin = Anchor.Centre,
|
||||
Width = 300,
|
||||
Margin = new MarginPadding(10),
|
||||
Text = "Select directory",
|
||||
Text = MaintenanceSettingsStrings.SelectDirectory,
|
||||
Action = () => OnSelection(directorySelector.CurrentPath.Value)
|
||||
},
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Collections;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
@ -37,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
{
|
||||
Add(importBeatmapsButton = new SettingsButton
|
||||
{
|
||||
Text = "Import beatmaps from stable",
|
||||
Text = MaintenanceSettingsStrings.ImportBeatmapsFromStable,
|
||||
Action = () =>
|
||||
{
|
||||
importBeatmapsButton.Enabled.Value = false;
|
||||
@ -48,7 +49,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
|
||||
Add(deleteBeatmapsButton = new DangerousSettingsButton
|
||||
{
|
||||
Text = "Delete ALL beatmaps",
|
||||
Text = MaintenanceSettingsStrings.DeleteAllBeatmaps,
|
||||
Action = () =>
|
||||
{
|
||||
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
|
||||
@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
{
|
||||
Add(importScoresButton = new SettingsButton
|
||||
{
|
||||
Text = "Import scores from stable",
|
||||
Text = MaintenanceSettingsStrings.ImportScoresFromStable,
|
||||
Action = () =>
|
||||
{
|
||||
importScoresButton.Enabled.Value = false;
|
||||
@ -74,7 +75,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
|
||||
Add(deleteScoresButton = new DangerousSettingsButton
|
||||
{
|
||||
Text = "Delete ALL scores",
|
||||
Text = MaintenanceSettingsStrings.DeleteAllScores,
|
||||
Action = () =>
|
||||
{
|
||||
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
|
||||
@ -89,7 +90,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
{
|
||||
Add(importSkinsButton = new SettingsButton
|
||||
{
|
||||
Text = "Import skins from stable",
|
||||
Text = MaintenanceSettingsStrings.ImportSkinsFromStable,
|
||||
Action = () =>
|
||||
{
|
||||
importSkinsButton.Enabled.Value = false;
|
||||
@ -100,7 +101,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
|
||||
Add(deleteSkinsButton = new DangerousSettingsButton
|
||||
{
|
||||
Text = "Delete ALL skins",
|
||||
Text = MaintenanceSettingsStrings.DeleteAllSkins,
|
||||
Action = () =>
|
||||
{
|
||||
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
|
||||
@ -117,7 +118,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
{
|
||||
Add(importCollectionsButton = new SettingsButton
|
||||
{
|
||||
Text = "Import collections from stable",
|
||||
Text = MaintenanceSettingsStrings.ImportCollectionsFromStable,
|
||||
Action = () =>
|
||||
{
|
||||
importCollectionsButton.Enabled.Value = false;
|
||||
@ -128,7 +129,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
|
||||
Add(new DangerousSettingsButton
|
||||
{
|
||||
Text = "Delete ALL collections",
|
||||
Text = MaintenanceSettingsStrings.DeleteAllCollections,
|
||||
Action = () =>
|
||||
{
|
||||
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(collectionManager.DeleteAll));
|
||||
@ -140,7 +141,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
{
|
||||
restoreButton = new SettingsButton
|
||||
{
|
||||
Text = "Restore all hidden difficulties",
|
||||
Text = MaintenanceSettingsStrings.RestoreAllHiddenDifficulties,
|
||||
Action = () =>
|
||||
{
|
||||
restoreButton.Enabled.Value = false;
|
||||
@ -153,7 +154,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
},
|
||||
undeleteButton = new SettingsButton
|
||||
{
|
||||
Text = "Restore all recently deleted beatmaps",
|
||||
Text = MaintenanceSettingsStrings.RestoreAllRecentlyDeletedBeatmaps,
|
||||
Action = () =>
|
||||
{
|
||||
undeleteButton.Enabled.Value = false;
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings.Sections.Maintenance;
|
||||
using osuTK;
|
||||
|
||||
@ -10,7 +12,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class MaintenanceSection : SettingsSection
|
||||
{
|
||||
public override string Header => "Maintenance";
|
||||
public override LocalisableString Header => MaintenanceSettingsStrings.MaintenanceSectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
|
@ -5,12 +5,13 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Online
|
||||
{
|
||||
public class AlertsAndPrivacySettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Alerts and Privacy";
|
||||
protected override LocalisableString Header => OnlineSettingsStrings.AlertsAndPrivacyHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -19,12 +20,12 @@ namespace osu.Game.Overlays.Settings.Sections.Online
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show a notification when someone mentions your name",
|
||||
LabelText = OnlineSettingsStrings.NotifyOnMentioned,
|
||||
Current = config.GetBindable<bool>(OsuSetting.NotifyOnUsernameMentioned)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show a notification when you receive a private message",
|
||||
LabelText = OnlineSettingsStrings.NotifyOnPrivateMessage,
|
||||
Current = config.GetBindable<bool>(OsuSetting.NotifyOnPrivateMessage)
|
||||
},
|
||||
};
|
||||
|
@ -5,12 +5,13 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Online
|
||||
{
|
||||
public class IntegrationSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Integrations";
|
||||
protected override LocalisableString Header => OnlineSettingsStrings.IntegrationsHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online
|
||||
{
|
||||
new SettingsEnumDropdown<DiscordRichPresenceMode>
|
||||
{
|
||||
LabelText = "Discord Rich Presence",
|
||||
LabelText = OnlineSettingsStrings.DiscordRichPresence,
|
||||
Current = config.GetBindable<DiscordRichPresenceMode>(OsuSetting.DiscordRichPresence)
|
||||
}
|
||||
};
|
||||
|
@ -5,12 +5,13 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Online
|
||||
{
|
||||
public class WebSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Web";
|
||||
protected override LocalisableString Header => OnlineSettingsStrings.WebHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -19,24 +20,24 @@ namespace osu.Game.Overlays.Settings.Sections.Online
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Warn about opening external links",
|
||||
LabelText = OnlineSettingsStrings.ExternalLinkWarning,
|
||||
Current = config.GetBindable<bool>(OsuSetting.ExternalLinkWarning)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Prefer downloads without video",
|
||||
LabelText = OnlineSettingsStrings.PreferNoVideo,
|
||||
Keywords = new[] { "no-video" },
|
||||
Current = config.GetBindable<bool>(OsuSetting.PreferNoVideo)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Automatically download beatmaps when spectating",
|
||||
LabelText = OnlineSettingsStrings.AutomaticallyDownloadWhenSpectating,
|
||||
Keywords = new[] { "spectator" },
|
||||
Current = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadWhenSpectating),
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show explicit content in search results",
|
||||
LabelText = OnlineSettingsStrings.ShowExplicitContent,
|
||||
Keywords = new[] { "nsfw", "18+", "offensive" },
|
||||
Current = config.GetBindable<bool>(OsuSetting.ShowOnlineExplicitContent),
|
||||
}
|
||||
|
@ -3,13 +3,15 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings.Sections.Online;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class OnlineSection : SettingsSection
|
||||
{
|
||||
public override string Header => "Online";
|
||||
public override LocalisableString Header => OnlineSettingsStrings.OnlineSectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Skinning.Editor;
|
||||
using osuTK;
|
||||
@ -23,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
private SkinSettingsDropdown skinDropdown;
|
||||
|
||||
public override string Header => "Skin";
|
||||
public override LocalisableString Header => SkinSettingsStrings.SkinSectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
@ -69,34 +70,34 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
skinDropdown = new SkinSettingsDropdown(),
|
||||
new SettingsButton
|
||||
{
|
||||
Text = "Skin layout editor",
|
||||
Text = SkinSettingsStrings.SkinLayoutEditor,
|
||||
Action = () => skinEditor?.Toggle(),
|
||||
},
|
||||
new ExportSkinButton(),
|
||||
new SettingsSlider<float, SizeSlider>
|
||||
{
|
||||
LabelText = "Gameplay cursor size",
|
||||
LabelText = SkinSettingsStrings.GameplayCursorSize,
|
||||
Current = config.GetBindable<float>(OsuSetting.GameplayCursorSize),
|
||||
KeyboardStep = 0.01f
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Adjust gameplay cursor size based on current beatmap",
|
||||
LabelText = SkinSettingsStrings.AutoCursorSize,
|
||||
Current = config.GetBindable<bool>(OsuSetting.AutoCursorSize)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Beatmap skins",
|
||||
LabelText = SkinSettingsStrings.BeatmapSkins,
|
||||
Current = config.GetBindable<bool>(OsuSetting.BeatmapSkins)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Beatmap colours",
|
||||
LabelText = SkinSettingsStrings.BeatmapColours,
|
||||
Current = config.GetBindable<bool>(OsuSetting.BeatmapColours)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Beatmap hitsounds",
|
||||
LabelText = SkinSettingsStrings.BeatmapHitsounds,
|
||||
Current = config.GetBindable<bool>(OsuSetting.BeatmapHitsounds)
|
||||
},
|
||||
};
|
||||
@ -200,7 +201,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Text = "Export selected skin";
|
||||
Text = SkinSettingsStrings.ExportSkinButton;
|
||||
Action = export;
|
||||
|
||||
currentSkin = skins.CurrentSkin.GetBoundCopy();
|
||||
|
@ -6,12 +6,13 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
{
|
||||
public class GeneralSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "General";
|
||||
protected override LocalisableString Header => UserInterfaceStrings.GeneralHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -20,23 +21,23 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Rotate cursor when dragging",
|
||||
LabelText = UserInterfaceStrings.CursorRotation,
|
||||
Current = config.GetBindable<bool>(OsuSetting.CursorRotation)
|
||||
},
|
||||
new SettingsSlider<float, SizeSlider>
|
||||
{
|
||||
LabelText = "Menu cursor size",
|
||||
LabelText = UserInterfaceStrings.MenuCursorSize,
|
||||
Current = config.GetBindable<float>(OsuSetting.MenuCursorSize),
|
||||
KeyboardStep = 0.01f
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Parallax",
|
||||
LabelText = UserInterfaceStrings.Parallax,
|
||||
Current = config.GetBindable<bool>(OsuSetting.MenuParallax)
|
||||
},
|
||||
new SettingsSlider<float, TimeSlider>
|
||||
{
|
||||
LabelText = "Hold-to-confirm activation time",
|
||||
LabelText = UserInterfaceStrings.HoldToConfirmActivationTime,
|
||||
Current = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay),
|
||||
KeyboardStep = 50
|
||||
},
|
||||
|
@ -6,6 +6,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Users;
|
||||
|
||||
@ -13,7 +14,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
{
|
||||
public class MainMenuSettings : SettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "Main Menu";
|
||||
protected override LocalisableString Header => UserInterfaceStrings.MainMenuHeader;
|
||||
|
||||
private IBindable<User> user;
|
||||
|
||||
@ -28,27 +29,27 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Interface voices",
|
||||
LabelText = UserInterfaceStrings.InterfaceVoices,
|
||||
Current = config.GetBindable<bool>(OsuSetting.MenuVoice)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "osu! music theme",
|
||||
LabelText = UserInterfaceStrings.OsuMusicTheme,
|
||||
Current = config.GetBindable<bool>(OsuSetting.MenuMusic)
|
||||
},
|
||||
new SettingsEnumDropdown<IntroSequence>
|
||||
{
|
||||
LabelText = "Intro sequence",
|
||||
LabelText = UserInterfaceStrings.IntroSequence,
|
||||
Current = config.GetBindable<IntroSequence>(OsuSetting.IntroSequence),
|
||||
},
|
||||
backgroundSourceDropdown = new SettingsEnumDropdown<BackgroundSource>
|
||||
{
|
||||
LabelText = "Background source",
|
||||
LabelText = UserInterfaceStrings.BackgroundSource,
|
||||
Current = config.GetBindable<BackgroundSource>(OsuSetting.MenuBackgroundSource),
|
||||
},
|
||||
new SettingsEnumDropdown<SeasonalBackgroundMode>
|
||||
{
|
||||
LabelText = "Seasonal backgrounds",
|
||||
LabelText = UserInterfaceStrings.SeasonalBackgrounds,
|
||||
Current = config.GetBindable<SeasonalBackgroundMode>(OsuSetting.SeasonalBackgroundMode),
|
||||
}
|
||||
};
|
||||
@ -60,9 +61,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
|
||||
user.BindValueChanged(u =>
|
||||
{
|
||||
const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag.";
|
||||
|
||||
backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? not_supporter_note : string.Empty;
|
||||
backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? UserInterfaceStrings.NotSupporterNote : default;
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
{
|
||||
@ -16,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
private Bindable<double> minStars;
|
||||
private Bindable<double> maxStars;
|
||||
|
||||
protected override LocalisableString Header => "Song Select";
|
||||
protected override LocalisableString Header => UserInterfaceStrings.SongSelectHeader;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -31,31 +32,31 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Right mouse drag to absolute scroll",
|
||||
LabelText = UserInterfaceStrings.RightMouseScroll,
|
||||
Current = config.GetBindable<bool>(OsuSetting.SongSelectRightMouseScroll),
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Show converted beatmaps",
|
||||
LabelText = UserInterfaceStrings.ShowConvertedBeatmaps,
|
||||
Current = config.GetBindable<bool>(OsuSetting.ShowConvertedBeatmaps),
|
||||
},
|
||||
new SettingsSlider<double, StarsSlider>
|
||||
{
|
||||
LabelText = "Display beatmaps from",
|
||||
LabelText = UserInterfaceStrings.StarsMinimum,
|
||||
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
|
||||
KeyboardStep = 0.1f,
|
||||
Keywords = new[] { "minimum", "maximum", "star", "difficulty" }
|
||||
},
|
||||
new SettingsSlider<double, MaximumStarsSlider>
|
||||
{
|
||||
LabelText = "up to",
|
||||
LabelText = UserInterfaceStrings.StarsMaximum,
|
||||
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
|
||||
KeyboardStep = 0.1f,
|
||||
Keywords = new[] { "minimum", "maximum", "star", "difficulty" }
|
||||
},
|
||||
new SettingsEnumDropdown<RandomSelectAlgorithm>
|
||||
{
|
||||
LabelText = "Random selection algorithm",
|
||||
LabelText = UserInterfaceStrings.RandomSelectionAlgorithm,
|
||||
Current = config.GetBindable<RandomSelectAlgorithm>(OsuSetting.RandomSelectAlgorithm),
|
||||
}
|
||||
};
|
||||
@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
|
||||
private class MaximumStarsSlider : StarsSlider
|
||||
{
|
||||
public override LocalisableString TooltipText => Current.IsDefault ? "no limit" : base.TooltipText;
|
||||
public override LocalisableString TooltipText => Current.IsDefault ? UserInterfaceStrings.NoLimit : base.TooltipText;
|
||||
}
|
||||
|
||||
private class StarsSlider : OsuSliderBar<double>
|
||||
|
@ -3,13 +3,15 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings.Sections.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class UserInterfaceSection : SettingsSection
|
||||
{
|
||||
public override string Header => "User Interface";
|
||||
public override LocalisableString Header => UserInterfaceStrings.UserInterfaceSectionHeader;
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon
|
||||
{
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osuTK.Graphics;
|
||||
@ -19,10 +20,10 @@ namespace osu.Game.Overlays.Settings
|
||||
protected override Container<Drawable> Content => FlowContent;
|
||||
|
||||
public abstract Drawable CreateIcon();
|
||||
public abstract string Header { get; }
|
||||
public abstract LocalisableString Header { get; }
|
||||
|
||||
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
|
||||
public virtual IEnumerable<string> FilterTerms => new[] { Header };
|
||||
public virtual IEnumerable<string> FilterTerms => new[] { Header.ToString() };
|
||||
|
||||
private const int header_size = 26;
|
||||
private const int margin = 20;
|
||||
|
@ -24,6 +24,11 @@ namespace osu.Game.Overlays.Settings
|
||||
protected abstract LocalisableString Header { get; }
|
||||
|
||||
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
|
||||
|
||||
// FilterTerms should contains both original string and localised string for user to search.
|
||||
// Since LocalisableString is unable to get original string at this time (2021-08-14),
|
||||
// only call .ToString() to use localised one.
|
||||
// TODO: Update here when FilterTerms accept LocalisableString.
|
||||
public virtual IEnumerable<string> FilterTerms => new[] { Header.ToString() };
|
||||
|
||||
public bool MatchingFilter
|
||||
|
@ -4,6 +4,7 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Performance
|
||||
{
|
||||
@ -12,9 +13,9 @@ namespace osu.Game.Performance
|
||||
private readonly IBindable<bool> localUserPlaying = new Bindable<bool>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGame game)
|
||||
private void load(ILocalUserPlayInfo localUserInfo)
|
||||
{
|
||||
localUserPlaying.BindTo(game.LocalUserPlaying);
|
||||
localUserPlaying.BindTo(localUserInfo.IsPlaying);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
54
osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs
Normal file
54
osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Difficulty.Skills
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to processes strain values of <see cref="DifficultyHitObject"/>s, keep track of strain levels caused by the processed objects
|
||||
/// and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
|
||||
/// </summary>
|
||||
public abstract class StrainDecaySkill : StrainSkill
|
||||
{
|
||||
/// <summary>
|
||||
/// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other.
|
||||
/// </summary>
|
||||
protected abstract double SkillMultiplier { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines how quickly strain decays for the given skill.
|
||||
/// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second.
|
||||
/// </summary>
|
||||
protected abstract double StrainDecayBase { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The current strain level.
|
||||
/// </summary>
|
||||
protected double CurrentStrain { get; private set; } = 1;
|
||||
|
||||
protected StrainDecaySkill(Mod[] mods)
|
||||
: base(mods)
|
||||
{
|
||||
}
|
||||
|
||||
protected override double CalculateInitialStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime);
|
||||
|
||||
protected override double StrainValueAt(DifficultyHitObject current)
|
||||
{
|
||||
CurrentStrain *= strainDecay(current.DeltaTime);
|
||||
CurrentStrain += StrainValueOf(current) * SkillMultiplier;
|
||||
|
||||
return CurrentStrain;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the strain value of a <see cref="DifficultyHitObject"/>. This value is affected by previously processed objects.
|
||||
/// </summary>
|
||||
protected abstract double StrainValueOf(DifficultyHitObject current);
|
||||
|
||||
private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000);
|
||||
}
|
||||
}
|
@ -15,27 +15,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills
|
||||
/// </summary>
|
||||
public abstract class StrainSkill : Skill
|
||||
{
|
||||
/// <summary>
|
||||
/// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other.
|
||||
/// </summary>
|
||||
protected abstract double SkillMultiplier { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines how quickly strain decays for the given skill.
|
||||
/// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second.
|
||||
/// </summary>
|
||||
protected abstract double StrainDecayBase { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The weight by which each strain value decays.
|
||||
/// </summary>
|
||||
protected virtual double DecayWeight => 0.9;
|
||||
|
||||
/// <summary>
|
||||
/// The current strain level.
|
||||
/// </summary>
|
||||
protected double CurrentStrain { get; private set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The length of each strain section.
|
||||
/// </summary>
|
||||
@ -52,6 +36,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the strain value at <see cref="DifficultyHitObject"/>. This value is calculated with or without respect to previous objects.
|
||||
/// </summary>
|
||||
protected abstract double StrainValueAt(DifficultyHitObject current);
|
||||
|
||||
/// <summary>
|
||||
/// Process a <see cref="DifficultyHitObject"/> and update current strain values accordingly.
|
||||
/// </summary>
|
||||
@ -68,10 +57,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills
|
||||
currentSectionEnd += SectionLength;
|
||||
}
|
||||
|
||||
CurrentStrain *= strainDecay(current.DeltaTime);
|
||||
CurrentStrain += StrainValueOf(current) * SkillMultiplier;
|
||||
|
||||
currentSectionPeak = Math.Max(CurrentStrain, currentSectionPeak);
|
||||
currentSectionPeak = Math.Max(StrainValueAt(current), currentSectionPeak);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -88,9 +74,9 @@ namespace osu.Game.Rulesets.Difficulty.Skills
|
||||
/// <param name="time">The beginning of the new section in milliseconds.</param>
|
||||
private void startNewSectionFrom(double time)
|
||||
{
|
||||
// The maximum strain of the new section is not zero by default, strain decays as usual regardless of section boundaries.
|
||||
// The maximum strain of the new section is not zero by default
|
||||
// This means we need to capture the strain level at the beginning of the new section, and use that as the initial peak level.
|
||||
currentSectionPeak = GetPeakStrain(time);
|
||||
currentSectionPeak = CalculateInitialStrain(time);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -98,7 +84,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills
|
||||
/// </summary>
|
||||
/// <param name="time">The time to retrieve the peak strain at.</param>
|
||||
/// <returns>The peak strain.</returns>
|
||||
protected virtual double GetPeakStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime);
|
||||
protected abstract double CalculateInitialStrain(double time);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a live enumerable of the peak strains for each <see cref="SectionLength"/> section of the beatmap,
|
||||
@ -124,12 +110,5 @@ namespace osu.Game.Rulesets.Difficulty.Skills
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the strain value of a <see cref="DifficultyHitObject"/>. This value is affected by previously processed objects.
|
||||
/// </summary>
|
||||
protected abstract double StrainValueOf(DifficultyHitObject current);
|
||||
|
||||
private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000);
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,13 @@ namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
// This is required as SettingsItem relies heavily on this bindable for internal use.
|
||||
// The actual update flow is done via the bindable provided in the constructor.
|
||||
public Bindable<float?> Current { get; set; } = new Bindable<float?>();
|
||||
private readonly BindableWithCurrent<float?> current = new BindableWithCurrent<float?>();
|
||||
|
||||
public Bindable<float?> Current
|
||||
{
|
||||
get => current.Current;
|
||||
set => current.Current = value;
|
||||
}
|
||||
|
||||
public SliderControl(BindableNumber<float> currentNumber)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
@ -14,8 +15,10 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
/// </summary>
|
||||
public class ListingPollingComponent : RoomPollingComponent
|
||||
{
|
||||
[Resolved]
|
||||
private Bindable<FilterCriteria> currentFilter { get; set; }
|
||||
public IBindable<bool> InitialRoomsReceived => initialRoomsReceived;
|
||||
private readonly Bindable<bool> initialRoomsReceived = new Bindable<bool>();
|
||||
|
||||
public readonly Bindable<FilterCriteria> Filter = new Bindable<FilterCriteria>();
|
||||
|
||||
[Resolved]
|
||||
private Bindable<Room> selectedRoom { get; set; }
|
||||
@ -23,9 +26,11 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
currentFilter.BindValueChanged(_ =>
|
||||
Filter.BindValueChanged(_ =>
|
||||
{
|
||||
NotifyRoomsReceived(null);
|
||||
RoomManager.ClearRooms();
|
||||
initialRoomsReceived.Value = false;
|
||||
|
||||
if (IsLoaded)
|
||||
PollImmediately();
|
||||
});
|
||||
@ -38,24 +43,26 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
if (!API.IsLoggedIn)
|
||||
return base.Poll();
|
||||
|
||||
if (Filter.Value == null)
|
||||
return base.Poll();
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
pollReq?.Cancel();
|
||||
pollReq = new GetRoomsRequest(currentFilter.Value.Status, currentFilter.Value.Category);
|
||||
pollReq = new GetRoomsRequest(Filter.Value.Status, Filter.Value.Category);
|
||||
|
||||
pollReq.Success += result =>
|
||||
{
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
foreach (var existing in RoomManager.Rooms.ToArray())
|
||||
{
|
||||
if (result[i].RoomID.Value == selectedRoom.Value?.RoomID.Value)
|
||||
{
|
||||
// The listing request always has less information than the opened room, so don't include it.
|
||||
result[i] = selectedRoom.Value;
|
||||
break;
|
||||
}
|
||||
if (result.All(r => r.RoomID.Value != existing.RoomID.Value))
|
||||
RoomManager.RemoveRoom(existing);
|
||||
}
|
||||
|
||||
NotifyRoomsReceived(result);
|
||||
foreach (var incoming in result)
|
||||
RoomManager.AddOrUpdateRoom(incoming);
|
||||
|
||||
initialRoomsReceived.Value = true;
|
||||
tcs.SetResult(true);
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,6 @@ using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
@ -17,15 +16,12 @@ using osu.Game.Rulesets;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Components
|
||||
{
|
||||
public abstract class RoomManager : CompositeDrawable, IRoomManager
|
||||
public class RoomManager : Component, IRoomManager
|
||||
{
|
||||
public event Action RoomsUpdated;
|
||||
|
||||
private readonly BindableList<Room> rooms = new BindableList<Room>();
|
||||
|
||||
public IBindable<bool> InitialRoomsReceived => initialRoomsReceived;
|
||||
private readonly Bindable<bool> initialRoomsReceived = new Bindable<bool>();
|
||||
|
||||
public IBindableList<Room> Rooms => rooms;
|
||||
|
||||
protected IBindable<Room> JoinedRoom => joinedRoom;
|
||||
@ -40,15 +36,9 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
protected RoomManager()
|
||||
public RoomManager()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = CreatePollingComponents().Select(p =>
|
||||
{
|
||||
p.RoomsReceived = onRoomsReceived;
|
||||
return p;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
@ -67,10 +57,10 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
{
|
||||
joinedRoom.Value = room;
|
||||
|
||||
update(room, result);
|
||||
addRoom(room);
|
||||
AddOrUpdateRoom(result);
|
||||
room.CopyFrom(result); // Also copy back to the source model, since this is likely to have been stored elsewhere.
|
||||
|
||||
RoomsUpdated?.Invoke();
|
||||
// The server may not contain all properties (such as password), so invoke success with the given room.
|
||||
onSuccess?.Invoke(room);
|
||||
};
|
||||
|
||||
@ -118,84 +108,49 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
|
||||
private readonly HashSet<long> ignoredRooms = new HashSet<long>();
|
||||
|
||||
private void onRoomsReceived(List<Room> received)
|
||||
public void AddOrUpdateRoom(Room room)
|
||||
{
|
||||
if (received == null)
|
||||
{
|
||||
ClearRooms();
|
||||
Debug.Assert(room.RoomID.Value != null);
|
||||
|
||||
if (ignoredRooms.Contains(room.RoomID.Value.Value))
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove past matches
|
||||
foreach (var r in rooms.ToList())
|
||||
room.Position.Value = -room.RoomID.Value.Value;
|
||||
|
||||
try
|
||||
{
|
||||
if (received.All(e => e.RoomID.Value != r.RoomID.Value))
|
||||
rooms.Remove(r);
|
||||
}
|
||||
foreach (var pi in room.Playlist)
|
||||
pi.MapObjects(beatmaps, rulesets);
|
||||
|
||||
for (int i = 0; i < received.Count; i++)
|
||||
var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value);
|
||||
if (existing == null)
|
||||
rooms.Add(room);
|
||||
else
|
||||
existing.CopyFrom(room);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var room = received[i];
|
||||
Logger.Error(ex, $"Failed to update room: {room.Name.Value}.");
|
||||
|
||||
Debug.Assert(room.RoomID.Value != null);
|
||||
|
||||
if (ignoredRooms.Contains(room.RoomID.Value.Value))
|
||||
continue;
|
||||
|
||||
room.Position.Value = i;
|
||||
|
||||
try
|
||||
{
|
||||
update(room, room);
|
||||
addRoom(room);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(ex, $"Failed to update room: {room.Name.Value}.");
|
||||
|
||||
ignoredRooms.Add(room.RoomID.Value.Value);
|
||||
rooms.Remove(room);
|
||||
}
|
||||
ignoredRooms.Add(room.RoomID.Value.Value);
|
||||
rooms.Remove(room);
|
||||
}
|
||||
|
||||
RoomsUpdated?.Invoke();
|
||||
initialRoomsReceived.Value = true;
|
||||
notifyRoomsUpdated();
|
||||
}
|
||||
|
||||
protected void RemoveRoom(Room room) => rooms.Remove(room);
|
||||
public void RemoveRoom(Room room)
|
||||
{
|
||||
rooms.Remove(room);
|
||||
notifyRoomsUpdated();
|
||||
}
|
||||
|
||||
protected void ClearRooms()
|
||||
public void ClearRooms()
|
||||
{
|
||||
rooms.Clear();
|
||||
initialRoomsReceived.Value = false;
|
||||
notifyRoomsUpdated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a local <see cref="Room"/> with a remote copy.
|
||||
/// </summary>
|
||||
/// <param name="local">The local <see cref="Room"/> to update.</param>
|
||||
/// <param name="remote">The remote <see cref="Room"/> to update with.</param>
|
||||
private void update(Room local, Room remote)
|
||||
{
|
||||
foreach (var pi in remote.Playlist)
|
||||
pi.MapObjects(beatmaps, rulesets);
|
||||
|
||||
local.CopyFrom(remote);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="Room"/> to the list of available rooms.
|
||||
/// </summary>
|
||||
/// <param name="room">The <see cref="Room"/> to add.</param>
|
||||
private void addRoom(Room room)
|
||||
{
|
||||
var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value);
|
||||
if (existing == null)
|
||||
rooms.Add(room);
|
||||
else
|
||||
existing.CopyFrom(room);
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<RoomPollingComponent> CreatePollingComponents();
|
||||
private void notifyRoomsUpdated() => Scheduler.AddOnce(() => RoomsUpdated?.Invoke());
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,18 @@
|
||||
// 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.Game.Online;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Components
|
||||
{
|
||||
public abstract class RoomPollingComponent : PollingComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoked when any <see cref="Room"/>s have been received from the API.
|
||||
/// <para>
|
||||
/// Any <see cref="Room"/>s present locally but not returned by this event are to be removed from display.
|
||||
/// If null, the display of local rooms is reset to an initial state.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public Action<List<Room>> RoomsReceived;
|
||||
|
||||
[Resolved]
|
||||
protected IAPIProvider API { get; private set; }
|
||||
|
||||
protected void NotifyRoomsReceived(List<Room> rooms) => RoomsReceived?.Invoke(rooms);
|
||||
[Resolved]
|
||||
protected IRoomManager RoomManager { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// 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 System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
@ -48,17 +46,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
|
||||
pollReq.Success += result =>
|
||||
{
|
||||
// existing rooms need to be ordered by their position because the received of NotifyRoomsReceives expects to be able to sort them based on this order.
|
||||
var rooms = new List<Room>(roomManager.Rooms.OrderBy(r => r.Position.Value));
|
||||
|
||||
int index = rooms.FindIndex(r => r.RoomID.Value == result.RoomID.Value);
|
||||
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
rooms[index] = result;
|
||||
|
||||
NotifyRoomsReceived(rooms);
|
||||
RoomManager.AddOrUpdateRoom(result);
|
||||
tcs.SetResult(true);
|
||||
};
|
||||
|
||||
|
@ -18,16 +18,29 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
/// </summary>
|
||||
event Action RoomsUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Whether an initial listing of rooms has been received.
|
||||
/// </summary>
|
||||
IBindable<bool> InitialRoomsReceived { get; }
|
||||
|
||||
/// <summary>
|
||||
/// All the active <see cref="Room"/>s.
|
||||
/// </summary>
|
||||
IBindableList<Room> Rooms { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="Room"/> to this <see cref="IRoomManager"/>.
|
||||
/// If already existing, the local room will be updated with the given one.
|
||||
/// </summary>
|
||||
/// <param name="room">The incoming <see cref="Room"/>.</param>
|
||||
void AddOrUpdateRoom(Room room);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a <see cref="Room"/> from this <see cref="IRoomManager"/>.
|
||||
/// </summary>
|
||||
/// <param name="room">The <see cref="Room"/> to remove.</param>
|
||||
void RemoveRoom(Room room);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all <see cref="Room"/>s from this <see cref="IRoomManager"/>.
|
||||
/// </summary>
|
||||
void ClearRooms();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Room"/>.
|
||||
/// </summary>
|
||||
|
@ -30,8 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
|
||||
public IReadOnlyList<DrawableRoom> Rooms => roomFlow.FlowingChildren.Cast<DrawableRoom>().ToArray();
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private Bindable<FilterCriteria> filter { get; set; }
|
||||
public readonly Bindable<FilterCriteria> Filter = new Bindable<FilterCriteria>();
|
||||
|
||||
[Resolved]
|
||||
private Bindable<Room> selectedRoom { get; set; }
|
||||
@ -74,7 +73,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
|
||||
rooms.BindTo(roomManager.Rooms);
|
||||
|
||||
filter?.BindValueChanged(criteria => Filter(criteria.NewValue));
|
||||
Filter?.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true);
|
||||
|
||||
selectedRoom.BindValueChanged(selection =>
|
||||
{
|
||||
@ -85,7 +84,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
private void updateSelection() =>
|
||||
roomFlow.Children.ForEach(r => r.State = r.Room == selectedRoom.Value ? SelectionState.Selected : SelectionState.NotSelected);
|
||||
|
||||
public void Filter(FilterCriteria criteria)
|
||||
private void applyFilterCriteria(FilterCriteria criteria)
|
||||
{
|
||||
roomFlow.Children.ForEach(r =>
|
||||
{
|
||||
@ -126,7 +125,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
roomFlow.Add(new DrawableRoom(room));
|
||||
}
|
||||
|
||||
Filter(filter?.Value);
|
||||
applyFilterCriteria(Filter?.Value);
|
||||
|
||||
updateSelection();
|
||||
}
|
||||
|
@ -13,14 +13,17 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
using osu.Game.Users;
|
||||
@ -42,10 +45,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
AutoSizeAxes = Axes.Both
|
||||
};
|
||||
|
||||
private readonly IBindable<bool> initialRoomsReceived = new Bindable<bool>();
|
||||
private readonly IBindable<bool> operationInProgress = new Bindable<bool>();
|
||||
|
||||
private LoadingLayer loadingLayer;
|
||||
protected ListingPollingComponent ListingPollingComponent { get; private set; }
|
||||
|
||||
[Resolved]
|
||||
private Bindable<Room> selectedRoom { get; set; }
|
||||
@ -56,31 +56,34 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OngoingOperationTracker ongoingOperationTracker { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private Bindable<FilterCriteria> filter { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; }
|
||||
|
||||
[CanBeNull]
|
||||
private IDisposable joiningRoomOperation { get; set; }
|
||||
|
||||
[CanBeNull]
|
||||
private LeasedBindable<Room> selectionLease;
|
||||
|
||||
private readonly Bindable<FilterCriteria> filter = new Bindable<FilterCriteria>(new FilterCriteria());
|
||||
private readonly IBindable<bool> operationInProgress = new Bindable<bool>();
|
||||
private readonly IBindable<bool> isIdle = new BindableBool();
|
||||
private LoadingLayer loadingLayer;
|
||||
private RoomsContainer roomsContainer;
|
||||
private SearchTextBox searchTextBox;
|
||||
private Dropdown<RoomStatusFilter> statusDropdown;
|
||||
|
||||
[CanBeNull]
|
||||
private LeasedBindable<Room> selectionLease;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load([CanBeNull] IdleTracker idleTracker)
|
||||
{
|
||||
filter ??= new Bindable<FilterCriteria>(new FilterCriteria());
|
||||
if (idleTracker != null)
|
||||
isIdle.BindTo(idleTracker.IsIdle);
|
||||
|
||||
OsuScrollContainer scrollContainer;
|
||||
|
||||
InternalChildren = new[]
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
ListingPollingComponent = CreatePollingComponent().With(c => c.Filter.BindTarget = filter),
|
||||
loadingLayer = new LoadingLayer(true),
|
||||
new Container
|
||||
{
|
||||
@ -154,7 +157,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ScrollbarOverlapsContent = false,
|
||||
Child = roomsContainer = new RoomsContainer()
|
||||
Child = roomsContainer = new RoomsContainer
|
||||
{
|
||||
Filter = { BindTarget = filter }
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -180,21 +186,22 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced());
|
||||
ruleset.BindValueChanged(_ => UpdateFilter());
|
||||
|
||||
initialRoomsReceived.BindTo(RoomManager.InitialRoomsReceived);
|
||||
initialRoomsReceived.BindValueChanged(_ => updateLoadingLayer());
|
||||
isIdle.BindValueChanged(_ => updatePollingRate(this.IsCurrentScreen()), true);
|
||||
|
||||
if (ongoingOperationTracker != null)
|
||||
{
|
||||
operationInProgress.BindTo(ongoingOperationTracker.InProgress);
|
||||
operationInProgress.BindValueChanged(_ => updateLoadingLayer(), true);
|
||||
operationInProgress.BindValueChanged(_ => updateLoadingLayer());
|
||||
}
|
||||
|
||||
ListingPollingComponent.InitialRoomsReceived.BindValueChanged(_ => updateLoadingLayer(), true);
|
||||
|
||||
updateFilter();
|
||||
}
|
||||
|
||||
#region Filtering
|
||||
|
||||
protected void UpdateFilter() => Scheduler.AddOnce(updateFilter);
|
||||
public void UpdateFilter() => Scheduler.AddOnce(updateFilter);
|
||||
|
||||
private ScheduledDelegate scheduledFilterUpdate;
|
||||
|
||||
@ -235,7 +242,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
public override void OnEntering(IScreen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
|
||||
onReturning();
|
||||
}
|
||||
|
||||
@ -275,11 +281,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
|
||||
private void onReturning()
|
||||
{
|
||||
updatePollingRate(true);
|
||||
searchTextBox.HoldFocus = true;
|
||||
}
|
||||
|
||||
private void onLeaving()
|
||||
{
|
||||
updatePollingRate(false);
|
||||
searchTextBox.HoldFocus = false;
|
||||
|
||||
// ensure any password prompt is dismissed.
|
||||
@ -327,6 +335,24 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
this.Push(CreateRoomSubScreen(room));
|
||||
}
|
||||
|
||||
private void updateLoadingLayer()
|
||||
{
|
||||
if (operationInProgress.Value || !ListingPollingComponent.InitialRoomsReceived.Value)
|
||||
loadingLayer.Show();
|
||||
else
|
||||
loadingLayer.Hide();
|
||||
}
|
||||
|
||||
private void updatePollingRate(bool isCurrentScreen)
|
||||
{
|
||||
if (!isCurrentScreen)
|
||||
ListingPollingComponent.TimeBetweenPolls.Value = 0;
|
||||
else
|
||||
ListingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000;
|
||||
|
||||
Logger.Log($"Polling adjusted (listing: {ListingPollingComponent.TimeBetweenPolls.Value})");
|
||||
}
|
||||
|
||||
protected abstract OsuButton CreateNewRoomButton();
|
||||
|
||||
/// <summary>
|
||||
@ -337,13 +363,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
|
||||
|
||||
protected abstract RoomSubScreen CreateRoomSubScreen(Room room);
|
||||
|
||||
private void updateLoadingLayer()
|
||||
{
|
||||
if (operationInProgress.Value || !initialRoomsReceived.Value)
|
||||
loadingLayer.Show();
|
||||
else
|
||||
loadingLayer.Hide();
|
||||
}
|
||||
protected abstract ListingPollingComponent CreatePollingComponent();
|
||||
|
||||
private class LoungeSearchTextBox : SearchTextBox
|
||||
{
|
||||
|
@ -41,11 +41,13 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
base.PopIn();
|
||||
Settings.MoveToY(0, TRANSITION_DURATION, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
@ -23,35 +22,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
client.ChangeState(MultiplayerUserState.Idle);
|
||||
}
|
||||
|
||||
protected override void UpdatePollingRate(bool isIdle)
|
||||
{
|
||||
var multiplayerRoomManager = (MultiplayerRoomManager)RoomManager;
|
||||
|
||||
if (!this.IsCurrentScreen())
|
||||
{
|
||||
multiplayerRoomManager.TimeBetweenListingPolls.Value = 0;
|
||||
multiplayerRoomManager.TimeBetweenSelectionPolls.Value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (CurrentSubScreen)
|
||||
{
|
||||
case LoungeSubScreen _:
|
||||
multiplayerRoomManager.TimeBetweenListingPolls.Value = isIdle ? 120000 : 15000;
|
||||
multiplayerRoomManager.TimeBetweenSelectionPolls.Value = isIdle ? 120000 : 15000;
|
||||
break;
|
||||
|
||||
// Don't poll inside the match or anywhere else.
|
||||
default:
|
||||
multiplayerRoomManager.TimeBetweenListingPolls.Value = 0;
|
||||
multiplayerRoomManager.TimeBetweenSelectionPolls.Value = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Log($"Polling adjusted (listing: {multiplayerRoomManager.TimeBetweenListingPolls.Value}, selection: {multiplayerRoomManager.TimeBetweenSelectionPolls.Value})");
|
||||
}
|
||||
|
||||
protected override string ScreenTitle => "Multiplayer";
|
||||
|
||||
protected override RoomManager CreateRoomManager() => new MultiplayerRoomManager();
|
||||
|
@ -1,12 +1,16 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
@ -21,6 +25,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; }
|
||||
|
||||
public override void OnResuming(IScreen last)
|
||||
{
|
||||
base.OnResuming(last);
|
||||
|
||||
// Upon having left a room, we don't know whether we were the only participant, and whether the room is now closed as a result of leaving it.
|
||||
// To work around this, temporarily remove the room and trigger an immediate listing poll.
|
||||
if (last is MultiplayerMatchSubScreen match)
|
||||
{
|
||||
RoomManager.RemoveRoom(match.Room);
|
||||
ListingPollingComponent.PollImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
protected override FilterCriteria CreateFilterCriteria()
|
||||
{
|
||||
var criteria = base.CreateFilterCriteria();
|
||||
@ -39,6 +56,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room);
|
||||
|
||||
protected override ListingPollingComponent CreatePollingComponent() => new MultiplayerListingPollingComponent();
|
||||
|
||||
protected override void OpenNewRoom(Room room)
|
||||
{
|
||||
if (client?.IsConnected.Value != true)
|
||||
@ -49,5 +68,32 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
base.OpenNewRoom(room);
|
||||
}
|
||||
|
||||
private class MultiplayerListingPollingComponent : ListingPollingComponent
|
||||
{
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; }
|
||||
|
||||
private readonly IBindable<bool> isConnected = new Bindable<bool>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
isConnected.BindTo(client.IsConnected);
|
||||
isConnected.BindValueChanged(c => Scheduler.AddOnce(() =>
|
||||
{
|
||||
if (isConnected.Value && IsLoaded)
|
||||
PollImmediately();
|
||||
}), true);
|
||||
}
|
||||
|
||||
protected override Task Poll()
|
||||
{
|
||||
if (!isConnected.Value)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return base.Poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
public override string ShortTitle => "room";
|
||||
|
||||
public readonly Room Room;
|
||||
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; }
|
||||
|
||||
@ -49,9 +51,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
private OngoingOperationTracker ongoingOperationTracker { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private Bindable<Room> currentRoom { get; set; }
|
||||
|
||||
private MultiplayerMatchSettingsOverlay settingsOverlay;
|
||||
private Bindable<Room> currentRoom { get; set; } // Todo: This should not exist.
|
||||
|
||||
private readonly IBindable<bool> isConnected = new Bindable<bool>();
|
||||
|
||||
@ -59,9 +59,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
private IDisposable readyClickOperation;
|
||||
|
||||
private GridContainer mainContent;
|
||||
private MultiplayerMatchSettingsOverlay settingsOverlay;
|
||||
|
||||
public MultiplayerMatchSubScreen(Room room)
|
||||
{
|
||||
Room = room;
|
||||
|
||||
Title = room.RoomID.Value == null ? "New room" : room.Name.Value;
|
||||
Activity.Value = new UserActivity.InLobby(room);
|
||||
}
|
||||
|
@ -2,11 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ExceptionExtensions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
@ -21,22 +18,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
[Resolved]
|
||||
private MultiplayerClient multiplayerClient { get; set; }
|
||||
|
||||
public readonly Bindable<double> TimeBetweenListingPolls = new Bindable<double>();
|
||||
public readonly Bindable<double> TimeBetweenSelectionPolls = new Bindable<double>();
|
||||
private readonly IBindable<bool> isConnected = new Bindable<bool>();
|
||||
private readonly Bindable<bool> allowPolling = new Bindable<bool>();
|
||||
|
||||
private ListingPollingComponent listingPollingComponent;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
isConnected.BindTo(multiplayerClient.IsConnected);
|
||||
isConnected.BindValueChanged(_ => Scheduler.AddOnce(updatePolling));
|
||||
JoinedRoom.BindValueChanged(_ => Scheduler.AddOnce(updatePolling), true);
|
||||
}
|
||||
|
||||
public override void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
=> base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), onError);
|
||||
|
||||
@ -64,19 +45,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
if (JoinedRoom.Value == null)
|
||||
return;
|
||||
|
||||
var joinedRoom = JoinedRoom.Value;
|
||||
|
||||
base.PartRoom();
|
||||
|
||||
multiplayerClient.LeaveRoom();
|
||||
|
||||
// Todo: This is not the way to do this. Basically when we're the only participant and the room closes, there's no way to know if this is actually the case.
|
||||
// This is delayed one frame because upon exiting the match subscreen, multiplayer updates the polling rate and messes with polling.
|
||||
Schedule(() =>
|
||||
{
|
||||
RemoveRoom(joinedRoom);
|
||||
listingPollingComponent.PollImmediately();
|
||||
});
|
||||
}
|
||||
|
||||
private void joinMultiplayerRoom(Room room, string password, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
@ -99,70 +69,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updatePolling()
|
||||
{
|
||||
if (!isConnected.Value)
|
||||
ClearRooms();
|
||||
|
||||
// Don't poll when not connected or when a room has been joined.
|
||||
allowPolling.Value = isConnected.Value && JoinedRoom.Value == null;
|
||||
}
|
||||
|
||||
protected override IEnumerable<RoomPollingComponent> CreatePollingComponents() => new RoomPollingComponent[]
|
||||
{
|
||||
listingPollingComponent = new MultiplayerListingPollingComponent
|
||||
{
|
||||
TimeBetweenPolls = { BindTarget = TimeBetweenListingPolls },
|
||||
AllowPolling = { BindTarget = allowPolling }
|
||||
},
|
||||
new MultiplayerSelectionPollingComponent
|
||||
{
|
||||
TimeBetweenPolls = { BindTarget = TimeBetweenSelectionPolls },
|
||||
AllowPolling = { BindTarget = allowPolling }
|
||||
}
|
||||
};
|
||||
|
||||
private class MultiplayerListingPollingComponent : ListingPollingComponent
|
||||
{
|
||||
public readonly IBindable<bool> AllowPolling = new Bindable<bool>();
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
AllowPolling.BindValueChanged(allowPolling =>
|
||||
{
|
||||
if (!allowPolling.NewValue)
|
||||
return;
|
||||
|
||||
if (IsLoaded)
|
||||
PollImmediately();
|
||||
});
|
||||
}
|
||||
|
||||
protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll();
|
||||
}
|
||||
|
||||
private class MultiplayerSelectionPollingComponent : SelectionPollingComponent
|
||||
{
|
||||
public readonly IBindable<bool> AllowPolling = new Bindable<bool>();
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
AllowPolling.BindValueChanged(allowPolling =>
|
||||
{
|
||||
if (!allowPolling.NewValue)
|
||||
return;
|
||||
|
||||
if (IsLoaded)
|
||||
PollImmediately();
|
||||
});
|
||||
}
|
||||
|
||||
protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
/// <param name="score">The score containing the player's replay.</param>
|
||||
/// <param name="spectatorPlayerClock">The clock controlling the gameplay running state.</param>
|
||||
public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock)
|
||||
: base(score)
|
||||
: base(score, new PlayerConfiguration { AllowUserInteraction = false })
|
||||
{
|
||||
this.spectatorPlayerClock = spectatorPlayerClock;
|
||||
}
|
||||
@ -34,6 +34,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
private void load()
|
||||
{
|
||||
spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames);
|
||||
|
||||
HUDOverlay.PlayerSettingsOverlay.Expire();
|
||||
HUDOverlay.HoldToQuit.Expire();
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
@ -19,6 +20,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
PlayerSettings.Expire();
|
||||
}
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
{
|
||||
}
|
||||
|
@ -14,14 +14,12 @@ using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge.Components;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -44,17 +42,12 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
private LoungeSubScreen loungeSubScreen;
|
||||
private ScreenStack screenStack;
|
||||
|
||||
private readonly IBindable<bool> isIdle = new BindableBool();
|
||||
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
protected RoomManager RoomManager { get; private set; }
|
||||
|
||||
[Cached]
|
||||
private readonly Bindable<Room> selectedRoom = new Bindable<Room>();
|
||||
|
||||
[Cached]
|
||||
private readonly Bindable<FilterCriteria> currentFilter = new Bindable<FilterCriteria>(new FilterCriteria());
|
||||
|
||||
[Cached]
|
||||
private readonly OngoingOperationTracker ongoingOperationTracker = new OngoingOperationTracker();
|
||||
|
||||
@ -67,9 +60,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
[Resolved]
|
||||
protected IAPIProvider API { get; private set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IdleTracker idleTracker { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuLogo logo { get; set; }
|
||||
|
||||
@ -147,12 +137,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
apiState.BindTo(API.State);
|
||||
apiState.BindValueChanged(onlineStateChanged, true);
|
||||
|
||||
if (idleTracker != null)
|
||||
{
|
||||
isIdle.BindTo(idleTracker.IsIdle);
|
||||
isIdle.BindValueChanged(idle => UpdatePollingRate(idle.NewValue), true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
@ -162,8 +146,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
protected abstract void UpdatePollingRate(bool isIdle);
|
||||
|
||||
private void forcefullyExit()
|
||||
{
|
||||
// This is temporary since we don't currently have a way to force screens to be exited
|
||||
@ -199,8 +181,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
screenStack.CurrentScreen.OnResuming(last);
|
||||
|
||||
base.OnResuming(last);
|
||||
|
||||
UpdatePollingRate(isIdle.Value);
|
||||
}
|
||||
|
||||
public override void OnSuspending(IScreen next)
|
||||
@ -210,8 +190,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
Debug.Assert(screenStack.CurrentScreen != null);
|
||||
screenStack.CurrentScreen.OnSuspending(next);
|
||||
|
||||
UpdatePollingRate(isIdle.Value);
|
||||
}
|
||||
|
||||
public override bool OnExiting(IScreen next)
|
||||
@ -275,15 +253,13 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
if (newScreen is IOsuScreen newOsuScreen)
|
||||
((IBindable<UserActivity>)Activity).BindTo(newOsuScreen.Activity);
|
||||
|
||||
UpdatePollingRate(isIdle.Value);
|
||||
}
|
||||
|
||||
protected IScreen CurrentSubScreen => screenStack.CurrentScreen;
|
||||
|
||||
protected abstract string ScreenTitle { get; }
|
||||
|
||||
protected abstract RoomManager CreateRoomManager();
|
||||
protected virtual RoomManager CreateRoomManager() => new RoomManager();
|
||||
|
||||
protected abstract LoungeSubScreen CreateLounge();
|
||||
|
||||
|
@ -1,53 +1,14 @@
|
||||
// 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.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
{
|
||||
public class Playlists : OnlinePlayScreen
|
||||
{
|
||||
protected override void UpdatePollingRate(bool isIdle)
|
||||
{
|
||||
var playlistsManager = (PlaylistsRoomManager)RoomManager;
|
||||
|
||||
if (!this.IsCurrentScreen())
|
||||
{
|
||||
playlistsManager.TimeBetweenListingPolls.Value = 0;
|
||||
playlistsManager.TimeBetweenSelectionPolls.Value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (CurrentSubScreen)
|
||||
{
|
||||
case LoungeSubScreen _:
|
||||
playlistsManager.TimeBetweenListingPolls.Value = isIdle ? 120000 : 15000;
|
||||
playlistsManager.TimeBetweenSelectionPolls.Value = isIdle ? 120000 : 15000;
|
||||
break;
|
||||
|
||||
case RoomSubScreen _:
|
||||
playlistsManager.TimeBetweenListingPolls.Value = 0;
|
||||
playlistsManager.TimeBetweenSelectionPolls.Value = isIdle ? 30000 : 5000;
|
||||
break;
|
||||
|
||||
default:
|
||||
playlistsManager.TimeBetweenListingPolls.Value = 0;
|
||||
playlistsManager.TimeBetweenSelectionPolls.Value = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Log($"Polling adjusted (listing: {playlistsManager.TimeBetweenListingPolls.Value}, selection: {playlistsManager.TimeBetweenSelectionPolls.Value})");
|
||||
}
|
||||
|
||||
protected override string ScreenTitle => "Playlists";
|
||||
|
||||
protected override RoomManager CreateRoomManager() => new PlaylistsRoomManager();
|
||||
|
||||
protected override LoungeSubScreen CreateLounge() => new PlaylistsLoungeSubScreen();
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
@ -66,6 +67,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
|
||||
protected override RoomSubScreen CreateRoomSubScreen(Room room) => new PlaylistsRoomSubScreen(room);
|
||||
|
||||
protected override ListingPollingComponent CreatePollingComponent() => new ListingPollingComponent();
|
||||
|
||||
private enum PlaylistsCategory
|
||||
{
|
||||
Any,
|
||||
|
@ -1,21 +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 System.Collections.Generic;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
{
|
||||
public class PlaylistsRoomManager : RoomManager
|
||||
{
|
||||
public readonly Bindable<double> TimeBetweenListingPolls = new Bindable<double>();
|
||||
public readonly Bindable<double> TimeBetweenSelectionPolls = new Bindable<double>();
|
||||
|
||||
protected override IEnumerable<RoomPollingComponent> CreatePollingComponents() => new RoomPollingComponent[]
|
||||
{
|
||||
new ListingPollingComponent { TimeBetweenPolls = { BindTarget = TimeBetweenListingPolls } },
|
||||
new SelectionPollingComponent { TimeBetweenPolls = { BindTarget = TimeBetweenSelectionPolls } }
|
||||
};
|
||||
}
|
||||
}
|
@ -3,11 +3,14 @@
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
@ -33,12 +36,13 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
[Resolved(typeof(Room), nameof(Room.Playlist))]
|
||||
private BindableList<PlaylistItem> playlist { get; set; }
|
||||
|
||||
private readonly IBindable<bool> isIdle = new BindableBool();
|
||||
|
||||
private MatchSettingsOverlay settingsOverlay;
|
||||
private MatchLeaderboard leaderboard;
|
||||
|
||||
private OverlinedHeader participantsHeader;
|
||||
|
||||
private GridContainer mainContent;
|
||||
private SelectionPollingComponent selectionPollingComponent;
|
||||
|
||||
public PlaylistsRoomSubScreen(Room room)
|
||||
{
|
||||
@ -46,11 +50,15 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
Activity.Value = new UserActivity.InLobby(room);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load([CanBeNull] IdleTracker idleTracker)
|
||||
{
|
||||
if (idleTracker != null)
|
||||
isIdle.BindTo(idleTracker.IsIdle);
|
||||
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
selectionPollingComponent = new SelectionPollingComponent(),
|
||||
mainContent = new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -260,6 +268,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
isIdle.BindValueChanged(_ => updatePollingRate(), true);
|
||||
|
||||
roomId.BindValueChanged(id =>
|
||||
{
|
||||
if (id.NewValue == null)
|
||||
@ -275,6 +285,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void updatePollingRate()
|
||||
{
|
||||
selectionPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 30000 : 5000;
|
||||
Logger.Log($"Polling adjusted (selection: {selectionPollingComponent.TimeBetweenPolls.Value})");
|
||||
}
|
||||
|
||||
protected override Screen CreateGameplayScreen() => new PlayerLoader(() => new PlaylistsPlayer(SelectedItem.Value)
|
||||
{
|
||||
Exited = () => leaderboard.RefreshScores()
|
||||
|
17
osu.Game/Screens/Play/ILocalUserPlayInfo.cs
Normal file
17
osu.Game/Screens/Play/ILocalUserPlayInfo.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 osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
[Cached]
|
||||
public interface ILocalUserPlayInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the local user is currently playing.
|
||||
/// </summary>
|
||||
IBindable<bool> IsPlaying { get; }
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play
|
||||
{
|
||||
[Cached]
|
||||
[Cached(typeof(ISamplePlaybackDisabler))]
|
||||
public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler
|
||||
public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler, ILocalUserPlayInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The delay upon completion of the beatmap before displaying the results screen.
|
||||
@ -1052,5 +1052,7 @@ namespace osu.Game.Screens.Play
|
||||
#endregion
|
||||
|
||||
IBindable<bool> ISamplePlaybackDisabler.SamplePlaybackDisabled => samplePlaybackDisabled;
|
||||
|
||||
IBindable<bool> ILocalUserPlayInfo.IsPlaying => LocalUserPlaying;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,11 @@ namespace osu.Game.Screens.Play
|
||||
/// </summary>
|
||||
public bool AllowRestart { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the player should be able to interact with this player instance.
|
||||
/// </summary>
|
||||
public bool AllowUserInteraction { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard.
|
||||
/// </summary>
|
||||
|
@ -46,9 +46,14 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
protected override bool PlayResumeSound => false;
|
||||
|
||||
protected BeatmapMetadataDisplay MetadataInfo;
|
||||
protected BeatmapMetadataDisplay MetadataInfo { get; private set; }
|
||||
|
||||
protected VisualSettings VisualSettings;
|
||||
/// <summary>
|
||||
/// A fill flow containing the player settings groups, exposed for the ability to hide it from inheritors of the player loader.
|
||||
/// </summary>
|
||||
protected FillFlowContainer<PlayerSettingsGroup> PlayerSettings { get; private set; }
|
||||
|
||||
protected VisualSettings VisualSettings { get; private set; }
|
||||
|
||||
protected Task LoadTask { get; private set; }
|
||||
|
||||
@ -140,7 +145,7 @@ namespace osu.Game.Screens.Play
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
new FillFlowContainer<PlayerSettingsGroup>
|
||||
PlayerSettings = new FillFlowContainer<PlayerSettingsGroup>
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
|
@ -119,7 +119,8 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
if (drawableRuleset != null)
|
||||
{
|
||||
AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded);
|
||||
if (player?.Configuration.AllowUserInteraction == true)
|
||||
((IBindable<bool>)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded);
|
||||
|
||||
referenceClock = drawableRuleset.FrameStableClock;
|
||||
Objects = drawableRuleset.Objects;
|
||||
|
@ -23,7 +23,8 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap
|
||||
|
||||
public SpectatorPlayer(Score score)
|
||||
public SpectatorPlayer(Score score, PlayerConfiguration configuration = null)
|
||||
: base(configuration)
|
||||
{
|
||||
this.score = score;
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
protected override Task<MultiplayerRoom> JoinRoom(long roomId, string? password = null)
|
||||
{
|
||||
var apiRoom = roomManager.Rooms.Single(r => r.RoomID.Value == roomId);
|
||||
var apiRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == roomId);
|
||||
|
||||
if (password != apiRoom.Password.Value)
|
||||
throw new InvalidOperationException("Invalid password.");
|
||||
@ -260,7 +260,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
Debug.Assert(Room != null);
|
||||
|
||||
var apiRoom = roomManager.Rooms.Single(r => r.RoomID.Value == Room.RoomID);
|
||||
var apiRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == Room.RoomID);
|
||||
var set = apiRoom.Playlist.FirstOrDefault(p => p.BeatmapID == beatmapId)?.Beatmap.Value.BeatmapSet
|
||||
?? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId)?.BeatmapSet;
|
||||
|
||||
|
@ -5,14 +5,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
@ -32,10 +30,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Resolved]
|
||||
private OsuGameBase game { get; set; }
|
||||
|
||||
[Cached]
|
||||
public readonly Bindable<FilterCriteria> Filter = new Bindable<FilterCriteria>(new FilterCriteria());
|
||||
|
||||
public new readonly List<Room> Rooms = new List<Room>();
|
||||
public IReadOnlyList<Room> ServerSideRooms => serverSideRooms;
|
||||
private readonly List<Room> serverSideRooms = new List<Room>();
|
||||
|
||||
private int currentRoomId;
|
||||
private int currentPlaylistItemId;
|
||||
@ -60,7 +56,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
apiRoom.HasPassword.Value = !string.IsNullOrEmpty(createRoomRequest.Room.Password.Value);
|
||||
apiRoom.Password.Value = createRoomRequest.Room.Password.Value;
|
||||
|
||||
AddRoom(apiRoom);
|
||||
AddServerSideRoom(apiRoom);
|
||||
|
||||
var responseRoom = new APICreatedRoom();
|
||||
responseRoom.CopyFrom(createResponseRoom(apiRoom, false));
|
||||
@ -70,7 +66,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
case JoinRoomRequest joinRoomRequest:
|
||||
{
|
||||
var room = Rooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value);
|
||||
var room = ServerSideRooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value);
|
||||
|
||||
if (joinRoomRequest.Password != room.Password.Value)
|
||||
{
|
||||
@ -89,14 +85,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
case GetRoomsRequest getRoomsRequest:
|
||||
var roomsWithoutParticipants = new List<Room>();
|
||||
|
||||
foreach (var r in Rooms)
|
||||
foreach (var r in ServerSideRooms)
|
||||
roomsWithoutParticipants.Add(createResponseRoom(r, false));
|
||||
|
||||
getRoomsRequest.TriggerSuccess(roomsWithoutParticipants);
|
||||
return true;
|
||||
|
||||
case GetRoomRequest getRoomRequest:
|
||||
getRoomRequest.TriggerSuccess(createResponseRoom(Rooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true));
|
||||
getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true));
|
||||
return true;
|
||||
|
||||
case GetBeatmapSetRequest getBeatmapSetRequest:
|
||||
@ -132,17 +128,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
};
|
||||
}
|
||||
|
||||
public void AddRoom(Room room)
|
||||
public void AddServerSideRoom(Room room)
|
||||
{
|
||||
room.RoomID.Value ??= currentRoomId++;
|
||||
for (int i = 0; i < room.Playlist.Count; i++)
|
||||
room.Playlist[i].ID = currentPlaylistItemId++;
|
||||
|
||||
Rooms.Add(room);
|
||||
serverSideRooms.Add(room);
|
||||
}
|
||||
|
||||
public new void RemoveRoom(Room room) => base.RemoveRoom(room);
|
||||
|
||||
private Room createResponseRoom(Room room, bool withParticipants)
|
||||
{
|
||||
var responseRoom = new Room();
|
||||
@ -152,9 +146,5 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
responseRoom.RecentParticipants.Clear();
|
||||
return responseRoom;
|
||||
}
|
||||
|
||||
public new void ClearRooms() => base.ClearRooms();
|
||||
|
||||
public new void Schedule(Action action) => base.Schedule(action);
|
||||
}
|
||||
}
|
||||
|
@ -28,17 +28,25 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
|
||||
IBindableList<Room> IRoomManager.Rooms => Rooms;
|
||||
|
||||
private int currentRoomId;
|
||||
|
||||
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
{
|
||||
room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1;
|
||||
onSuccess?.Invoke(room);
|
||||
|
||||
AddRoom(room);
|
||||
AddOrUpdateRoom(room);
|
||||
}
|
||||
|
||||
public void AddRoom(Room room)
|
||||
public void AddOrUpdateRoom(Room room)
|
||||
{
|
||||
Rooms.Add(room);
|
||||
var existing = Rooms.FirstOrDefault(r => r.RoomID.Value != null && r.RoomID.Value == room.RoomID.Value);
|
||||
|
||||
if (existing != null)
|
||||
existing.CopyFrom(room);
|
||||
else
|
||||
Rooms.Add(room);
|
||||
|
||||
RoomsUpdated?.Invoke();
|
||||
}
|
||||
|
||||
@ -48,6 +56,12 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
RoomsUpdated?.Invoke();
|
||||
}
|
||||
|
||||
public void ClearRooms()
|
||||
{
|
||||
Rooms.Clear();
|
||||
RoomsUpdated?.Invoke();
|
||||
}
|
||||
|
||||
public void JoinRoom(Room room, string password, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
{
|
||||
JoinRoomRequested?.Invoke(room, password);
|
||||
@ -64,9 +78,9 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
{
|
||||
var room = new Room
|
||||
{
|
||||
RoomID = { Value = i },
|
||||
Position = { Value = i },
|
||||
Name = { Value = $"Room {i}" },
|
||||
RoomID = { Value = currentRoomId },
|
||||
Position = { Value = currentRoomId },
|
||||
Name = { Value = $"Room {currentRoomId}" },
|
||||
Host = { Value = new User { Username = "Host" } },
|
||||
EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) },
|
||||
Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal },
|
||||
@ -89,6 +103,8 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
}
|
||||
|
||||
CreateRoom(room);
|
||||
|
||||
currentRoomId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user