1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-31 08:52:56 +08:00

Remove OrientationManager and the entire mobile namespace

This commit is contained in:
Salman Alshamrani 2025-01-25 20:01:12 -05:00
parent bb7daae080
commit c18128e974
8 changed files with 138 additions and 230 deletions

View File

@ -1,39 +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 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;
}
}
}

View File

@ -3,11 +3,13 @@
using System;
using Android.App;
using Android.Content.PM;
using Microsoft.Maui.Devices;
using osu.Framework.Allocation;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Platform;
using osu.Game;
using osu.Game.Screens;
using osu.Game.Updater;
using osu.Game.Utils;
@ -71,7 +73,35 @@ namespace osu.Android
protected override void LoadComplete()
{
base.LoadComplete();
LoadComponentAsync(new AndroidOrientationManager(), Add);
UserPlayingState.BindValueChanged(_ => updateOrientation());
}
protected override void ScreenChanged(IOsuScreen? current, IOsuScreen? newScreen)
{
base.ScreenChanged(current, newScreen);
if (newScreen != null)
updateOrientation();
}
private void updateOrientation()
{
var orientation = MobileUtils.GetOrientation(this, (IOsuScreen)ScreenStack.CurrentScreen, gameActivity.IsTablet);
switch (orientation)
{
case MobileUtils.Orientation.Locked:
gameActivity.RequestedOrientation = ScreenOrientation.Locked;
break;
case MobileUtils.Orientation.Portrait:
gameActivity.RequestedOrientation = ScreenOrientation.Portrait;
break;
case MobileUtils.Orientation.Default:
gameActivity.RequestedOrientation = gameActivity.DefaultOrientation;
break;
}
}
public override void SetHost(GameHost host)

View File

@ -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.
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,
}
}

View File

@ -1,77 +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.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 lockToPortraitOnPhone = requiresPortraitOrientation.Value;
if (IsTablet)
{
if (lockCurrentOrientation)
SetAllowedOrientations(GameOrientation.Locked);
else
SetAllowedOrientations(null);
}
else
{
if (lockToPortraitOnPhone)
SetAllowedOrientations(GameOrientation.Portrait);
else if (lockCurrentOrientation)
SetAllowedOrientations(GameOrientation.Locked);
else
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);
}
}

View File

