mirror of
https://github.com/ppy/osu.git
synced 2025-01-18 10:43:22 +08:00
Abstractify orientation handling and add Android support
This commit is contained in:
parent
d7e4038f4a
commit
0cd7f1b2d4
39
osu.Android/AndroidOrientationManager.cs
Normal file
39
osu.Android/AndroidOrientationManager.cs
Normal file
@ -0,0 +1,39 @@
|
||||
// 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 Android.Content.PM;
|
||||
using Android.Content.Res;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Mobile;
|
||||
|
||||
namespace osu.Android
|
||||
{
|
||||
public partial class AndroidOrientationManager : OrientationManager
|
||||
{
|
||||
[Resolved]
|
||||
private OsuGameActivity gameActivity { get; set; } = null!;
|
||||
|
||||
protected override bool IsCurrentOrientationPortrait => gameActivity.Resources!.Configuration!.Orientation == Orientation.Portrait;
|
||||
protected override bool IsTablet => gameActivity.IsTablet;
|
||||
|
||||
protected override void SetAllowedOrientations(GameOrientation? orientation)
|
||||
=> gameActivity.RequestedOrientation = orientation == null ? gameActivity.DefaultOrientation : toScreenOrientation(orientation.Value);
|
||||
|
||||
private static ScreenOrientation toScreenOrientation(GameOrientation orientation)
|
||||
{
|
||||
if (orientation == GameOrientation.Locked)
|
||||
return ScreenOrientation.Locked;
|
||||
|
||||
if (orientation == GameOrientation.Portrait)
|
||||
return ScreenOrientation.Portrait;
|
||||
|
||||
if (orientation == GameOrientation.Landscape)
|
||||
return ScreenOrientation.Landscape;
|
||||
|
||||
if (orientation == GameOrientation.FullPortrait)
|
||||
return ScreenOrientation.SensorPortrait;
|
||||
|
||||
return ScreenOrientation.SensorLandscape;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +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 Android.Content.PM;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Android
|
||||
{
|
||||
public partial class GameplayScreenRotationLocker : Component
|
||||
{
|
||||
private IBindable<LocalUserPlayingState> localUserPlaying = null!;
|
||||
|
||||
[Resolved]
|
||||
private OsuGameActivity gameActivity { get; set; } = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ILocalUserPlayInfo localUserPlayInfo)
|
||||
{
|
||||
localUserPlaying = localUserPlayInfo.PlayingState.GetBoundCopy();
|
||||
localUserPlaying.BindValueChanged(updateLock, true);
|
||||
}
|
||||
|
||||
private void updateLock(ValueChangedEvent<LocalUserPlayingState> userPlaying)
|
||||
{
|
||||
gameActivity.RunOnUiThread(() =>
|
||||
{
|
||||
gameActivity.RequestedOrientation = userPlaying.NewValue == LocalUserPlayingState.Playing ? ScreenOrientation.Locked : gameActivity.DefaultOrientation;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -50,6 +50,8 @@ namespace osu.Android
|
||||
/// <remarks>Adjusted on startup to match expected UX for the current device type (phone/tablet).</remarks>
|
||||
public ScreenOrientation DefaultOrientation = ScreenOrientation.Unspecified;
|
||||
|
||||
public bool IsTablet { get; private set; }
|
||||
|
||||
private OsuGameAndroid game = null!;
|
||||
|
||||
protected override Framework.Game CreateGame() => game = new OsuGameAndroid(this);
|
||||
@ -76,9 +78,9 @@ namespace osu.Android
|
||||
WindowManager.DefaultDisplay.GetSize(displaySize);
|
||||
#pragma warning restore CA1422
|
||||
float smallestWidthDp = Math.Min(displaySize.X, displaySize.Y) / Resources.DisplayMetrics.Density;
|
||||
bool isTablet = smallestWidthDp >= 600f;
|
||||
IsTablet = smallestWidthDp >= 600f;
|
||||
|
||||
RequestedOrientation = DefaultOrientation = isTablet ? ScreenOrientation.FullUser : ScreenOrientation.SensorLandscape;
|
||||
RequestedOrientation = DefaultOrientation = IsTablet ? ScreenOrientation.FullUser : ScreenOrientation.SensorLandscape;
|
||||
|
||||
// Currently (SDK 6.0.200), BundleAssemblies is not runnable for net6-android.
|
||||
// The assembly files are not available as files either after native AOT.
|
||||
|
@ -71,7 +71,7 @@ namespace osu.Android
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
LoadComponentAsync(new GameplayScreenRotationLocker(), Add);
|
||||
LoadComponentAsync(new AndroidOrientationManager(), Add);
|
||||
}
|
||||
|
||||
public override void SetHost(GameHost host)
|
||||
|
34
osu.Game/Mobile/GameOrientation.cs
Normal file
34
osu.Game/Mobile/GameOrientation.cs
Normal file
@ -0,0 +1,34 @@
|
||||
// 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.Mobile
|
||||
{
|
||||
public enum GameOrientation
|
||||
{
|
||||
/// <summary>
|
||||
/// Lock the game orientation.
|
||||
/// </summary>
|
||||
Locked,
|
||||
|
||||
/// <summary>
|
||||
/// Display the game in regular portrait orientation.
|
||||
/// </summary>
|
||||
Portrait,
|
||||
|
||||
/// <summary>
|
||||
/// Display the game in landscape-right orientation.
|
||||
/// </summary>
|
||||
Landscape,
|
||||
|
||||
/// <summary>
|
||||
/// Display the game in landscape-right/landscape-left orientations.
|
||||
/// </summary>
|
||||
FullLandscape,
|
||||
|
||||
/// <summary>
|
||||
/// Display the game in portrait/portrait-upside-down orientations.
|
||||
/// This is exclusive to tablet mobile devices.
|
||||
/// </summary>
|
||||
FullPortrait,
|
||||
}
|
||||
}
|
84
osu.Game/Mobile/OrientationManager.cs
Normal file
84
osu.Game/Mobile/OrientationManager.cs
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Mobile
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="Component"/> that manages the device orientations a game can display in.
|
||||
/// </summary>
|
||||
public abstract partial class OrientationManager : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the current orientation of the game is portrait.
|
||||
/// </summary>
|
||||
protected abstract bool IsCurrentOrientationPortrait { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the mobile device is considered a tablet.
|
||||
/// </summary>
|
||||
protected abstract bool IsTablet { get; }
|
||||
|
||||
[Resolved]
|
||||
private OsuGame game { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private ILocalUserPlayInfo localUserPlayInfo { get; set; } = null!;
|
||||
|
||||
private IBindable<bool> requiresPortraitOrientation = null!;
|
||||
private IBindable<LocalUserPlayingState> localUserPlaying = null!;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
requiresPortraitOrientation = game.RequiresPortraitOrientation.GetBoundCopy();
|
||||
requiresPortraitOrientation.BindValueChanged(_ => updateOrientations());
|
||||
|
||||
localUserPlaying = localUserPlayInfo.PlayingState.GetBoundCopy();
|
||||
localUserPlaying.BindValueChanged(_ => updateOrientations());
|
||||
|
||||
updateOrientations();
|
||||
}
|
||||
|
||||
private void updateOrientations()
|
||||
{
|
||||
bool lockCurrentOrientation = localUserPlaying.Value == LocalUserPlayingState.Playing;
|
||||
bool lockToPortrait = requiresPortraitOrientation.Value;
|
||||
|
||||
if (lockCurrentOrientation)
|
||||
{
|
||||
if (lockToPortrait && !IsCurrentOrientationPortrait)
|
||||
SetAllowedOrientations(GameOrientation.Portrait);
|
||||
else if (!lockToPortrait && IsCurrentOrientationPortrait && !IsTablet)
|
||||
SetAllowedOrientations(GameOrientation.Landscape);
|
||||
else
|
||||
SetAllowedOrientations(GameOrientation.Locked);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (lockToPortrait)
|
||||
{
|
||||
if (IsTablet)
|
||||
SetAllowedOrientations(GameOrientation.FullPortrait);
|
||||
else
|
||||
SetAllowedOrientations(GameOrientation.Portrait);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SetAllowedOrientations(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the allowed orientations the device can rotate to.
|
||||
/// </summary>
|
||||
/// <param name="orientation">The allowed orientations, or null to return back to default.</param>
|
||||
protected abstract void SetAllowedOrientations(GameOrientation? orientation);
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game;
|
||||
using osu.Game.Screens.Play;
|
||||
using UIKit;
|
||||
|
||||
namespace osu.iOS
|
||||
{
|
||||
public partial class IOSOrientationHandler : Component
|
||||
{
|
||||
private readonly AppDelegate appDelegate;
|
||||
|
||||
[Resolved]
|
||||
private OsuGame game { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private ILocalUserPlayInfo localUserPlayInfo { get; set; } = null!;
|
||||
|
||||
private IBindable<bool> requiresPortraitOrientation = null!;
|
||||
private IBindable<LocalUserPlayingState> localUserPlaying = null!;
|
||||
|
||||
public IOSOrientationHandler(AppDelegate appDelegate)
|
||||
{
|
||||
this.appDelegate = appDelegate;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
requiresPortraitOrientation = game.RequiresPortraitOrientation.GetBoundCopy();
|
||||
requiresPortraitOrientation.BindValueChanged(_ => updateOrientations());
|
||||
|
||||
localUserPlaying = localUserPlayInfo.PlayingState.GetBoundCopy();
|
||||
localUserPlaying.BindValueChanged(_ => updateOrientations());
|
||||
|
||||
updateOrientations();
|
||||
}
|
||||
|
||||
private void updateOrientations()
|
||||
{
|
||||
UIInterfaceOrientation currentOrientation = appDelegate.CurrentOrientation;
|
||||
bool lockCurrentOrientation = localUserPlaying.Value == LocalUserPlayingState.Playing;
|
||||
bool lockToPortrait = requiresPortraitOrientation.Value;
|
||||
bool isPhone = UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone;
|
||||
|
||||
if (lockCurrentOrientation)
|
||||
{
|
||||
if (lockToPortrait && !currentOrientation.IsPortrait())
|
||||
currentOrientation = UIInterfaceOrientation.Portrait;
|
||||
else if (!lockToPortrait && currentOrientation.IsPortrait() && isPhone)
|
||||
currentOrientation = UIInterfaceOrientation.LandscapeRight;
|
||||
|
||||
appDelegate.Orientations = (UIInterfaceOrientationMask)(1 << (int)currentOrientation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lockToPortrait)
|
||||
{
|
||||
UIInterfaceOrientationMask portraitOrientations = UIInterfaceOrientationMask.Portrait;
|
||||
|
||||
if (!isPhone)
|
||||
portraitOrientations |= UIInterfaceOrientationMask.PortraitUpsideDown;
|
||||
|
||||
appDelegate.Orientations = portraitOrientations;
|
||||
return;
|
||||
}
|
||||
|
||||
appDelegate.Orientations = null;
|
||||
}
|
||||
}
|
||||
}
|
41
osu.iOS/IOSOrientationManager.cs
Normal file
41
osu.iOS/IOSOrientationManager.cs
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Mobile;
|
||||
using UIKit;
|
||||
|
||||
namespace osu.iOS
|
||||
{
|
||||
public partial class IOSOrientationManager : OrientationManager
|
||||
{
|
||||
private readonly AppDelegate appDelegate;
|
||||
|
||||
protected override bool IsCurrentOrientationPortrait => appDelegate.CurrentOrientation.IsPortrait();
|
||||
protected override bool IsTablet => UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad;
|
||||
|
||||
public IOSOrientationManager(AppDelegate appDelegate)
|
||||
{
|
||||
this.appDelegate = appDelegate;
|
||||
}
|
||||
|
||||
protected override void SetAllowedOrientations(GameOrientation? orientation)
|
||||
=> appDelegate.Orientations = orientation == null ? null : toUIInterfaceOrientationMask(orientation.Value);
|
||||
|
||||
private UIInterfaceOrientationMask toUIInterfaceOrientationMask(GameOrientation orientation)
|
||||
{
|
||||
if (orientation == GameOrientation.Locked)
|
||||
return (UIInterfaceOrientationMask)(1 << (int)appDelegate.CurrentOrientation);
|
||||
|
||||
if (orientation == GameOrientation.Portrait)
|
||||
return UIInterfaceOrientationMask.Portrait;
|
||||
|
||||
if (orientation == GameOrientation.Landscape)
|
||||
return UIInterfaceOrientationMask.LandscapeRight;
|
||||
|
||||
if (orientation == GameOrientation.FullPortrait)
|
||||
return UIInterfaceOrientationMask.Portrait | UIInterfaceOrientationMask.PortraitUpsideDown;
|
||||
|
||||
return UIInterfaceOrientationMask.Landscape;
|
||||
}
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ namespace osu.iOS
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Add(new IOSOrientationHandler(appDelegate));
|
||||
LoadComponentAsync(new IOSOrientationManager(appDelegate), Add);
|
||||
}
|
||||
|
||||
protected override UpdateManager CreateUpdateManager() => new MobileUpdateNotifier();
|
||||
|
Loading…
Reference in New Issue
Block a user