-
Notifications
You must be signed in to change notification settings - Fork 422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bring back iOS application delegates and fix many issues #6453
Changes from all commits
f21100d
3134295
3ef7542
0edaede
dfbf4b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using Foundation; | ||
using osu.Framework; | ||
using osu.Framework.iOS; | ||
|
||
namespace SampleGame.iOS | ||
{ | ||
[Register("AppDelegate")] | ||
public class AppDelegate : GameApplicationDelegate | ||
{ | ||
protected override Game CreateGame() => new SampleGameGame(); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using UIKit; | ||
|
||
namespace SampleGame.iOS | ||
{ | ||
public static class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
UIApplication.Main(args, null, typeof(AppDelegate)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using osu.Framework.iOS; | ||
using TemplateGame.Game; | ||
|
||
namespace TemplateGame.iOS | ||
{ | ||
/// <inheritdoc /> | ||
public class AppDelegate : GameApplicationDelegate | ||
{ | ||
/// <inheritdoc /> | ||
protected override osu.Framework.Game CreateGame() => new TemplateGameGame(); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using UIKit; | ||
|
||
namespace TemplateGame.iOS | ||
{ | ||
/// <summary> | ||
/// </summary> | ||
public static class Program | ||
{ | ||
/// <summary> | ||
/// </summary> | ||
public static void Main(string[] args) | ||
{ | ||
UIApplication.Main(args, null, typeof(AppDelegate)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using FlappyDon.Game; | ||
using osu.Framework.iOS; | ||
|
||
namespace FlappyDon.iOS | ||
{ | ||
/// <inheritdoc /> | ||
public class AppDelegate : GameApplicationDelegate | ||
{ | ||
/// <inheritdoc /> | ||
protected override osu.Framework.Game CreateGame() => new FlappyDonGame(); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using UIKit; | ||
|
||
namespace FlappyDon.iOS | ||
{ | ||
/// <summary> | ||
/// </summary> | ||
public static class Program | ||
{ | ||
/// <summary> | ||
/// </summary> | ||
public static void Main(string[] args) | ||
{ | ||
UIApplication.Main(args, null, typeof(AppDelegate)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using Foundation; | ||
using osu.Framework.iOS; | ||
|
||
namespace osu.Framework.Tests | ||
{ | ||
[Register("AppDelegate")] | ||
public class AppDelegate : GameApplicationDelegate | ||
{ | ||
protected override Game CreateGame() => new VisualTestGame(); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using UIKit; | ||
|
||
namespace osu.Framework.Tests | ||
{ | ||
public static class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
UIApplication.Main(args, null, typeof(AppDelegate)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,48 +2,66 @@ | |
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using System; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
using AVFoundation; | ||
using Foundation; | ||
using ManagedBass; | ||
using ManagedBass.Fx; | ||
using ManagedBass.Mix; | ||
using SDL; | ||
using UIKit; | ||
using static SDL.SDL3; | ||
|
||
namespace osu.Framework.iOS | ||
{ | ||
public static class GameApplication | ||
/// <summary> | ||
/// Base <see cref="UIApplicationDelegate"/> implementation for osu!framework applications. | ||
/// </summary> | ||
public abstract class GameApplicationDelegate : UIApplicationDelegate | ||
{ | ||
private const string output_volume = @"outputVolume"; | ||
internal event Action<string>? DragDrop; | ||
|
||
private static IOSGameHost host = null!; | ||
private static Game game = null!; | ||
private const string output_volume = "outputVolume"; | ||
|
||
private static readonly OutputVolumeObserver output_volume_observer = new OutputVolumeObserver(); | ||
|
||
public static unsafe void Main(Game target) | ||
{ | ||
NativeLibrary.SetDllImportResolver(typeof(Bass).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bass.framework/bass", assembly, path)); | ||
NativeLibrary.SetDllImportResolver(typeof(BassFx).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bass_fx.framework/bass_fx", assembly, path)); | ||
NativeLibrary.SetDllImportResolver(typeof(BassMix).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bassmix.framework/bassmix", assembly, path)); | ||
NativeLibrary.SetDllImportResolver(typeof(SDL3).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/SDL3.framework/SDL3", assembly, path)); | ||
private IOSGameHost host = null!; | ||
|
||
game = target; | ||
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) | ||
{ | ||
mapLibraryNames(); | ||
|
||
SDL3.SDL_RunApp(0, null, &main, IntPtr.Zero); | ||
} | ||
SDL_SetMainReady(); | ||
SDL_SetiOSEventPump(true); | ||
|
||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] | ||
private static unsafe int main(int argc, byte** argv) | ||
{ | ||
var audioSession = AVAudioSession.SharedInstance(); | ||
audioSession.AddObserver(output_volume_observer, output_volume, NSKeyValueObservingOptions.New, 0); | ||
|
||
host = new IOSGameHost(); | ||
host.Run(game); | ||
host.Run(CreateGame()); | ||
return true; | ||
} | ||
|
||
return 0; | ||
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) | ||
{ | ||
// copied verbatim from SDL: https://github.com/libsdl-org/SDL/blob/d252a8fe126b998bd1b0f4e4cf52312cd11de378/src/video/uikit/SDL_uikitappdelegate.m#L508-L535 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you subclass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was the hope at first but it was an extremely complicated process. We haven't explored through the concept of "iOS binding projects" before, which is an essential key to expose such types in the C# world. And throughout a brief attempt from my end, it cannot be integrated within the It will be a multi-day effort with back-and-fourth discussions on where and how should it be implemented and whether it's going to cause issues if it's a separate project (looping back to the concern about the Android project being previously separate), so I ultimately gave up on it on the trust that SDL will not silently add crucial code in |
||
// the hope is that the SDL app delegate class does not have such handling exist there, but Apple does not provide a corresponding notification to make that possible. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there some copy-paste error in this comment? I don't really understand what it's supposed to say. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no error, there are just some iOS terminologies mixed in the comment. Apple provides things called The key point of this comment is that some functionalities that used to exist in |
||
NSUrl? fileUrl = url.FilePathUrl; | ||
DragDrop?.Invoke(fileUrl != null ? fileUrl.Path! : url.AbsoluteString!); | ||
return true; | ||
} | ||
|
||
/// <summary> | ||
/// Creates the <see cref="Game"/> class to launch. | ||
/// </summary> | ||
protected abstract Game CreateGame(); | ||
|
||
private static void mapLibraryNames() | ||
{ | ||
NativeLibrary.SetDllImportResolver(typeof(Bass).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bass.framework/bass", assembly, path)); | ||
NativeLibrary.SetDllImportResolver(typeof(BassFx).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bass_fx.framework/bass_fx", assembly, path)); | ||
NativeLibrary.SetDllImportResolver(typeof(BassMix).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/bassmix.framework/bassmix", assembly, path)); | ||
NativeLibrary.SetDllImportResolver(typeof(SDL3).Assembly, (_, assembly, path) => NativeLibrary.Load("@rpath/SDL3.framework/SDL3", assembly, path)); | ||
} | ||
|
||
private class OutputVolumeObserver : NSObject | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is
[Register("AppDelegate")]
missing here?Why is it required in the first place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The attribute is inserted by default into every created iOS project, I did not delve deep into why it's required but I wouldn't want to defy what .NET/Xamarin does so /shrug. Will fix the missing specification.