451 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			451 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | #import "GLView.h"
 | ||
|  | 
 | ||
|  | #include <kinc/graphics5/graphics.h>
 | ||
|  | #include <kinc/graphics5/rendertarget.h>
 | ||
|  | #include <kinc/input/acceleration.h>
 | ||
|  | #include <kinc/input/keyboard.h>
 | ||
|  | #include <kinc/input/mouse.h>
 | ||
|  | #include <kinc/input/pen.h>
 | ||
|  | #include <kinc/input/rotation.h>
 | ||
|  | #include <kinc/input/surface.h>
 | ||
|  | #include <kinc/system.h>
 | ||
|  | 
 | ||
|  | #ifdef KINC_OPENGL
 | ||
|  | #include <kinc/backend/graphics4/OpenGLWindow.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | static const int touchmaxcount = 20; | ||
|  | static void *touches[touchmaxcount]; | ||
|  | 
 | ||
|  | static void initTouches(void) { | ||
|  | 	for (int i = 0; i < touchmaxcount; ++i) { | ||
|  | 		touches[i] = NULL; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | static int getTouchIndex(void *touch) { | ||
|  | 	for (int i = 0; i < touchmaxcount; ++i) { | ||
|  | 		if (touches[i] == touch) | ||
|  | 			return i; | ||
|  | 	} | ||
|  | 	return -1; | ||
|  | } | ||
|  | 
 | ||
|  | static int addTouch(void *touch) { | ||
|  | 	for (int i = 0; i < touchmaxcount; ++i) { | ||
|  | 		if (touches[i] == NULL) { | ||
|  | 			touches[i] = touch; | ||
|  | 			return i; | ||
|  | 		} | ||
|  | 	} | ||
|  | 	return -1; | ||
|  | } | ||
|  | 
 | ||
|  | static int removeTouch(void *touch) { | ||
|  | 	for (int i = 0; i < touchmaxcount; ++i) { | ||
|  | 		if (touches[i] == touch) { | ||
|  | 			touches[i] = NULL; | ||
|  | 			return i; | ||
|  | 		} | ||
|  | 	} | ||
|  | 	return -1; | ||
|  | } | ||
|  | 
 | ||
|  | static GLint backingWidth, backingHeight; | ||
|  | 
 | ||
|  | int kinc_window_width(int window) { | ||
|  | 	return backingWidth; | ||
|  | } | ||
|  | 
 | ||
|  | int kinc_window_height(int window) { | ||
|  | 	return backingHeight; | ||
|  | } | ||
|  | 
 | ||
|  | @implementation GLView | ||
|  | 
 | ||
|  | #ifdef KINC_METAL
 | ||
|  | + (Class)layerClass { | ||
|  | 	return [CAMetalLayer class]; | ||
|  | } | ||
|  | #else
 | ||
|  | + (Class)layerClass { | ||
|  | 	return [CAEAGLLayer class]; | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef KINC_OPENGL
 | ||
|  | extern int kinc_ios_gl_framebuffer; | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef KINC_METAL
 | ||
|  | - (id)initWithFrame:(CGRect)frame { | ||
|  | 	self = [super initWithFrame:(CGRect)frame]; | ||
|  | 	self.contentScaleFactor = [UIScreen mainScreen].scale; | ||
|  | 
 | ||
|  | 	backingWidth = frame.size.width * self.contentScaleFactor; | ||
|  | 	backingHeight = frame.size.height * self.contentScaleFactor; | ||
|  | 
 | ||
|  | 	initTouches(); | ||
|  | 
 | ||
|  | 	device = MTLCreateSystemDefaultDevice(); | ||
|  | 	commandQueue = [device newCommandQueue]; | ||
|  | 	library = [device newDefaultLibrary]; | ||
|  | 
 | ||
|  | 	CAMetalLayer *metalLayer = (CAMetalLayer *)self.layer; | ||
|  | 
 | ||
|  | 	metalLayer.device = device; | ||
|  | 	metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; | ||
|  | 	metalLayer.framebufferOnly = YES; | ||
|  | 	// metalLayer.presentsWithTransaction = YES;
 | ||
|  | 
 | ||
|  | 	metalLayer.opaque = YES; | ||
|  | 	metalLayer.backgroundColor = nil; | ||
|  | 
 | ||
|  | 	return self; | ||
|  | } | ||
|  | #else
 | ||
|  | - (id)initWithFrame:(CGRect)frame { | ||
|  | 	self = [super initWithFrame:(CGRect)frame]; | ||
|  | 	self.contentScaleFactor = [UIScreen mainScreen].scale; | ||
|  | 
 | ||
|  | 	backingWidth = frame.size.width * self.contentScaleFactor; | ||
|  | 	backingHeight = frame.size.height * self.contentScaleFactor; | ||
|  | 
 | ||
|  | 	initTouches(); | ||
|  | 
 | ||
|  | 	CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; | ||
|  | 
 | ||
|  | 	eaglLayer.opaque = YES; | ||
|  | 	eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, | ||
|  | 	                                                                          kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; | ||
|  | 
 | ||
|  | 	context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; | ||
|  | 
 | ||
|  | 	if (!context || ![EAGLContext setCurrentContext:context]) { | ||
|  | 		//[self release];
 | ||
|  | 		return nil; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	glGenFramebuffersOES(1, &defaultFramebuffer); | ||
|  | 	glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer); | ||
|  | 	kinc_ios_gl_framebuffer = defaultFramebuffer; | ||
|  | 
 | ||
|  | 	glGenRenderbuffersOES(1, &colorRenderbuffer); | ||
|  | 	glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); | ||
|  | 	glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer); | ||
|  | 
 | ||
|  | 	glGenRenderbuffersOES(1, &depthStencilRenderbuffer); | ||
|  | 	glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthStencilRenderbuffer); | ||
|  | 	glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthStencilRenderbuffer); | ||
|  | 	glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthStencilRenderbuffer); | ||
|  | 
 | ||
