bgfx/examples/common/entry/entry_ios.mm

373 lines
8.3 KiB
Text
Raw Normal View History

2013-07-21 17:44:53 -04:00
/*
2015-01-02 17:43:11 -05:00
* Copyright 2011-2015 Branimir Karadzic. All rights reserved.
2013-07-21 17:44:53 -04:00
* License: http://www.opensource.org/licenses/BSD-2-Clause
*/
2013-08-15 00:08:46 -04:00
#include "entry_p.h"
2013-07-21 17:44:53 -04:00
2013-08-15 00:08:46 -04:00
#if ENTRY_CONFIG_USE_NATIVE && BX_PLATFORM_IOS
2013-07-21 17:44:53 -04:00
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <QuartzCore/CAEAGLLayer.h>
2015-08-14 09:12:44 -04:00
#if __IPHONE_8_0 && !TARGET_IPHONE_SIMULATOR // check if sdk/target supports metal
# import <Metal/Metal.h>
# import <QuartzCore/CAMetalLayer.h>
//# define HAS_METAL_SDK
#endif
#include <bgfx/bgfxplatform.h>
2013-08-08 02:11:20 -04:00
2013-07-21 17:44:53 -04:00
#include <bx/uint32_t.h>
#include <bx/thread.h>
namespace entry
{
struct MainThreadEntry
{
int m_argc;
char** m_argv;
static int32_t threadFunc(void* _userData);
};
2014-09-19 13:37:52 -04:00
static WindowHandle s_defaultWindow = { 0 };
2013-07-21 17:44:53 -04:00
struct Context
{
Context(uint32_t _width, uint32_t _height)
2013-07-21 17:44:53 -04:00
{
2014-12-10 16:38:50 -05:00
static const char* argv[1] = { "ios" };
2013-07-21 17:44:53 -04:00
m_mte.m_argc = 1;
m_mte.m_argv = const_cast<char**>(argv);
2014-09-19 13:37:52 -04:00
m_eventQueue.postSizeEvent(s_defaultWindow, _width, _height);
2013-07-21 17:44:53 -04:00
// Prevent render thread creation.
bgfx::renderFrame();
2013-07-21 17:44:53 -04:00
m_thread.init(MainThreadEntry::threadFunc, &m_mte);
}
~Context()
{
m_thread.shutdown();
}
MainThreadEntry m_mte;
bx::Thread m_thread;
EventQueue m_eventQueue;
};
static Context* s_ctx;
int32_t MainThreadEntry::threadFunc(void* _userData)
{
2014-07-07 01:14:20 -04:00
CFBundleRef mainBundle = CFBundleGetMainBundle();
if ( mainBundle != nil )
2014-07-07 01:14:20 -04:00
{
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
if ( resourcesURL != nil )
{
char path[PATH_MAX];
if (CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX) )
{
chdir(path);
}
CFRelease(resourcesURL);
}
2014-07-07 01:14:20 -04:00
}
2014-08-22 22:29:54 -04:00
2013-07-21 17:44:53 -04:00
MainThreadEntry* self = (MainThreadEntry*)_userData;
2013-08-08 01:50:01 -04:00
int32_t result = main(self->m_argc, self->m_argv);
2013-07-21 17:44:53 -04:00
return result;
}
const Event* poll()
{
return s_ctx->m_eventQueue.poll();
}
2014-09-22 22:34:10 -04:00
const Event* poll(WindowHandle _handle)
{
return s_ctx->m_eventQueue.poll(_handle);
}
2013-07-21 17:44:53 -04:00
void release(const Event* _event)
{
s_ctx->m_eventQueue.release(_event);
}
2014-09-22 22:34:10 -04:00
WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title)
{
BX_UNUSED(_x, _y, _width, _height, _flags, _title);
WindowHandle handle = { UINT16_MAX };
return handle;
}
void destroyWindow(WindowHandle _handle)
{
BX_UNUSED(_handle);
}
void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y)
{
BX_UNUSED(_handle, _x, _y);
}
2014-09-19 13:37:52 -04:00
void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height)
2013-07-21 17:44:53 -04:00
{
2014-09-19 13:37:52 -04:00
BX_UNUSED(_handle, _width, _height);
2014-08-05 15:57:52 -04:00
}
2014-09-19 13:37:52 -04:00
void setWindowTitle(WindowHandle _handle, const char* _title)
2014-08-05 15:57:52 -04:00
{
2014-09-19 13:37:52 -04:00
BX_UNUSED(_handle, _title);
2013-07-21 17:44:53 -04:00
}
2014-09-19 13:37:52 -04:00
void toggleWindowFrame(WindowHandle _handle)
2013-07-21 17:44:53 -04:00
{
2014-09-19 13:37:52 -04:00
BX_UNUSED(_handle);
2013-07-21 17:44:53 -04:00
}
void toggleFullscreen(WindowHandle _handle)
{
BX_UNUSED(_handle);
}
2014-09-19 13:37:52 -04:00
void setMouseLock(WindowHandle _handle, bool _lock)
2013-07-21 17:44:53 -04:00
{
2014-09-19 13:37:52 -04:00
BX_UNUSED(_handle, _lock);
2013-07-21 17:44:53 -04:00
}
} // namespace entry
using namespace entry;
2015-08-14 09:12:44 -04:00
#ifdef HAS_METAL_SDK
static id<MTLDevice> m_device = NULL;
#else
static void* m_device = NULL;
#endif
@interface ViewController : UIViewController
@end
@implementation ViewController
- (BOOL)prefersStatusBarHidden
{
return YES;
}
@end
2013-07-21 23:56:12 -04:00
@interface View : UIView
2013-07-21 17:44:53 -04:00
{
CADisplayLink* m_displayLink;
}
@end
2013-07-21 23:56:12 -04:00
@implementation View
2013-07-21 17:44:53 -04:00
+ (Class)layerClass
{
2015-08-14 09:12:44 -04:00
#ifdef HAS_METAL_SDK
Class metalClass = NSClassFromString(@"CAMetalLayer"); //is metal runtime sdk available
if ( metalClass != nil)
{
m_device = MTLCreateSystemDefaultDevice(); // is metal supported on this device (is there a better way to do this - without creating device ?)
if (m_device)
{
[m_device retain];
return metalClass;
}
}
#endif
2013-07-21 17:44:53 -04:00
return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)rect
{
self = [super initWithFrame:rect];
if (nil == self)
{
return nil;
}
2015-08-14 09:12:44 -04:00
bgfx::PlatformData pd;
pd.ndt = NULL;
pd.nwh = self.layer;
pd.context = m_device;
pd.backBuffer = NULL;
pd.backBufferDS = NULL;
bgfx::setPlatformData(pd);
2013-07-21 17:44:53 -04:00
return self;
}
- (void)layoutSubviews
{
2015-07-21 21:15:12 -04:00
uint32_t frameW = (uint32_t)(self.contentScaleFactor * self.frame.size.width);
uint32_t frameH = (uint32_t)(self.contentScaleFactor * self.frame.size.height);
s_ctx->m_eventQueue.postSizeEvent(s_defaultWindow, frameW, frameH);
}
2013-07-21 17:44:53 -04:00
- (void)start
{
if (nil == m_displayLink)
{
m_displayLink = [self.window.screen displayLinkWithTarget:self selector:@selector(renderFrame)];
2013-12-07 13:19:54 -05:00
//[m_displayLink setFrameInterval:1];
//[m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
2014-08-22 22:29:54 -04:00
// [m_displayLink addToRunLoop:[NSRunLoop currentRunLoop]];
2013-12-20 19:41:53 -05:00
[m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
2013-07-21 17:44:53 -04:00
}
}
- (void)stop
{
if (nil != m_displayLink)
{
[m_displayLink invalidate];
m_displayLink = nil;
}
}
- (void)renderFrame
{
bgfx::renderFrame();
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
2014-08-22 22:29:54 -04:00
BX_UNUSED(touches);
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self];
2014-09-19 13:37:52 -04:00
s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0);
s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0, MouseButton::Left, true);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
2014-08-22 22:29:54 -04:00
BX_UNUSED(touches);
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self];
2014-09-19 13:37:52 -04:00
s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0, MouseButton::Left, false);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
2014-08-22 22:29:54 -04:00
BX_UNUSED(touches);
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self];
2014-09-19 13:37:52 -04:00
s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0);
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
2014-08-22 22:29:54 -04:00
BX_UNUSED(touches);
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self];
2014-09-19 13:37:52 -04:00
s_ctx->m_eventQueue.postMouseEvent(s_defaultWindow, touchLocation.x, touchLocation.y, 0, MouseButton::Left, false);
}
2013-07-21 17:44:53 -04:00
@end
@interface AppDelegate : UIResponder<UIApplicationDelegate>
{
UIWindow* m_window;
2013-07-21 23:56:12 -04:00
View* m_view;
2013-07-21 17:44:53 -04:00
}
@property (nonatomic, retain) UIWindow* m_window;
2013-07-21 23:56:12 -04:00
@property (nonatomic, retain) View* m_view;
2013-07-21 17:44:53 -04:00
@end
@implementation AppDelegate
@synthesize m_window;
@synthesize m_view;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
2013-12-07 13:19:54 -05:00
BX_UNUSED(application, launchOptions);
2013-07-21 17:44:53 -04:00
CGRect rect = [ [UIScreen mainScreen] bounds];
m_window = [ [UIWindow alloc] initWithFrame: rect];
2013-07-21 23:56:12 -04:00
m_view = [ [View alloc] initWithFrame: rect];
2013-07-21 17:44:53 -04:00
[m_window addSubview: m_view];
2015-08-14 09:12:44 -04:00
UIViewController *viewController = [[ViewController alloc] init];
viewController.view = m_view;
[m_window setRootViewController:viewController];
[m_window makeKeyAndVisible];
2013-07-21 17:44:53 -04:00
[m_window makeKeyAndVisible];
2014-08-22 22:29:54 -04:00
//float scaleFactor = [[UIScreen mainScreen] scale]; // should use this, but ui is too small on ipad retina
float scaleFactor = 1.0f;
[m_view setContentScaleFactor: scaleFactor ];
2013-07-21 17:44:53 -04:00
s_ctx = new Context((uint32_t)(scaleFactor*rect.size.width), (uint32_t)(scaleFactor*rect.size.height));
2013-07-21 17:44:53 -04:00
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
2013-12-07 13:19:54 -05:00
BX_UNUSED(application);
s_ctx->m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillSuspend);
2013-07-21 17:44:53 -04:00
[m_view stop];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
2013-12-07 13:19:54 -05:00
BX_UNUSED(application);
s_ctx->m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidSuspend);
2013-07-21 17:44:53 -04:00
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
2013-12-07 13:19:54 -05:00
BX_UNUSED(application);
s_ctx->m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillResume);
2013-07-21 17:44:53 -04:00
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
2013-12-07 13:19:54 -05:00
BX_UNUSED(application);
s_ctx->m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidResume);
2013-07-21 17:44:53 -04:00
[m_view start];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
2013-12-07 13:19:54 -05:00
BX_UNUSED(application);
2013-07-21 17:44:53 -04:00
[m_view stop];
}
- (void)dealloc
{
[m_window release];
[m_view release];
[super dealloc];
}
@end
int main(int _argc, char* _argv[])
{
NSAutoreleasePool* pool = [ [NSAutoreleasePool alloc] init];
int exitCode = UIApplicationMain(_argc, _argv, @"UIApplication", NSStringFromClass([AppDelegate class]) );
[pool release];
return exitCode;
}
#endif // BX_PLATFORM_IOS