stk-code_catmod/lib/irrlicht/source/Irrlicht/CIrrDeviceiOS.mm
2019-12-21 01:30:01 +08:00

972 lines
27 KiB
Plaintext

// Copyright (C) 2002-2008 Nikolaus Gebhardt
// Copyright (C) 2008 Redshift Software, Inc.
// Copyright (C) 2012 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#import "CIrrDeviceiOS.h"
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
#include "IFileSystem.h"
#include "CTimer.h"
#include "COGLES2Driver.h"
#include "MobileCursorControl.h"
#import <CoreMotion/CoreMotion.h>
#import <GLKit/GLKView.h>
#import <sys/utsname.h>
extern void getConfigForDevice(const char* dev);
/* Important information */
// The application state events and following methods: IrrlichtDevice::isWindowActive, IrrlichtDevice::isWindowFocused
// and IrrlichtDevice::isWindowMinimized works out of box only if you'll use built-in CIrrDelegateiOS,
// so _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_ must be enabled in this case. If you need a custom UIApplicationDelegate you must
// handle all application events yourself.
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
namespace irr
{
class CIrrDeviceiOS;
}
@interface HideStatusBarView : UIViewController
-(BOOL)prefersStatusBarHidden;
-(BOOL)prefersHomeIndicatorAutoHidden;
-(void)viewDidAppear:(BOOL)animated;
-(void)viewDidLoad;
-(void)dealloc;
@end
@implementation HideStatusBarView
{
irr::CIrrDeviceiOS* Device;
}
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver: self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[super dealloc];
}
- (id)init: (irr::CIrrDeviceiOS*)device
{
self = [super init];
Device = device;
return self;
}
-(BOOL)prefersStatusBarHidden
{
return YES;
}
-(BOOL)prefersHomeIndicatorAutoHidden
{
return YES;
}
- (void)orientationChanged:(NSNotification*)note
{
UIDevice* dev = [UIDevice currentDevice];
if (dev == nil)
return;
UIDeviceOrientation orientation = [dev orientation];
switch(orientation)
{
case UIDeviceOrientationLandscapeLeft:
Device->setUpsideDown(true);
break;
case UIDeviceOrientationLandscapeRight:
Device->setUpsideDown(false);
break;
default:
break;
};
}
-(void)viewDidLoad
{
[super viewDidLoad];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
// On first lanuch orientationChanged returns UIDeviceOrientationUnknown,
// so we get the first oritentation from statusBarOrientation
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
// Those values are inverted with UIDeviceOrientation enum for landscape
if (orientation == UIInterfaceOrientationLandscapeLeft)
Device->setUpsideDown(false);
else if (orientation == UIInterfaceOrientationLandscapeRight)
Device->setUpsideDown(true);
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear : animated];
if (@available(iOS 11.0, *))
{
Device->setPaddings(self.view.safeAreaInsets.top,
self.view.safeAreaInsets.bottom,
self.view.safeAreaInsets.left,
self.view.safeAreaInsets.right);
}
}
@end
/* CIrrDelegateiOS */
@interface CIrrDelegateiOS : NSObject<UIApplicationDelegate>
- (void)setDevice:(irr::CIrrDeviceiOS*)device;
- (bool)isActive;
- (bool)hasFocus;
@property (strong, nonatomic) UIWindow* window;
@end
@implementation CIrrDelegateiOS
{
irr::CIrrDeviceiOS* Device;
bool Active;
bool Focus;
}
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)options
{
Device = nil;
Active = true;
Focus = false;
[self performSelectorOnMainThread:@selector(runSTK) withObject:nil waitUntilDone:NO];
return YES;
}
- (void)applicationWillTerminate:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_TERMINATE;
Device->postEventFromUser(ev);
Device->closeDevice();
}
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_MEMORY_WARNING;
Device->postEventFromUser(ev);
}
}
- (void)applicationWillResignActive:(UIApplication*)application
{
if (Device != nil)
{
Device->clearAllTouchIds();
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_PAUSE;
Device->postEventFromUser(ev);
}
Focus = false;
}
- (void)applicationDidEnterBackground:(UIApplication*)application
{
if (Device != nil)
{
Device->clearAllTouchIds();
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_DID_PAUSE;
Device->postEventFromUser(ev);
}
Active = false;
}
- (void)applicationWillEnterForeground:(UIApplication*)application
{
if (Device != nil)
{
Device->clearAllTouchIds();
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_RESUME;
Device->postEventFromUser(ev);
}
Active = true;
}
- (void)applicationDidBecomeActive:(UIApplication*)application
{
if (Device != nil)
{
Device->clearAllTouchIds();
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_DID_RESUME;
Device->postEventFromUser(ev);
}
Focus = true;
}
- (void)runSTK
{
override_default_params_for_mobile();
struct utsname system_info;
uname(&system_info);
NSString* model = [NSString stringWithCString:system_info.machine
encoding:NSUTF8StringEncoding];
getConfigForDevice([model UTF8String]);
ios_main(0, {});
// App store may not like this
exit(0);
}
- (void)setDevice:(irr::CIrrDeviceiOS*)device
{
Device = device;
}
- (bool)isActive
{
return Active;
}
- (bool)hasFocus
{
return Focus;
}
@end
#endif
/* CIrrViewiOS */
@interface CIrrViewiOS : GLKView
- (id)initWithFrame:(CGRect)frame forDevice:(irr::CIrrDeviceiOS*)device forContext:(EAGLContext*)eagl_context;
- (void)setDevice:(irr::CIrrDeviceiOS*)device;
@end
@implementation CIrrViewiOS
{
irr::CIrrDeviceiOS* Device;
}
- (id)initWithFrame:(CGRect)frame forDevice:(irr::CIrrDeviceiOS*)device forContext:(EAGLContext*)eagl_context
{
self = [super initWithFrame:(frame) context:(eagl_context)];
if (self)
{
self.drawableDepthFormat = GLKViewDrawableDepthFormat16;
self.multipleTouchEnabled = YES;
Device = device;
}
return self;
}
- (void)setDevice:(irr::CIrrDeviceiOS*)device
{
Device = device;
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
if (Device == nil)
return;
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_PRESSED_DOWN;
irr::core::position2d<irr::s32> mouse_pos = irr::core::position2d<irr::s32>(0, 0);
bool simulate_mouse = false;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = Device->getTouchId(touch);
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x * self.contentScaleFactor;
ev.TouchInput.Y = touchPoint.y * self.contentScaleFactor;
Device->postEventFromUser(ev);
if (ev.TouchInput.ID == 0)
{
simulate_mouse = true;
mouse_pos.X = ev.TouchInput.X;
mouse_pos.Y = ev.TouchInput.Y;
}
}
if (simulate_mouse)
Device->simulateMouse(ev, mouse_pos);
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
if (Device == nil)
return;
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_MOVED;
irr::core::position2d<irr::s32> mouse_pos = irr::core::position2d<irr::s32>(0, 0);
bool simulate_mouse = false;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = Device->getTouchId(touch);
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x * self.contentScaleFactor;
ev.TouchInput.Y = touchPoint.y * self.contentScaleFactor;
Device->postEventFromUser(ev);
if (ev.TouchInput.ID == 0)
{
simulate_mouse = true;
mouse_pos.X = ev.TouchInput.X;
mouse_pos.Y = ev.TouchInput.Y;
}
}
if (simulate_mouse)
Device->simulateMouse(ev, mouse_pos);
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
if (Device == nil)
return;
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_LEFT_UP;
irr::core::position2d<irr::s32> mouse_pos = irr::core::position2d<irr::s32>(0, 0);
bool simulate_mouse = false;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = Device->getTouchId(touch);
Device->removeTouchId(touch);
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x * self.contentScaleFactor;
ev.TouchInput.Y = touchPoint.y * self.contentScaleFactor;
Device->postEventFromUser(ev);
if (ev.TouchInput.ID == 0)
{
simulate_mouse = true;
mouse_pos.X = ev.TouchInput.X;
mouse_pos.Y = ev.TouchInput.Y;
}
}
if (simulate_mouse)
Device->simulateMouse(ev, mouse_pos);
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
if (Device == nil)
return;
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_LEFT_UP;
irr::core::position2d<irr::s32> mouse_pos = irr::core::position2d<irr::s32>(0, 0);
bool simulate_mouse = false;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = Device->getTouchId(touch);
Device->removeTouchId(touch);
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x * self.contentScaleFactor;
ev.TouchInput.Y = touchPoint.y * self.contentScaleFactor;
Device->postEventFromUser(ev);
if (ev.TouchInput.ID == 0)
{
simulate_mouse = true;
mouse_pos.X = ev.TouchInput.X;
mouse_pos.Y = ev.TouchInput.Y;
}
}
if (simulate_mouse)
Device->simulateMouse(ev, mouse_pos);
}
@end
namespace irr
{
struct SIrrDeviceiOSDataStorage
{
SIrrDeviceiOSDataStorage() : Window(0), ViewController(0), View(0), MotionManager(0), ReferenceAttitude(0)
{
MotionManager = [[CMMotionManager alloc] init];
m_eagl_context = 0;
}
~SIrrDeviceiOSDataStorage()
{
[Window release];
[ViewController release];
if (View != nil)
[View setDevice:nil];
[View release];
[MotionManager release];
[EAGLContext setCurrentContext:0];
[m_eagl_context release];
}
UIWindow* Window;
UIViewController* ViewController;
CIrrViewiOS* View;
CMMotionManager* MotionManager;
CMAttitude* ReferenceAttitude;
EAGLContext* m_eagl_context;
};
CIrrDeviceiOS::CIrrDeviceiOS(const SIrrlichtCreationParameters& params)
: CIrrDeviceStub(params), DataStorage(0), Close(false), m_upside_down(false)
{
m_top_padding = 0.0f;
m_bottom_padding = 0.0f;
m_left_padding = 0.0f;
m_right_padding = 0.0f;
m_native_scale = 1.0f;
#ifdef _DEBUG
setDebugName("CIrrDeviceiOS");
#endif
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
[delegate setDevice:this];
#endif
DataStorage = new SIrrDeviceiOSDataStorage();
FileSystem->changeWorkingDirectoryTo([[[NSBundle mainBundle] resourcePath] UTF8String]);
if (VideoModeList.getVideoModeCount() == 0)
{
// Add current screen size
CGRect screen_bounds = [[UIScreen mainScreen] nativeBounds];
// nativeBounds is the size in a portrait-up orientation, so reverse width and height
core::dimension2du screen_size =
{
(u32)screen_bounds.size.height,
(u32)screen_bounds.size.width
};
VideoModeList.addMode(screen_size, 32);
VideoModeList.setDesktop(32, screen_size);
}
createWindow();
createViewAndDriver();
if (!VideoDriver)
return;
createGUIAndScene();
CursorControl = new gui::MobileCursorControl();
}
CIrrDeviceiOS::~CIrrDeviceiOS()
{
deactivateDeviceMotion();
deactivateGyroscope();
deactivateAccelerometer();
delete static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
[delegate setDevice:nil];
#endif
}
bool CIrrDeviceiOS::run()
{
if (!Close)
{
const CFTimeInterval timeInSeconds = 0.000002;
s32 result = 0;
do
{
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeInSeconds, TRUE);
}
while (result == kCFRunLoopRunHandledSource);
os::Timer::tick();
//! Update events
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
//! Accelerometer
if (motionManager.isAccelerometerActive)
{
irr::SEvent ev;
ev.EventType = irr::EET_ACCELEROMETER_EVENT;
ev.AccelerometerEvent.X = motionManager.accelerometerData.acceleration.x * 9.81;
ev.AccelerometerEvent.Y = motionManager.accelerometerData.acceleration.y * 9.81;
ev.AccelerometerEvent.Z = motionManager.accelerometerData.acceleration.z * 9.81;
if (m_upside_down)
ev.AccelerometerEvent.Y = -ev.AccelerometerEvent.Y;
postEventFromUser(ev);
}
//! Gyroscope
if (motionManager.isGyroActive)
{
irr::SEvent ev;
ev.EventType = irr::EET_GYROSCOPE_EVENT;
ev.GyroscopeEvent.X = motionManager.gyroData.rotationRate.x;
ev.GyroscopeEvent.Y = motionManager.gyroData.rotationRate.y;
ev.GyroscopeEvent.Z = motionManager.gyroData.rotationRate.z;
postEventFromUser(ev);
}
//! Device Motion
if (motionManager.isDeviceMotionActive)
{
CMAttitude* currentAttitude = motionManager.deviceMotion.attitude;
CMAttitude* referenceAttitude = dataStorage->ReferenceAttitude;
if (referenceAttitude != nil)
[currentAttitude multiplyByInverseOfAttitude: referenceAttitude];
else
referenceAttitude = motionManager.deviceMotion.attitude;
irr::SEvent ev;
ev.EventType = irr::EET_DEVICE_MOTION_EVENT;
ev.AccelerometerEvent.X = currentAttitude.roll;
ev.AccelerometerEvent.Y = currentAttitude.pitch;
ev.AccelerometerEvent.Z = currentAttitude.yaw;
postEventFromUser(ev);
}
}
return !Close;
}
void CIrrDeviceiOS::yield()
{
struct timespec ts = {0,0};
nanosleep(&ts, NULL);
}
void CIrrDeviceiOS::sleep(u32 timeMs, bool pauseTimer=false)
{
bool wasStopped = Timer ? Timer->isStopped() : true;
struct timespec ts;
ts.tv_sec = (time_t) (timeMs / 1000);
ts.tv_nsec = (long) (timeMs % 1000) * 1000000;
if (pauseTimer && !wasStopped)
Timer->stop();
nanosleep(&ts, NULL);
if (pauseTimer && !wasStopped)
Timer->start();
}
void CIrrDeviceiOS::setWindowCaption(const wchar_t* text)
{
}
bool CIrrDeviceiOS::isWindowActive() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return [delegate isActive];
#else
return false;
#endif
}
bool CIrrDeviceiOS::isWindowFocused() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return [delegate hasFocus];
#else
return false;
#endif
}
bool CIrrDeviceiOS::isWindowMinimized() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return ![delegate isActive];
#else
return false;
#endif
}
bool CIrrDeviceiOS::present(video::IImage* image, void * windowId, core::rect<s32>* src)
{
return false;
}
void CIrrDeviceiOS::closeDevice()
{
CFRunLoopStop(CFRunLoopGetMain());
Close = true;
}
void CIrrDeviceiOS::setResizable(bool resize)
{
}
void CIrrDeviceiOS::minimizeWindow()
{
}
void CIrrDeviceiOS::maximizeWindow()
{
}
void CIrrDeviceiOS::restoreWindow()
{
}
bool CIrrDeviceiOS::getWindowPosition(int* x, int* y)
{
*x = 0;
*y = 0;
return true;
}
bool CIrrDeviceiOS::activateAccelerometer(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isAccelerometerAvailable)
{
if (!motionManager.isAccelerometerActive)
{
motionManager.accelerometerUpdateInterval = updateInterval;
[motionManager startAccelerometerUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateAccelerometer()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isAccelerometerAvailable)
{
if (motionManager.isAccelerometerActive)
[motionManager stopAccelerometerUpdates];
status = true;
}
return status;
}
bool CIrrDeviceiOS::isAccelerometerActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isAccelerometerActive);
}
bool CIrrDeviceiOS::isAccelerometerAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isAccelerometerAvailable);
}
bool CIrrDeviceiOS::activateGyroscope(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isGyroAvailable)
{
if (!motionManager.isGyroActive)
{
motionManager.gyroUpdateInterval = updateInterval;
[motionManager startGyroUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateGyroscope()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isGyroAvailable)
{
if (motionManager.isGyroActive)
[motionManager stopGyroUpdates];
status = true;
}
return status;
}
bool CIrrDeviceiOS::isGyroscopeActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isGyroActive);
}
bool CIrrDeviceiOS::isGyroscopeAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isGyroAvailable);
}
bool CIrrDeviceiOS::activateDeviceMotion(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isDeviceMotionAvailable)
{
if (!motionManager.isDeviceMotionActive)
{
dataStorage->ReferenceAttitude = nil;
motionManager.deviceMotionUpdateInterval = updateInterval;
[motionManager startDeviceMotionUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateDeviceMotion()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isDeviceMotionAvailable)
{
if (motionManager.isDeviceMotionActive)
{
[motionManager stopDeviceMotionUpdates];
dataStorage->ReferenceAttitude = nil;
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::isDeviceMotionActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isDeviceMotionActive);
}
bool CIrrDeviceiOS::isDeviceMotionAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isDeviceMotionAvailable);
}
E_DEVICE_TYPE CIrrDeviceiOS::getType() const
{
return EIDT_IOS;
}
void CIrrDeviceiOS::createWindow()
{
if (CreationParams.DriverType != video::EDT_NULL)
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
dataStorage->Window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
dataStorage->ViewController = [[HideStatusBarView alloc] init: this];
dataStorage->Window.rootViewController = dataStorage->ViewController;
[dataStorage->Window makeKeyAndVisible];
}
}
void CIrrDeviceiOS::createViewAndDriver()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
switch (CreationParams.DriverType)
{
case video::EDT_OGLES2:
#ifdef _IRR_COMPILE_WITH_OGLES2_
{
EAGLRenderingAPI OpenGLESVersion = kEAGLRenderingAPIOpenGLES2;
// For IOS we use 64bit only and all 64bit ios devices support GLES3 anyway
if (!CreationParams.ForceLegacyDevice)
OpenGLESVersion = kEAGLRenderingAPIOpenGLES3;
else
OpenGLESVersion = kEAGLRenderingAPIOpenGLES2;
dataStorage->m_eagl_context = [[EAGLContext alloc] initWithAPI:OpenGLESVersion];
[EAGLContext setCurrentContext:dataStorage->m_eagl_context];
CIrrViewiOS* view = [[CIrrViewiOS alloc] initWithFrame:[[UIScreen mainScreen] bounds]
forDevice:this forContext:dataStorage->m_eagl_context];
dataStorage->View = view;
m_native_scale = dataStorage->Window.screen.nativeScale;
view.contentScaleFactor = m_native_scale;
// This will initialize the default framebuffer, which bind its valus to GL_FRAMEBUFFER_BINDING
beginScene();
GLint default_fb = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &default_fb);
CreationParams.WindowSize =
{
(u32)view.drawableWidth,
(u32)view.drawableHeight
};
[dataStorage->Window addSubview:view];
VideoDriver = new video::COGLES2Driver(CreationParams, FileSystem, this, default_fb);
if (!VideoDriver)
os::Printer::log("Could not create OpenGL ES 2.x driver.", ELL_ERROR);
}
#else
os::Printer::log("No OpenGL ES 2.x support compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_SOFTWARE:
case video::EDT_BURNINGSVIDEO:
case video::EDT_DIRECT3D9:
case video::EDT_OPENGL:
os::Printer::log("This driver is not available in iOS. Try OpenGL ES.", ELL_ERROR);
break;
case video::EDT_NULL:
VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
break;
default:
os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR);
break;
}
dataStorage->ViewController.view = dataStorage->View;
}
void CIrrDeviceiOS::beginScene()
{
[static_cast<SIrrDeviceiOSDataStorage*>(DataStorage)->View bindDrawable];
}
void CIrrDeviceiOS::swapBuffers()
{
[static_cast<SIrrDeviceiOSDataStorage*>(DataStorage)->View display];
}
std::string CIrrDeviceiOS::getSystemLanguageCode()
{
NSString* language = [[NSLocale preferredLanguages] firstObject];
return std::string([language UTF8String]);
}
void CIrrDeviceiOS::openURLiOS(const char* url)
{
UIApplication* application = [UIApplication sharedApplication];
NSString* url_nsstring = [NSString stringWithCString:url encoding:NSUTF8StringEncoding];
NSURL* nsurl_val = [NSURL URLWithString:url_nsstring];
[application openURL:nsurl_val];
}
}
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
int main(int argc, char** argv)
{
int result = UIApplicationMain(argc, argv, 0, NSStringFromClass([CIrrDelegateiOS class]));
return result;
}
#endif
#endif