|  | 	// Start acceletometer
 | ||
|  | 	hasAccelerometer = false; | ||
|  | #ifndef KINC_TVOS
 | ||
|  | 	motionManager = [[CMMotionManager alloc] init]; | ||
|  | 	if ([motionManager isAccelerometerAvailable]) { | ||
|  | 		motionManager.accelerometerUpdateInterval = 0.033; | ||
|  | 		[motionManager startAccelerometerUpdates]; | ||
|  | 		hasAccelerometer = true; | ||
|  | 	} | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifndef KINC_TVOS
 | ||
|  | 	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onKeyboardHide:) name:UIKeyboardWillHideNotification object:nil]; | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 	return self; | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef KINC_METAL
 | ||
|  | - (void)begin { | ||
|  | } | ||
|  | #else
 | ||
|  | - (void)begin { | ||
|  | 	[EAGLContext setCurrentContext:context]; | ||
|  | 	// glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
 | ||
|  | 	// glViewport(0, 0, backingWidth, backingHeight);
 | ||
|  | 
 | ||
|  | #ifndef KINC_TVOS
 | ||
|  | 	// Accelerometer updates
 | ||
|  | 	if (hasAccelerometer) { | ||
|  | 
 | ||
|  | 		CMAcceleration acc = motionManager.accelerometerData.acceleration; | ||
|  | 
 | ||
|  | 		if (acc.x != lastAccelerometerX || acc.y != lastAccelerometerY || acc.z != lastAccelerometerZ) { | ||
|  | 
 | ||
|  | 			kinc_internal_on_acceleration(acc.x, acc.y, acc.z); | ||
|  | 
 | ||
|  | 			lastAccelerometerX = acc.x; | ||
|  | 			lastAccelerometerY = acc.y; | ||
|  | 			lastAccelerometerZ = acc.z; | ||
|  | 		} | ||
|  | 	} | ||
|  | #endif
 | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef KINC_METAL
 | ||
|  | - (void)end { | ||
|  | } | ||
|  | #else
 | ||
|  | - (void)end { | ||
|  | 	glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); | ||
|  | 	[context presentRenderbuffer:GL_RENDERBUFFER_OES]; // crash at end
 | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | void kinc_internal_call_resize_callback(int window, int width, int height); | ||
|  | 
 | ||
|  | #ifdef KINC_METAL
 | ||
|  | - (void)layoutSubviews { | ||
|  | 	backingWidth = self.frame.size.width * self.contentScaleFactor; | ||
|  | 	backingHeight = self.frame.size.height * self.contentScaleFactor; | ||
|  | 
 | ||
|  | 	CAMetalLayer *metalLayer = (CAMetalLayer *)self.layer; | ||
|  | 	metalLayer.drawableSize = CGSizeMake(backingWidth, backingHeight); | ||
|  | 
 | ||
|  | 	kinc_internal_call_resize_callback(0, backingWidth, backingHeight); | ||
|  | } | ||
|  | #else
 | ||
|  | - (void)layoutSubviews { | ||
|  | 	glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); | ||
|  | 	[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer *)self.layer]; | ||
|  | 
 | ||
|  | 	glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); | ||
|  | 	glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); | ||
|  | 
 | ||
|  | 	printf("backingWitdh/Height: %i, %i\n", backingWidth, backingHeight); | ||
|  | 
 | ||
|  | 	glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthStencilRenderbuffer); | ||
|  | 	glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH24_STENCIL8_OES, backingWidth, backingHeight); | ||
|  | 
 | ||