@ -173,25 +173,14 @@ namespace osu.Game
/// </summary>
public readonly IBindable<OverlayActivation> OverlayActivationMode = new Bindable<OverlayActivation>();
/// <summary>
/// On mobile phones, this specifies whether the device should be set and locked to portrait orientation.
/// Tablet devices are unaffected by this property.
/// </summary>
/// <remarks>
/// Implementations can be viewed in mobile projects.
/// </remarks>
public IBindable<bool> RequiresPortraitOrientation => requiresPortraitOrientation;
private readonly Bindable<bool> requiresPortraitOrientation = new BindableBool();
/// <summary>
/// Whether the back button is currently displayed.
/// </summary>
private readonly IBindable<bool> backButtonVisibility = new Bindable<bool>();
IBindable<LocalUserPlayingState> ILocalUserPlayInfo.PlayingState => playingState;
IBindable<LocalUserPlayingState> ILocalUserPlayInfo.PlayingState => UserPlayingState;
private readonly Bindable<LocalUserPlayingState> playingState = new Bindable<LocalUserPlayingState>();
protected readonly Bindable<LocalUserPlayingState> UserPlayingState = new Bindable<LocalUserPlayingState>();
protected OsuScreenStack ScreenStack;
@ -319,7 +308,7 @@ namespace osu.Game
protected override UserInputManager CreateUserInputManager()
{
var userInputManager = base.CreateUserInputManager();
(userInputManager as OsuUserInputManager)?.PlayingState.BindTo(playingState);
(userInputManager as OsuUserInputManager)?.PlayingState.BindTo(UserPlayingState);
return userInputManager;
}
@ -414,7 +403,7 @@ namespace osu.Game
// Transfer any runtime changes back to configuration file.
SkinManager.CurrentSkinInfo.ValueChanged += skin => configSkin.Value = skin.NewValue.ID.ToString();
playingState.BindValueChanged(p =>
UserPlayingState.BindValueChanged(p =>
{
BeatmapManager.PauseImports = p.NewValue != LocalUserPlayingState.NotPlaying;
SkinManager.PauseImports = p.NewValue != LocalUserPlayingState.NotPlaying;
@ -1555,7 +1544,7 @@ namespace osu.Game
GlobalCursorDisplay.ShowCursor = (ScreenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false;
}
private void screenChanged(IScreen current, IScreen newScreen)
protected virtual void ScreenChanged([CanBeNull] IOsuScreen current, [CanBeNull] IOsuScreen newScreen)
{
SentrySdk.ConfigureScope(scope =>
{
@ -1571,10 +1560,10 @@ namespace osu.Game
switch (current)
{
case Player player:
player.PlayingState.UnbindFrom(playingState);
player.PlayingState.UnbindFrom(UserPlayingState);
// reset for sanity.
playingState.Value = LocalUserPlayingState.NotPlaying;
UserPlayingState.Value = LocalUserPlayingState.NotPlaying;
break;
}
@ -1591,7 +1580,7 @@ namespace osu.Game
break;
case Player player:
player.PlayingState.BindTo(playingState);
player.PlayingState.BindTo(UserPlayingState);
break;
default:
@ -1599,32 +1588,32 @@ namespace osu.Game
break;
}
if (current is IOsuScreen currentOsuScreen)
if (current != null)
{
backButtonVisibility.UnbindFrom(currentOsuScreen.BackButtonVisibility);
OverlayActivationMode.UnbindFrom(currentOsuScreen.OverlayActivationMode);
configUserActivity.UnbindFrom(currentOsuScreen.Activity);
backButtonVisibility.UnbindFrom(current.BackButtonVisibility);
OverlayActivationMode.UnbindFrom(current.OverlayActivationMode);
configUserActivity.UnbindFrom(current.Activity);
}
if (newScreen is IOsuScreen newOsuScreen)
// Bind to new screen.
if (newScreen != null)
{
backButtonVisibility.BindTo(newOsuScreen.BackButtonVisibility);
OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode);
configUserActivity.BindTo(newOsuScreen.Activity);
backButtonVisibility.BindTo(newScreen.BackButtonVisibility);
OverlayActivationMode.BindTo(newScreen.OverlayActivationMode);
configUserActivity.BindTo(newScreen.Activity);
GlobalCursorDisplay.MenuCursor.HideCursorOnNonMouseInput = newOsuScreen.HideMenuCursorOnNonMouseInput;
// Handle various configuration updates based on new screen settings.
GlobalCursorDisplay.MenuCursor.HideCursorOnNonMouseInput = newScreen.HideMenuCursorOnNonMouseInput;
requiresPortraitOrientation.Value = newOsuScreen.RequiresPortraitOrientation;
if (newOsuScreen.HideOverlaysOnEnter)
if (newScreen.HideOverlaysOnEnter)
CloseAllOverlays();
else
Toolbar.Show();
if (newOsuScreen.ShowFooter)
if (newScreen.ShowFooter)
{
BackButton.Hide();
ScreenFooter.SetButtons(newOsuScreen.CreateFooterButtons());
ScreenFooter.SetButtons(newScreen.CreateFooterButtons());
ScreenFooter.Show();
}
else
@ -1632,16 +1621,16 @@ namespace osu.Game
ScreenFooter.SetButtons(Array.Empty<ScreenFooterButton>());
ScreenFooter.Hide();
}
}
skinEditor.SetTarget((OsuScreen)newScreen);
skinEditor.SetTarget((OsuScreen)newScreen);
}
}
private void screenPushed(IScreen lastScreen, IScreen newScreen) => screenChanged(lastScreen, newScreen);
private void screenPushed(IScreen lastScreen, IScreen newScreen) => ScreenChanged((OsuScreen)lastScreen, (OsuScreen)newScreen);
private void screenExited(IScreen lastScreen, IScreen newScreen)
{
screenChanged(lastScreen, newScreen);
ScreenChanged((OsuScreen)lastScreen, (OsuScreen)newScreen);
if (newScreen == null)
Exit();

View 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.Game.Screens;
using osu.Game.Screens.Play;
namespace osu.Game.Utils
{
public static class MobileUtils
{
/// <summary>
/// Determines the correct <see cref="Orientation"/> state which a mobile device should be put into for the given information.
/// </summary>
/// <param name="userPlayInfo">Information about whether the user is currently playing.</param>
/// <param name="currentScreen">The current screen which the user is at.</param>
/// <param name="isTablet">Whether the user is playing on a mobile tablet device instead of a phone.</param>
public static Orientation GetOrientation(ILocalUserPlayInfo userPlayInfo, IOsuScreen currentScreen, bool isTablet)
{
bool lockCurrentOrientation = userPlayInfo.PlayingState.Value == LocalUserPlayingState.Playing;
bool lockToPortraitOnPhone = currentScreen.RequiresPortraitOrientation;
if (lockToPortraitOnPhone && !isTablet)
return Orientation.Portrait;
if (lockCurrentOrientation)
return Orientation.Locked;
return Orientation.Default;
}
public enum Orientation
{
/// <summary>
/// Lock the game orientation.
/// </summary>
Locked,
/// <summary>
/// Lock the game to portrait orientation (does not include upside-down portrait).
/// </summary>
Portrait,
/// <summary>
/// Use the application's default settings.
/// </summary>
Default,
}
}
}

View File

@ -1,41 +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.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;
}
}
}

View File

@ -8,8 +8,10 @@ using osu.Framework.Graphics;
using osu.Framework.iOS;
using osu.Framework.Platform;
using osu.Game;
using osu.Game.Screens;
using osu.Game.Updater;
using osu.Game.Utils;
using UIKit;
namespace osu.iOS
{
@ -28,7 +30,36 @@ namespace osu.iOS
protected override void LoadComplete()
{
base.LoadComplete();
LoadComponentAsync(new IOSOrientationManager(appDelegate), Add);
UserPlayingState.BindValueChanged(_ => updateOrientation());
}
protected override void ScreenChanged(IOsuScreen? current, IOsuScreen? newScreen)
{
base.ScreenChanged(current, newScreen);
if (newScreen != null)
updateOrientation();
}
private void updateOrientation()
{
bool iPad = UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad;
var orientation = MobileUtils.GetOrientation(this, (IOsuScreen)ScreenStack.CurrentScreen, iPad);
switch (orientation)
{
case MobileUtils.Orientation.Locked:
appDelegate.Orientations = (UIInterfaceOrientationMask)(1 << (int)appDelegate.CurrentOrientation);
break;
case MobileUtils.Orientation.Portrait:
appDelegate.Orientations = UIInterfaceOrientationMask.Portrait;
break;
case MobileUtils.Orientation.Default:
appDelegate.Orientations = null;
break;
}
}
protected override UpdateManager CreateUpdateManager() => new MobileUpdateNotifier();