mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 02:42:54 +08:00
Merge branch 'master' into mod-barrel-roll
This commit is contained in:
commit
3374895e40
@ -52,6 +52,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.412.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.412.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.413.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.415.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -7,6 +7,8 @@ using Android.OS;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game;
|
using osu.Game;
|
||||||
using osu.Game.Updater;
|
using osu.Game.Updater;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
using Xamarin.Essentials;
|
||||||
|
|
||||||
namespace osu.Android
|
namespace osu.Android
|
||||||
{
|
{
|
||||||
@ -72,5 +74,14 @@ namespace osu.Android
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
||||||
|
|
||||||
|
protected override BatteryInfo CreateBatteryInfo() => new AndroidBatteryInfo();
|
||||||
|
|
||||||
|
private class AndroidBatteryInfo : BatteryInfo
|
||||||
|
{
|
||||||
|
public override double ChargeLevel => Battery.ChargeLevel;
|
||||||
|
|
||||||
|
public override bool IsCharging => Battery.PowerSource != BatteryPowerSource.Battery;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
|
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.BATTERY_STATS" />
|
||||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!" android:icon="@drawable/lazer" />
|
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!" android:icon="@drawable/lazer" />
|
||||||
</manifest>
|
</manifest>
|
@ -63,5 +63,8 @@
|
|||||||
<Version>5.0.0</Version>
|
<Version>5.0.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public override string Name => "Mirror";
|
public override string Name => "Mirror";
|
||||||
public override string Acronym => "MR";
|
public override string Acronym => "MR";
|
||||||
public override ModType Type => ModType.Conversion;
|
public override ModType Type => ModType.Conversion;
|
||||||
public override string Description => "Notes are flipped horizontally";
|
public override string Description => "Notes are flipped horizontally.";
|
||||||
public override double ScoreMultiplier => 1;
|
public override double ScoreMultiplier => 1;
|
||||||
public override bool Ranked => true;
|
public override bool Ranked => true;
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
{
|
{
|
||||||
Add(cursorScaleContainer = new Container
|
Add(cursorScaleContainer = new Container
|
||||||
{
|
{
|
||||||
RelativePositionAxes = Axes.Both,
|
|
||||||
Child = clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume }
|
Child = clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,21 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
stack.Push(songSelect = new DummySongSelect());
|
stack.Push(songSelect = new DummySongSelect());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User settings should always be ignored on song select screen.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestUserSettingsIgnoredOnSongSelect()
|
||||||
|
{
|
||||||
|
setupUserSettings();
|
||||||
|
AddUntilStep("Screen is undimmed", () => songSelect.IsBackgroundUndimmed());
|
||||||
|
AddUntilStep("Screen using background blur", () => songSelect.IsBackgroundBlur());
|
||||||
|
performFullSetup();
|
||||||
|
AddStep("Exit to song select", () => player.Exit());
|
||||||
|
AddUntilStep("Screen is undimmed", () => songSelect.IsBackgroundUndimmed());
|
||||||
|
AddUntilStep("Screen using background blur", () => songSelect.IsBackgroundBlur());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if <see cref="PlayerLoader"/> properly triggers the visual settings preview when a user hovers over the visual settings panel.
|
/// Check if <see cref="PlayerLoader"/> properly triggers the visual settings preview when a user hovers over the visual settings panel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -227,17 +242,6 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
songSelect.IsBackgroundUndimmed() && songSelect.IsBackgroundCurrent() && songSelect.CheckBackgroundBlur(results.ExpectedBackgroundBlur));
|
songSelect.IsBackgroundUndimmed() && songSelect.IsBackgroundCurrent() && songSelect.CheckBackgroundBlur(results.ExpectedBackgroundBlur));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check if background gets undimmed and unblurred when leaving <see cref="Player"/> for <see cref="PlaySongSelect"/>
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void TestTransitionOut()
|
|
||||||
{
|
|
||||||
performFullSetup();
|
|
||||||
AddStep("Exit to song select", () => player.Exit());
|
|
||||||
AddUntilStep("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && songSelect.IsBlurCorrect());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if hovering on the visual settings dialogue after resuming from player still previews the background dim.
|
/// Check if hovering on the visual settings dialogue after resuming from player still previews the background dim.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -333,7 +337,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
|
|
||||||
public bool IsBackgroundVisible() => background.CurrentAlpha == 1;
|
public bool IsBackgroundVisible() => background.CurrentAlpha == 1;
|
||||||
|
|
||||||
public bool IsBlurCorrect() => background.CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
public bool IsBackgroundBlur() => background.CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
||||||
|
|
||||||
public bool CheckBackgroundBlur(Vector2 expected) => background.CurrentBlur == expected;
|
public bool CheckBackgroundBlur(Vector2 expected) => background.CurrentBlur == expected;
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -16,12 +15,21 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
public class TestSceneEditorSummaryTimeline : EditorClockTestScene
|
public class TestSceneEditorSummaryTimeline : EditorClockTestScene
|
||||||
{
|
{
|
||||||
[Cached(typeof(EditorBeatmap))]
|
[Cached(typeof(EditorBeatmap))]
|
||||||
private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap());
|
private readonly EditorBeatmap editorBeatmap;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
public TestSceneEditorSummaryTimeline()
|
||||||
private void load()
|
|
||||||
{
|
{
|
||||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
editorBeatmap = new EditorBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
AddStep("create timeline", () =>
|
||||||
|
{
|
||||||
|
// required for track
|
||||||
|
Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap);
|
||||||
|
|
||||||
Add(new SummaryTimeline
|
Add(new SummaryTimeline
|
||||||
{
|
{
|
||||||
@ -29,6 +37,7 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(500, 50)
|
Size = new Vector2(500, 50)
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ using osu.Game.Rulesets.Scoring;
|
|||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Play.PlayerSettings;
|
using osu.Game.Screens.Play.PlayerSettings;
|
||||||
|
using osu.Game.Utils;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
@ -48,6 +49,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
[Cached]
|
[Cached]
|
||||||
private readonly VolumeOverlay volumeOverlay;
|
private readonly VolumeOverlay volumeOverlay;
|
||||||
|
|
||||||
|
[Cached(typeof(BatteryInfo))]
|
||||||
|
private readonly LocalBatteryInfo batteryInfo = new LocalBatteryInfo();
|
||||||
|
|
||||||
private readonly ChangelogOverlay changelogOverlay;
|
private readonly ChangelogOverlay changelogOverlay;
|
||||||
|
|
||||||
public TestScenePlayerLoader()
|
public TestScenePlayerLoader()
|
||||||
@ -288,6 +292,33 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase(false, 1.0, false)] // not charging, above cutoff --> no warning
|
||||||
|
[TestCase(true, 0.1, false)] // charging, below cutoff --> no warning
|
||||||
|
[TestCase(false, 0.25, true)] // not charging, at cutoff --> warning
|
||||||
|
public void TestLowBatteryNotification(bool isCharging, double chargeLevel, bool shouldWarn)
|
||||||
|
{
|
||||||
|
AddStep("reset notification lock", () => sessionStatics.GetBindable<bool>(Static.LowBatteryNotificationShownOnce).Value = false);
|
||||||
|
|
||||||
|
// set charge status and level
|
||||||
|
AddStep("load player", () => resetPlayer(false, () =>
|
||||||
|
{
|
||||||
|
batteryInfo.SetCharging(isCharging);
|
||||||
|
batteryInfo.SetChargeLevel(chargeLevel);
|
||||||
|
}));
|
||||||
|
AddUntilStep("wait for player", () => player?.LoadState == LoadState.Ready);
|
||||||
|
AddAssert($"notification {(shouldWarn ? "triggered" : "not triggered")}", () => notificationOverlay.UnreadCount.Value == (shouldWarn ? 1 : 0));
|
||||||
|
AddStep("click notification", () =>
|
||||||
|
{
|
||||||
|
var scrollContainer = (OsuScrollContainer)notificationOverlay.Children.Last();
|
||||||
|
var flowContainer = scrollContainer.Children.OfType<FillFlowContainer<NotificationSection>>().First();
|
||||||
|
var notification = flowContainer.First();
|
||||||
|
|
||||||
|
InputManager.MoveMouseTo(notification);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
AddUntilStep("wait for player load", () => player.IsLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestEpilepsyWarningEarlyExit()
|
public void TestEpilepsyWarningEarlyExit()
|
||||||
{
|
{
|
||||||
@ -349,5 +380,29 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
throw new TimeoutException();
|
throw new TimeoutException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mutable dummy BatteryInfo class for <see cref="TestScenePlayerLoader.TestLowBatteryNotification"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <inheritdoc/>
|
||||||
|
private class LocalBatteryInfo : BatteryInfo
|
||||||
|
{
|
||||||
|
private bool isCharging = true;
|
||||||
|
private double chargeLevel = 1;
|
||||||
|
|
||||||
|
public override bool IsCharging => isCharging;
|
||||||
|
|
||||||
|
public override double ChargeLevel => chargeLevel;
|
||||||
|
|
||||||
|
public void SetCharging(bool value)
|
||||||
|
{
|
||||||
|
isCharging = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetChargeLevel(double value)
|
||||||
|
{
|
||||||
|
chargeLevel = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ namespace osu.Game.Configuration
|
|||||||
{
|
{
|
||||||
SetDefault(Static.LoginOverlayDisplayed, false);
|
SetDefault(Static.LoginOverlayDisplayed, false);
|
||||||
SetDefault(Static.MutedAudioNotificationShownOnce, false);
|
SetDefault(Static.MutedAudioNotificationShownOnce, false);
|
||||||
|
SetDefault(Static.LowBatteryNotificationShownOnce, false);
|
||||||
SetDefault(Static.LastHoverSoundPlaybackTime, (double?)null);
|
SetDefault(Static.LastHoverSoundPlaybackTime, (double?)null);
|
||||||
SetDefault<APISeasonalBackgrounds>(Static.SeasonalBackgrounds, null);
|
SetDefault<APISeasonalBackgrounds>(Static.SeasonalBackgrounds, null);
|
||||||
}
|
}
|
||||||
@ -25,6 +26,7 @@ namespace osu.Game.Configuration
|
|||||||
{
|
{
|
||||||
LoginOverlayDisplayed,
|
LoginOverlayDisplayed,
|
||||||
MutedAudioNotificationShownOnce,
|
MutedAudioNotificationShownOnce,
|
||||||
|
LowBatteryNotificationShownOnce,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Info about seasonal backgrounds available fetched from API - see <see cref="APISeasonalBackgrounds"/>.
|
/// Info about seasonal backgrounds available fetched from API - see <see cref="APISeasonalBackgrounds"/>.
|
||||||
|
@ -40,6 +40,7 @@ using osu.Game.Rulesets;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Utils;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
using RuntimeInfo = osu.Framework.RuntimeInfo;
|
using RuntimeInfo = osu.Framework.RuntimeInfo;
|
||||||
|
|
||||||
@ -156,6 +157,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
protected override UserInputManager CreateUserInputManager() => new OsuUserInputManager();
|
protected override UserInputManager CreateUserInputManager() => new OsuUserInputManager();
|
||||||
|
|
||||||
|
protected virtual BatteryInfo CreateBatteryInfo() => null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum volume at which audio tracks should playback. This can be set lower than 1 to create some head-room for sound effects.
|
/// The maximum volume at which audio tracks should playback. This can be set lower than 1 to create some head-room for sound effects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -281,6 +284,11 @@ namespace osu.Game
|
|||||||
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
|
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
|
||||||
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
|
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
|
||||||
dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore));
|
dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore));
|
||||||
|
|
||||||
|
var powerStatus = CreateBatteryInfo();
|
||||||
|
if (powerStatus != null)
|
||||||
|
dependencies.CacheAs(powerStatus);
|
||||||
|
|
||||||
dependencies.Cache(new SessionStatics());
|
dependencies.Cache(new SessionStatics());
|
||||||
dependencies.Cache(new OsuColour());
|
dependencies.Cache(new OsuColour());
|
||||||
|
|
||||||
|
@ -56,8 +56,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
|
|
||||||
public virtual IEnumerable<HitSampleInfo> GetSamples() => HitObject.Samples;
|
public virtual IEnumerable<HitSampleInfo> GetSamples() => HitObject.Samples;
|
||||||
|
|
||||||
private readonly Lazy<List<DrawableHitObject>> nestedHitObjects = new Lazy<List<DrawableHitObject>>();
|
private readonly List<DrawableHitObject> nestedHitObjects = new List<DrawableHitObject>();
|
||||||
public IReadOnlyList<DrawableHitObject> NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : (IReadOnlyList<DrawableHitObject>)Array.Empty<DrawableHitObject>();
|
public IReadOnlyList<DrawableHitObject> NestedHitObjects => nestedHitObjects;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this object should handle any user input events.
|
/// Whether this object should handle any user input events.
|
||||||
@ -249,7 +249,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
// Must be done before the nested DHO is added to occur before the nested Apply()!
|
// Must be done before the nested DHO is added to occur before the nested Apply()!
|
||||||
drawableNested.ParentHitObject = this;
|
drawableNested.ParentHitObject = this;
|
||||||
|
|
||||||
nestedHitObjects.Value.Add(drawableNested);
|
nestedHitObjects.Add(drawableNested);
|
||||||
AddNestedHitObject(drawableNested);
|
AddNestedHitObject(drawableNested);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,18 +305,15 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
if (Samples != null)
|
if (Samples != null)
|
||||||
Samples.Samples = null;
|
Samples.Samples = null;
|
||||||
|
|
||||||
if (nestedHitObjects.IsValueCreated)
|
foreach (var obj in nestedHitObjects)
|
||||||
{
|
|
||||||
foreach (var obj in nestedHitObjects.Value)
|
|
||||||
{
|
{
|
||||||
obj.OnNewResult -= onNewResult;
|
obj.OnNewResult -= onNewResult;
|
||||||
obj.OnRevertResult -= onRevertResult;
|
obj.OnRevertResult -= onRevertResult;
|
||||||
obj.ApplyCustomUpdateState -= onApplyCustomUpdateState;
|
obj.ApplyCustomUpdateState -= onApplyCustomUpdateState;
|
||||||
}
|
}
|
||||||
|
|
||||||
nestedHitObjects.Value.Clear();
|
nestedHitObjects.Clear();
|
||||||
ClearNestedHitObjects();
|
ClearNestedHitObjects();
|
||||||
}
|
|
||||||
|
|
||||||
HitObject.DefaultsApplied -= onDefaultsApplied;
|
HitObject.DefaultsApplied -= onDefaultsApplied;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
var enumerable = HitObjectContainer.Objects;
|
var enumerable = HitObjectContainer.Objects;
|
||||||
|
|
||||||
if (nestedPlayfields.IsValueCreated)
|
if (nestedPlayfields.Count != 0)
|
||||||
enumerable = enumerable.Concat(NestedPlayfields.SelectMany(p => p.AllHitObjects));
|
enumerable = enumerable.Concat(NestedPlayfields.SelectMany(p => p.AllHitObjects));
|
||||||
|
|
||||||
return enumerable;
|
return enumerable;
|
||||||
@ -76,9 +76,9 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// All <see cref="Playfield"/>s nested inside this <see cref="Playfield"/>.
|
/// All <see cref="Playfield"/>s nested inside this <see cref="Playfield"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<Playfield> NestedPlayfields => nestedPlayfields.IsValueCreated ? nestedPlayfields.Value : Enumerable.Empty<Playfield>();
|
public IEnumerable<Playfield> NestedPlayfields => nestedPlayfields;
|
||||||
|
|
||||||
private readonly Lazy<List<Playfield>> nestedPlayfields = new Lazy<List<Playfield>>();
|
private readonly List<Playfield> nestedPlayfields = new List<Playfield>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether judgements should be displayed by this and and all nested <see cref="Playfield"/>s.
|
/// Whether judgements should be displayed by this and and all nested <see cref="Playfield"/>s.
|
||||||
@ -217,7 +217,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
otherPlayfield.HitObjectUsageBegan += h => HitObjectUsageBegan?.Invoke(h);
|
otherPlayfield.HitObjectUsageBegan += h => HitObjectUsageBegan?.Invoke(h);
|
||||||
otherPlayfield.HitObjectUsageFinished += h => HitObjectUsageFinished?.Invoke(h);
|
otherPlayfield.HitObjectUsageFinished += h => HitObjectUsageFinished?.Invoke(h);
|
||||||
|
|
||||||
nestedPlayfields.Value.Add(otherPlayfield);
|
nestedPlayfields.Add(otherPlayfield);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -279,12 +279,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool removedFromNested = false;
|
return nestedPlayfields.Any(p => p.Remove(hitObject));
|
||||||
|
|
||||||
if (nestedPlayfields.IsValueCreated)
|
|
||||||
removedFromNested = nestedPlayfields.Value.Any(p => p.Remove(hitObject));
|
|
||||||
|
|
||||||
return removedFromNested;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -429,10 +424,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nestedPlayfields.IsValueCreated)
|
foreach (var p in nestedPlayfields)
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var p in nestedPlayfields.Value)
|
|
||||||
p.SetKeepAlive(hitObject, keepAlive);
|
p.SetKeepAlive(hitObject, keepAlive);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,10 +436,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
foreach (var (_, entry) in lifetimeEntryMap)
|
foreach (var (_, entry) in lifetimeEntryMap)
|
||||||
entry.KeepAlive = true;
|
entry.KeepAlive = true;
|
||||||
|
|
||||||
if (!nestedPlayfields.IsValueCreated)
|
foreach (var p in nestedPlayfields)
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var p in nestedPlayfields.Value)
|
|
||||||
p.KeepAllAlive();
|
p.KeepAllAlive();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,10 +450,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
{
|
{
|
||||||
HitObjectContainer.PastLifetimeExtension = value;
|
HitObjectContainer.PastLifetimeExtension = value;
|
||||||
|
|
||||||
if (!nestedPlayfields.IsValueCreated)
|
foreach (var nested in nestedPlayfields)
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var nested in nestedPlayfields.Value)
|
|
||||||
nested.PastLifetimeExtension = value;
|
nested.PastLifetimeExtension = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,10 +465,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
{
|
{
|
||||||
HitObjectContainer.FutureLifetimeExtension = value;
|
HitObjectContainer.FutureLifetimeExtension = value;
|
||||||
|
|
||||||
if (!nestedPlayfields.IsValueCreated)
|
foreach (var nested in nestedPlayfields)
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var nested in nestedPlayfields.Value)
|
|
||||||
nested.FutureLifetimeExtension = value;
|
nested.FutureLifetimeExtension = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,12 @@ namespace osu.Game.Screens.Backgrounds
|
|||||||
private WorkingBeatmap beatmap;
|
private WorkingBeatmap beatmap;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not user-configured settings relating to brightness of elements should be ignored
|
/// Whether or not user-configured settings relating to brightness of elements should be ignored.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly Bindable<bool> IgnoreUserSettings = new Bindable<bool>();
|
/// <remarks>
|
||||||
|
/// Beatmap background screens should not apply user settings by default.
|
||||||
|
/// </remarks>
|
||||||
|
public readonly Bindable<bool> IgnoreUserSettings = new Bindable<bool>(true);
|
||||||
|
|
||||||
public readonly Bindable<bool> StoryboardReplacesBackground = new Bindable<bool>();
|
public readonly Bindable<bool> StoryboardReplacesBackground = new Bindable<bool>();
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours) => Colour = colours.Yellow;
|
private void load(OsuColour colours) => Colour = colours.GreyCarmineLight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||||
|
{
|
||||||
|
public class ControlPointVisualisation : PointVisualisation
|
||||||
|
{
|
||||||
|
protected readonly ControlPoint Point;
|
||||||
|
|
||||||
|
public ControlPointVisualisation(ControlPoint point)
|
||||||
|
{
|
||||||
|
Point = point;
|
||||||
|
|
||||||
|
Height = 0.25f;
|
||||||
|
Origin = Anchor.TopCentre;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Colour = Point.GetRepresentingColour(colours);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||||
|
{
|
||||||
|
public class EffectPointVisualisation : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly EffectControlPoint effect;
|
||||||
|
private Bindable<bool> kiai;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private EditorBeatmap beatmap { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
|
public EffectPointVisualisation(EffectControlPoint point)
|
||||||
|
{
|
||||||
|
RelativePositionAxes = Axes.Both;
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
effect = point;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
kiai = effect.KiaiModeBindable.GetBoundCopy();
|
||||||
|
kiai.BindValueChanged(_ =>
|
||||||
|
{
|
||||||
|
ClearInternal();
|
||||||
|
|
||||||
|
AddInternal(new ControlPointVisualisation(effect));
|
||||||
|
|
||||||
|
if (!kiai.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var endControlPoint = beatmap.ControlPointInfo.EffectPoints.FirstOrDefault(c => c.Time > effect.Time && !c.KiaiMode);
|
||||||
|
|
||||||
|
// handle kiai duration
|
||||||
|
// eventually this will be simpler when we have control points with durations.
|
||||||
|
if (endControlPoint != null)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Origin = Anchor.TopLeft;
|
||||||
|
|
||||||
|
Width = (float)(endControlPoint.Time - effect.Time);
|
||||||
|
|
||||||
|
AddInternal(new PointVisualisation
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
|
Width = 1,
|
||||||
|
Height = 0.25f,
|
||||||
|
Depth = float.MaxValue,
|
||||||
|
Colour = effect.GetRepresentingColour(colours).Darken(0.5f),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,33 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||||
{
|
{
|
||||||
public class GroupVisualisation : PointVisualisation
|
public class GroupVisualisation : CompositeDrawable
|
||||||
{
|
{
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
public readonly ControlPointGroup Group;
|
public readonly ControlPointGroup Group;
|
||||||
|
|
||||||
private readonly IBindableList<ControlPoint> controlPoints = new BindableList<ControlPoint>();
|
private readonly IBindableList<ControlPoint> controlPoints = new BindableList<ControlPoint>();
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private OsuColour colours { get; set; }
|
|
||||||
|
|
||||||
public GroupVisualisation(ControlPointGroup group)
|
public GroupVisualisation(ControlPointGroup group)
|
||||||
: base(group.Time)
|
|
||||||
{
|
{
|
||||||
|
RelativePositionAxes = Axes.X;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Origin = Anchor.TopLeft;
|
||||||
|
|
||||||
Group = group;
|
Group = group;
|
||||||
|
X = (float)group.Time;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -33,13 +37,32 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
|||||||
controlPoints.BindTo(Group.ControlPoints);
|
controlPoints.BindTo(Group.ControlPoints);
|
||||||
controlPoints.BindCollectionChanged((_, __) =>
|
controlPoints.BindCollectionChanged((_, __) =>
|
||||||
{
|
{
|
||||||
if (controlPoints.Count == 0)
|
ClearInternal();
|
||||||
{
|
|
||||||
Colour = Color4.Transparent;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Colour = controlPoints.Any(c => c is TimingControlPoint) ? colours.YellowDark : colours.Green;
|
if (controlPoints.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var point in Group.ControlPoints)
|
||||||
|
{
|
||||||
|
switch (point)
|
||||||
|
{
|
||||||
|
case TimingControlPoint _:
|
||||||
|
AddInternal(new ControlPointVisualisation(point) { Y = 0, });
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DifficultyControlPoint _:
|
||||||
|
AddInternal(new ControlPointVisualisation(point) { Y = 0.25f, });
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SampleControlPoint _:
|
||||||
|
AddInternal(new ControlPointVisualisation(point) { Y = 0.5f, });
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EffectControlPoint effect:
|
||||||
|
AddInternal(new EffectPointVisualisation(effect) { Y = 0.75f });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Y = -10,
|
||||||
Height = 0.35f
|
Height = 0.35f
|
||||||
},
|
},
|
||||||
new BookmarkPart
|
new BookmarkPart
|
||||||
@ -38,6 +39,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary
|
|||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
|
Name = "centre line",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = colours.Gray5,
|
Colour = colours.Gray5,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -45,7 +47,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary
|
|||||||
new Circle
|
new Circle
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(5)
|
Size = new Vector2(5)
|
||||||
},
|
},
|
||||||
new Box
|
new Box
|
||||||
@ -59,7 +61,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary
|
|||||||
new Circle
|
new Circle
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreRight,
|
Anchor = Anchor.CentreRight,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(5)
|
Size = new Vector2(5)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -69,7 +71,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Height = 0.25f
|
Height = 0.10f
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
|
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
|
||||||
@ -10,19 +9,15 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a spanning point on a timeline part.
|
/// Represents a spanning point on a timeline part.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DurationVisualisation : Container
|
public class DurationVisualisation : Circle
|
||||||
{
|
{
|
||||||
protected DurationVisualisation(double startTime, double endTime)
|
protected DurationVisualisation(double startTime, double endTime)
|
||||||
{
|
{
|
||||||
Masking = true;
|
|
||||||
CornerRadius = 5;
|
|
||||||
|
|
||||||
RelativePositionAxes = Axes.X;
|
RelativePositionAxes = Axes.X;
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
X = (float)startTime;
|
X = (float)startTime;
|
||||||
Width = (float)(endTime - startTime);
|
Width = (float)(endTime - startTime);
|
||||||
|
|
||||||
AddInternal(new Box { RelativeSizeAxes = Axes.Both });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a singular point on a timeline part.
|
/// Represents a singular point on a timeline part.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PointVisualisation : Box
|
public class PointVisualisation : Circle
|
||||||
{
|
{
|
||||||
public const float MAX_WIDTH = 4;
|
public const float MAX_WIDTH = 4;
|
||||||
|
|
||||||
@ -21,9 +21,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
|
|||||||
|
|
||||||
public PointVisualisation()
|
public PointVisualisation()
|
||||||
{
|
{
|
||||||
Origin = Anchor.TopCentre;
|
RelativePositionAxes = Axes.Both;
|
||||||
|
|
||||||
RelativePositionAxes = Axes.X;
|
|
||||||
RelativeSizeAxes = Axes.Y;
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
|
||||||
Anchor = Anchor.CentreLeft;
|
Anchor = Anchor.CentreLeft;
|
||||||
|
@ -24,6 +24,7 @@ using osu.Game.Overlays.Notifications;
|
|||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
using osu.Game.Screens.Play.PlayerSettings;
|
using osu.Game.Screens.Play.PlayerSettings;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
using osu.Game.Utils;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -112,6 +113,9 @@ namespace osu.Game.Screens.Play
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private AudioManager audioManager { get; set; }
|
private AudioManager audioManager { get; set; }
|
||||||
|
|
||||||
|
[Resolved(CanBeNull = true)]
|
||||||
|
private BatteryInfo batteryInfo { get; set; }
|
||||||
|
|
||||||
public PlayerLoader(Func<Player> createPlayer)
|
public PlayerLoader(Func<Player> createPlayer)
|
||||||
{
|
{
|
||||||
this.createPlayer = createPlayer;
|
this.createPlayer = createPlayer;
|
||||||
@ -121,6 +125,7 @@ namespace osu.Game.Screens.Play
|
|||||||
private void load(SessionStatics sessionStatics)
|
private void load(SessionStatics sessionStatics)
|
||||||
{
|
{
|
||||||
muteWarningShownOnce = sessionStatics.GetBindable<bool>(Static.MutedAudioNotificationShownOnce);
|
muteWarningShownOnce = sessionStatics.GetBindable<bool>(Static.MutedAudioNotificationShownOnce);
|
||||||
|
batteryWarningShownOnce = sessionStatics.GetBindable<bool>(Static.LowBatteryNotificationShownOnce);
|
||||||
|
|
||||||
InternalChild = (content = new LogoTrackingContainer
|
InternalChild = (content = new LogoTrackingContainer
|
||||||
{
|
{
|
||||||
@ -196,6 +201,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Scheduler.Add(new ScheduledDelegate(pushWhenLoaded, Clock.CurrentTime + 1800, 0));
|
Scheduler.Add(new ScheduledDelegate(pushWhenLoaded, Clock.CurrentTime + 1800, 0));
|
||||||
|
|
||||||
showMuteWarningIfNeeded();
|
showMuteWarningIfNeeded();
|
||||||
|
showBatteryWarningIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnResuming(IScreen last)
|
public override void OnResuming(IScreen last)
|
||||||
@ -470,5 +476,48 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Low battery warning
|
||||||
|
|
||||||
|
private Bindable<bool> batteryWarningShownOnce;
|
||||||
|
|
||||||
|
private void showBatteryWarningIfNeeded()
|
||||||
|
{
|
||||||
|
if (batteryInfo == null) return;
|
||||||
|
|
||||||
|
if (!batteryWarningShownOnce.Value)
|
||||||
|
{
|
||||||
|
if (!batteryInfo.IsCharging && batteryInfo.ChargeLevel <= 0.25)
|
||||||
|
{
|
||||||
|
notificationOverlay?.Post(new BatteryWarningNotification());
|
||||||
|
batteryWarningShownOnce.Value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BatteryWarningNotification : SimpleNotification
|
||||||
|
{
|
||||||
|
public override bool IsImportant => true;
|
||||||
|
|
||||||
|
public BatteryWarningNotification()
|
||||||
|
{
|
||||||
|
Text = "Your battery level is low! Charge your device to prevent interruptions during gameplay.";
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours, NotificationOverlay notificationOverlay)
|
||||||
|
{
|
||||||
|
Icon = FontAwesome.Solid.BatteryQuarter;
|
||||||
|
IconBackgound.Colour = colours.RedDark;
|
||||||
|
|
||||||
|
Activated = delegate
|
||||||
|
{
|
||||||
|
notificationOverlay.Hide();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
osu.Game/Utils/BatteryInfo.cs
Normal file
18
osu.Game/Utils/BatteryInfo.cs
Normal file
@ -0,0 +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.
|
||||||
|
|
||||||
|
namespace osu.Game.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides access to the system's power status.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class BatteryInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The charge level of the battery, from 0 to 1.
|
||||||
|
/// </summary>
|
||||||
|
public abstract double ChargeLevel { get; }
|
||||||
|
|
||||||
|
public abstract bool IsCharging { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.NETCore.Targets" Version="3.1.0" />
|
<PackageReference Include="Microsoft.NETCore.Targets" Version="3.1.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2021.413.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2021.415.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.412.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.412.0" />
|
||||||
<PackageReference Include="Sentry" Version="3.2.0" />
|
<PackageReference Include="Sentry" Version="3.2.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.28.1" />
|
<PackageReference Include="SharpCompress" Version="0.28.1" />
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.413.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.415.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.412.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.412.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
||||||
@ -93,7 +93,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2021.413.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2021.415.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.28.1" />
|
<PackageReference Include="SharpCompress" Version="0.28.1" />
|
||||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
|
@ -5,6 +5,8 @@ using System;
|
|||||||
using Foundation;
|
using Foundation;
|
||||||
using osu.Game;
|
using osu.Game;
|
||||||
using osu.Game.Updater;
|
using osu.Game.Updater;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
using Xamarin.Essentials;
|
||||||
|
|
||||||
namespace osu.iOS
|
namespace osu.iOS
|
||||||
{
|
{
|
||||||
@ -13,5 +15,14 @@ namespace osu.iOS
|
|||||||
public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString());
|
public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString());
|
||||||
|
|
||||||
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
||||||
|
|
||||||
|
protected override BatteryInfo CreateBatteryInfo() => new IOSBatteryInfo();
|
||||||
|
|
||||||
|
private class IOSBatteryInfo : BatteryInfo
|
||||||
|
{
|
||||||
|
public override double ChargeLevel => Battery.ChargeLevel;
|
||||||
|
|
||||||
|
public override bool IsCharging => Battery.PowerSource != BatteryPowerSource.Battery;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,5 +116,8 @@
|
|||||||
<Visible>false</Visible>
|
<Visible>false</Visible>
|
||||||
</ImageAsset>
|
</ImageAsset>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user