2025-01-22 16:18:30 +01:00

451 lines
12 KiB
Objective-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