Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Vuforia UnityAppController Patch
#include "QCARUnityPlayer.h"
extern int _curOrientation;
#import "UnityAppController.h"
#import "UnityAppController+ViewHandling.h"
#import "UnityAppController+Rendering.h"
#import "iPhone_Sensors.h"
#import <CoreGraphics/CoreGraphics.h>
#import <QuartzCore/QuartzCore.h>
#import <QuartzCore/CADisplayLink.h>
#import <UIKit/UIKit.h>
#import <Availability.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/EAGLDrawable.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#include <mach/mach_time.h>
#import <AVFoundation/AVFoundation.h>
// MSAA_DEFAULT_SAMPLE_COUNT was moved to iPhone_GlesSupport.h
// ENABLE_INTERNAL_PROFILER and related defines were moved to iPhone_Profiler.h
// kFPS define for removed: you can use Application.targetFrameRate (30 fps by default)
// DisplayLink is the only run loop mode now - all others were removed
#include "CrashReporter.h"
#include "iPhone_OrientationSupport.h"
#include "iPhone_Profiler.h"
#include "UI/Keyboard.h"
#include "UI/UnityView.h"
#include "UI/SplashScreen.h"
#include "Unity/DisplayManager.h"
#include "Unity/EAGLContextHelper.h"
#include "Unity/GlesHelper.h"
#include "PluginBase/AppDelegateListener.h"
BOOL vuforia_patch_CameraCheckDone = NO;
extern "C" void UnityRunUnitTests();
bool _ios42orNewer = false;
bool _ios43orNewer = false;
bool _ios50orNewer = false;
bool _ios60orNewer = false;
bool _ios70orNewer = false;
bool _ios80orNewer = false;
bool _supportsDiscard = false;
bool _supportsMSAA = false;
bool _supportsPackedStencil = false;
bool _glesContextCreated = false;
bool _unityAppReady = false;
bool _skipPresent = false;
bool _didResignActive = false;
void UnityInitJoysticks();
@interface UnityAppController (vuforia_patch_Private) <UIAlertViewDelegate>
@end
@implementation UnityAppController
@synthesize unityView = _unityView;
@synthesize unityDisplayLink = _unityDisplayLink;
@synthesize rootView = _rootView;
@synthesize rootViewController = _rootController;
@synthesize mainDisplay = _mainDisplay;
@synthesize renderDelegate = _renderDelegate;
- (void)setWindow:(id)object {}
- (UIWindow*)window { return _window; }
- (void)shouldAttachRenderDelegate {}
- (void)preStartUnity {}
- (void)startUnity:(UIApplication*)application
{
UnityInitApplicationGraphics();
// we make sure that first level gets correct display list and orientation
[[DisplayManager Instance] updateDisplayListInUnity];
[self updateOrientationFromController:[SplashScreenController Instance]];
UnityLoadApplication();
Profiler_InitProfiler();
[self showGameUI];
[self createDisplayLink];
}
- (void)onForcedOrientation:(ScreenOrientation)orient
{
[_unityView willRotateTo:orient];
OrientView(_rootController, _rootView, orient);
[_rootView layoutSubviews];
[_unityView didRotate];
}
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
// UIInterfaceOrientationMaskAll
// it is the safest way of doing it:
// - GameCenter and some other services might have portrait-only variant
// and will throw exception if portrait is not supported here
// - When you change allowed orientations if you end up forbidding current one
// exception will be thrown
// Anyway this is intersected with values provided from UIViewController, so we are good
return (1 << UIInterfaceOrientationPortrait) | (1 << UIInterfaceOrientationPortraitUpsideDown)
| (1 << UIInterfaceOrientationLandscapeRight) | (1 << UIInterfaceOrientationLandscapeLeft);
}
- (void)application:(UIApplication*)application didReceiveLocalNotification:(UILocalNotification*)notification
{
AppController_SendNotificationWithArg(kUnityDidReceiveLocalNotification, notification);
UnitySendLocalNotification(notification);
}
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
{
AppController_SendNotificationWithArg(kUnityDidReceiveRemoteNotification, userInfo);
UnitySendRemoteNotification(userInfo);
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
AppController_SendNotificationWithArg(kUnityDidRegisterForRemoteNotificationsWithDeviceToken, deviceToken);
UnitySendDeviceToken(deviceToken);
}
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
AppController_SendNotificationWithArg(kUnityDidFailToRegisterForRemoteNotificationsWithError, error);
UnitySendRemoteNotificationError(error);
}
- (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation
{
NSMutableArray* keys = [NSMutableArray arrayWithCapacity:3];
NSMutableArray* values = [NSMutableArray arrayWithCapacity:3];
#define ADD_ITEM(item) do{ if(item) {[keys addObject:@#item]; [values addObject:item];} }while(0)
ADD_ITEM(url);
ADD_ITEM(sourceApplication);
ADD_ITEM(annotation);
#undef ADD_ITEM
NSDictionary* notifData = [NSDictionary dictionaryWithObjects:values forKeys:keys];
AppController_SendNotificationWithArg(kUnityOnOpenURL, notifData);
return YES;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
vuforia_patch_CameraCheckDone = YES;
}
- (void) vuforia_patch_WaitForCameraCheck
{
if (!vuforia_patch_CameraCheckDone) {
NSLog(@"Waiting for camera access check to be completed ...");
// block further execution until requestAccessForMediaType is back otherwise QCARInit call in DidBecomeActive
// would mess up AR stuff
while (!vuforia_patch_CameraCheckDone) { }
NSLog (@"Camera access check completed");
}
}
- (void)vuforia_patch_CameraPermissionAlert:(NSString*)message
{
// be sure to not block the main thread with our own UIAlert
vuforia_patch_CameraCheckDone = YES;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Kamera Einstellung"
message:message
delegate:self
cancelButtonTitle:@"Ändern"
otherButtonTitles:@"Weiter", nil];
[alertView show];
}
- (void)vuforia_patch_CheckCameraPermission
{
// Determine camera access on iOS >= 7
if ([AVCaptureDevice respondsToSelector:@selector(requestAccessForMediaType:completionHandler:)]) {
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(status == AVAuthorizationStatusAuthorized) {
NSLog (@"AVAuthorizationStatus (%ld): OK, authorised for using camera", (long)status);
vuforia_patch_CameraCheckDone = YES;
} else if(status == AVAuthorizationStatusDenied){
NSLog (@"AVAuthorizationStatus (%ld): NO authorisation to use the camera", (long)status);
[self vuforia_patch_CameraPermissionAlert:@"MyApp! funktioniert nur, wenn der Zugriff auf die Kamera erlaubt ist.\nDrücke \"Ändern\", um in die Systemeinstellungen zu wechseln.\nDrücke \"Weiter\", um MyApp! eingeschränkt zu nutzen"];
} else if(status == AVAuthorizationStatusRestricted){
NSLog (@"AVAuthorizationStatus (%ld): Camera authorisation restricted dur to parental control", (long)status);
[self vuforia_patch_CameraPermissionAlert:@"MyApp! funktioniert nur, wenn der Zugriff auf die Kamera erlaubt ist.\nBitte deine Eltern, die Kameraeinstellung zu erlauben. Dazu drücke \"Ändern\", um in die Systemeinstellungen zu wechseln.\nDrücke \"Weiter\", um MyApp! eingeschränkt zu nutzen"];
} else if(status == AVAuthorizationStatusNotDetermined){
NSLog (@"AVAuthorizationStatus (%ld): Very first start => Ask for camera authorisation", (long)status);
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (YES == granted) {
// User granted access to the camera, continue with app launch
NSLog (@"Authorised for using camera on very first start");
} else {
// User denied camera access, show warning
[self vuforia_patch_CameraPermissionAlert:@"MyApp! funktioniert nur, wenn der Zugriff auf die Kamera erlaubt ist.\nDrücke \"Ändern\", um in die Systemeinstellungen zu wechseln.\nDrücke \"Weiter\", um MyApp! eingeschränkt zu nutzen"];
}
vuforia_patch_CameraCheckDone = YES;
}];
} else {
// WTF, iOS 12 is out
NSLog(@"Unrecognised AVAuthorizationStatus %ld", (long)status);
vuforia_patch_CameraCheckDone = YES;
}
} else {
// iOS < 7 (camera access always OK)
vuforia_patch_CameraCheckDone = YES;
}
}
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
printf_console("-> applicationDidFinishLaunching()\n");
[self vuforia_patch_CheckCameraPermission];
// get local notification
if (&UIApplicationLaunchOptionsLocalNotificationKey != nil)
{
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (notification)
UnitySendLocalNotification(notification);
}
// get remote notification
if (&UIApplicationLaunchOptionsRemoteNotificationKey != nil)
{
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification)
UnitySendRemoteNotification(notification);
}
if ([UIDevice currentDevice].generatesDeviceOrientationNotifications == NO)
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[DisplayManager Initialize];
_mainDisplay = [[[DisplayManager Instance] mainDisplay] createView:YES showRightAway:NO];
_window = _mainDisplay->window;
[KeyboardDelegate Initialize];
[self createViewHierarchy];
[self preStartUnity];
UnityInitApplicationNoGraphics([[[NSBundle mainBundle] bundlePath]UTF8String]);
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
printf_console("-> applicationDidEnterBackground()\n");
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
printf_console("-> applicationWillEnterForeground()\n");
// if we were showing video before going to background - the view size may be changed while we are in background
[GetAppController().unityView recreateGLESSurfaceIfNeeded];
}
- (void)applicationDidBecomeActive:(UIApplication*)application
{
printf_console("-> applicationDidBecomeActive()\n");
if(_unityAppReady)
{
if(_didResignActive)
UnityPause(false);
}
else
{
NSString* orientation = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UIInterfaceOrientation"];
[self vuforia_patch_WaitForCameraCheck];
QCARUnityPlayer::getInstance().QCARInit([orientation UTF8String]);
QCARUnityPlayer::getInstance().QCARSetOrientation([_unityView contentOrientation]);
[self performSelector:@selector(startUnity:) withObject:application afterDelay:0];
}
_didResignActive = false;
}
- (void)applicationWillResignActive:(UIApplication*)application
{
printf_console("-> applicationWillResignActive()\n");
if(_unityAppReady)
{
QCARUnityPlayer::getInstance().QCARPause(true);
UnityPause(true);
extern void UnityStopVideoIfPlaying();
UnityStopVideoIfPlaying();
// Force player to do one more frame, so scripts get a chance to render custom screen for
// minimized app in task manager.
UnityForcedPlayerLoop();
[self repaintDisplayLink];
}
_didResignActive = true;
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application
{
printf_console("WARNING -> applicationDidReceiveMemoryWarning()\n");
}
- (void)applicationWillTerminate:(UIApplication*)application
{
printf_console("-> applicationWillTerminate()\n");
Profiler_UninitProfiler();
QCARUnityPlayer::getInstance().destroy();
UnityCleanup();
}
- (void)dealloc
{
extern void SensorsCleanup();
SensorsCleanup();
[self releaseViewHierarchy];
[super dealloc];
}
@end
void AppController_RenderPluginMethod(SEL method)
{
id delegate = GetAppController().renderDelegate;
if([delegate respondsToSelector:method])
[delegate performSelector:method];
}
void AppController_RenderPluginMethodWithArg(SEL method, id arg)
{
id delegate = GetAppController().renderDelegate;
if([delegate respondsToSelector:method])
[delegate performSelector:method withObject:arg];
}
void AppController_SendNotification(NSString* name)
{
[[NSNotificationCenter defaultCenter] postNotificationName:name object:GetAppController()];
}
void AppController_SendNotificationWithArg(NSString* name, id arg)
{
[[NSNotificationCenter defaultCenter] postNotificationName:name object:GetAppController() userInfo:arg];
}
extern "C" UIWindow* UnityGetMainWindow() { return GetAppController().mainDisplay->window; }
extern "C" UIViewController* UnityGetGLViewController() { return GetAppController().rootViewController; }
extern "C" UIView* UnityGetGLView() { return GetAppController().unityView; }
extern "C" ScreenOrientation UnityCurrentOrientation() { return [GetAppController().unityView contentOrientation]; }
bool LogToNSLogHandler(LogType logType, const char* log, va_list list)
{
NSLogv([NSString stringWithUTF8String:log], list);
return true;
}
void UnityInitTrampoline()
{
#if ENABLE_CRASH_REPORT_SUBMISSION
SubmitCrashReportsAsync();
#endif
InitCrashHandling();
_ios42orNewer = [[[UIDevice currentDevice] systemVersion] compare: @"4.2" options: NSNumericSearch] != NSOrderedAscending;
_ios43orNewer = [[[UIDevice currentDevice] systemVersion] compare: @"4.3" options: NSNumericSearch] != NSOrderedAscending;
_ios50orNewer = [[[UIDevice currentDevice] systemVersion] compare: @"5.0" options: NSNumericSearch] != NSOrderedAscending;
_ios60orNewer = [[[UIDevice currentDevice] systemVersion] compare: @"6.0" options: NSNumericSearch] != NSOrderedAscending;
_ios70orNewer = [[[UIDevice currentDevice] systemVersion] compare: @"7.0" options: NSNumericSearch] != NSOrderedAscending;
_ios80orNewer = [[[UIDevice currentDevice] systemVersion] compare: @"8.0" options: NSNumericSearch] != NSOrderedAscending;
// Try writing to console and if it fails switch to NSLog logging
fprintf(stdout, "\n");
if (ftell(stdout) < 0)
SetLogEntryHandler(LogToNSLogHandler);
// Fix home directory environment variable.
const char *newHomeDirectory = ([[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] UTF8String]);
setenv("XDG_CONFIG_HOME", newHomeDirectory, 1);
UnityInitJoysticks();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.