|  | 	if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { | ||
|  | 		NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	kinc_internal_call_resize_callback(0, backingWidth, backingHeight); | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef KINC_METAL
 | ||
|  | - (void)dealloc { | ||
|  | } | ||
|  | #else
 | ||
|  | - (void)dealloc { | ||
|  | 	if (defaultFramebuffer) { | ||
|  | 		glDeleteFramebuffersOES(1, &defaultFramebuffer); | ||
|  | 		defaultFramebuffer = 0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if (colorRenderbuffer) { | ||
|  | 		glDeleteRenderbuffersOES(1, &colorRenderbuffer); | ||
|  | 		colorRenderbuffer = 0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if (depthStencilRenderbuffer) { | ||
|  | 		glDeleteRenderbuffersOES(1, &depthStencilRenderbuffer); | ||
|  | 		depthStencilRenderbuffer = 0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if ([EAGLContext currentContext] == context) | ||
|  | 		[EAGLContext setCurrentContext:nil]; | ||
|  | 
 | ||
|  | 	//[context release];
 | ||
|  | 	context = nil; | ||
|  | 
 | ||
|  | 	//[super dealloc];
 | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { | ||
|  | 	for (UITouch *touch in touches) { | ||
|  | 		int index = getTouchIndex((__bridge void *)touch); | ||
|  | 		if (index == -1) | ||
|  | 			index = addTouch((__bridge void *)touch); | ||
|  | 		if (index >= 0) { | ||
|  | 			CGPoint point = [touch locationInView:self]; | ||
|  | 			float x = point.x * self.contentScaleFactor; | ||
|  | 			float y = point.y * self.contentScaleFactor; | ||
|  | 			if (index == 0) { | ||
|  | 				kinc_internal_mouse_trigger_press(0, event.buttonMask == UIEventButtonMaskSecondary ? 1 : 0, x, y); | ||
|  | 			} | ||
|  | 			kinc_internal_surface_trigger_touch_start(index, x, y); | ||
|  | 
 | ||
|  | 			if (touch.type == UITouchTypePencil) { | ||
|  | 				kinc_internal_pen_trigger_press(0, x, y, 0.0); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { | ||
|  | 	for (UITouch *touch in touches) { | ||
|  | 		int index = getTouchIndex((__bridge void *)touch); | ||
|  | 		if (index >= 0) { | ||
|  | 			CGPoint point = [touch locationInView:self]; | ||
|  | 			float x = point.x * self.contentScaleFactor; | ||
|  | 			float y = point.y * self.contentScaleFactor; | ||
|  | 			if (index == 0) { | ||
|  | 				kinc_internal_mouse_trigger_move(0, x, y); | ||
|  | 			} | ||
|  | 			kinc_internal_surface_trigger_move(index, x, y); | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | - (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches { | ||
|  | 	for (UITouch *touch in touches) { | ||
|  | 		if (touch.type == UITouchTypePencil) { | ||
|  | 			CGPoint point = [touch locationInView:self]; | ||
|  | 			float x = point.x * self.contentScaleFactor; | ||
|  | 			float y = point.y * self.contentScaleFactor; | ||
|  | 			kinc_internal_pen_trigger_move(0, x, y, touch.force); | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { | ||
|  | 	for (UITouch *touch in touches) { | ||
|  | 		int index = removeTouch((__bridge void *)touch); | ||
|  | 		if (index >= 0) { | ||
|  | 			CGPoint point = [touch locationInView:self]; | ||
|  | 			float x = point.x * self.contentScaleFactor; | ||
|  | 			float y = point.y * self.contentScaleFactor; | ||
|  | 			if (index == 0) { | ||
|  | 				kinc_internal_mouse_trigger_release(0, event.buttonMask == UIEventButtonMaskSecondary ? 1 : 0, x, y); | ||
|  | 			} | ||
|  | 			kinc_internal_surface_trigger_touch_end(index, x, y); | ||
|  | 
 | ||
|  | 			if (touch.type == UITouchTypePencil) { | ||
|  | 				kinc_internal_pen_trigger_release(0, x, y, 0.0); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { | ||
|  | 	for (UITouch *touch in touches) { | ||
|  | 		int index = removeTouch((__bridge void *)touch); | ||
|  | 		if (index >= 0) { | ||
|  | 			CGPoint point = [touch locationInView:self]; | ||
|  | 			float x = point.x * self.contentScaleFactor; | ||
|  | 			float y = point.y * self.contentScaleFactor; | ||
|  | 			if (index == 0) { | ||
|  | 				kinc_internal_mouse_trigger_release(0, event.buttonMask == UIEventButtonMaskSecondary ? 1 : 0, x, y); | ||
|  | 			} | ||
|  | 			kinc_internal_surface_trigger_touch_end(index, x, y); | ||
|  | 
 | ||
|  | 			if (touch.type == UITouchTypePencil) { | ||
|  | 				kinc_internal_pen_trigger_release(0, x, y, 0.0); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | static NSString *keyboardstring; | ||
|  | static UITextField *myTextField = NULL; | ||
|  | static bool shiftDown = false; | ||
|  | 
 | ||
|  | - (void)showKeyboard { | ||
|  | 	[self becomeFirstResponder]; | ||
|  | } | ||
|  | 
 | ||
|  | - (void)hideKeyboard { | ||
|  | 	[self resignFirstResponder]; | ||
|  | } | ||
|  | 
 | ||
|  | - (BOOL)hasText { | ||
|  | 	return YES; | ||
|  | } | ||
|  | 
 | ||
|  | - (void)insertText:(NSString *)text { | ||
|  | 	if ([text length] == 1) { | ||
|  | 		unichar ch = [text characterAtIndex:[text length] - 1]; | ||
|  | 		if (ch == 8212) | ||
|  | 			ch = '_'; | ||
|  | 		if (ch == L'\n') { | ||
|  | 			kinc_internal_keyboard_trigger_key_down(KINC_KEY_RETURN); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(KINC_KEY_RETURN); | ||
|  | 			return; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (ch == L'.') { | ||
|  | 			kinc_internal_keyboard_trigger_key_down(KINC_KEY_PERIOD); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(KINC_KEY_PERIOD); | ||
|  | 		} | ||
|  | 		else if (ch == L'%') { | ||
|  | 			kinc_internal_keyboard_trigger_key_down(KINC_KEY_PERCENT); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(KINC_KEY_PERCENT); | ||
|  | 		} | ||
|  | 		else if (ch == L'(') { | ||
|  | 			kinc_internal_keyboard_trigger_key_down(KINC_KEY_OPEN_PAREN); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(KINC_KEY_OPEN_PAREN); | ||
|  | 		} | ||
|  | 		else if (ch == L'&') { | ||
|  | 			kinc_internal_keyboard_trigger_key_down(KINC_KEY_AMPERSAND); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(KINC_KEY_AMPERSAND); | ||
|  | 		} | ||
|  | 		else if (ch == L'$') { | ||
|  | 			kinc_internal_keyboard_trigger_key_down(KINC_KEY_DOLLAR); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(KINC_KEY_DOLLAR); | ||
|  | 		} | ||
|  | 		else if (ch == L'#') { | ||
|  | 			kinc_internal_keyboard_trigger_key_down(KINC_KEY_HASH); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(KINC_KEY_HASH); | ||
|  | 		} | ||
|  | 		else if (ch >= L'a' && ch <= L'z') { | ||
|  | 			if (shiftDown) { | ||
|  | 				kinc_internal_keyboard_trigger_key_up(KINC_KEY_SHIFT); | ||
|  | 				shiftDown = false; | ||
|  | 			} | ||
|  | 			kinc_internal_keyboard_trigger_key_down(ch + KINC_KEY_A - L'a'); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(ch + KINC_KEY_A - L'a'); | ||
|  | 		} | ||
|  | 		else { | ||
|  | 			if (!shiftDown) { | ||
|  | 				kinc_internal_keyboard_trigger_key_down(KINC_KEY_SHIFT); | ||
|  | 				shiftDown = true; | ||
|  | 			} | ||
|  | 			kinc_internal_keyboard_trigger_key_down(ch + KINC_KEY_A - L'A'); | ||
|  | 			kinc_internal_keyboard_trigger_key_up(ch + KINC_KEY_A - L'A'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		kinc_internal_keyboard_trigger_key_press(ch); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | - (void)deleteBackward { | ||
|  | 	kinc_internal_keyboard_trigger_key_down(KINC_KEY_BACKSPACE); | ||
|  | 	kinc_internal_keyboard_trigger_key_up(KINC_KEY_BACKSPACE); | ||
|  | } | ||
|  | 
 | ||
|  | - (BOOL)canBecomeFirstResponder { | ||
|  | 	return YES; | ||
|  | } | ||
|  | 
 | ||
|  | - (void)onKeyboardHide:(NSNotification *)notification { | ||
|  | 	kinc_keyboard_hide(); | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef KINC_METAL
 | ||
|  | - (CAMetalLayer *)metalLayer { | ||
|  | 	return (CAMetalLayer *)self.layer; | ||
|  | } | ||
|  | 
 | ||
|  | - (id<MTLDevice>)metalDevice { | ||
|  | 	return device; | ||
|  | } | ||
|  | 
 | ||
|  | - (id<MTLLibrary>)metalLibrary { | ||
|  | 	return library; | ||
|  | } | ||
|  | 
 | ||
|  | - (id<MTLCommandQueue>)metalQueue { | ||
|  | 	return commandQueue; | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | @end |