- Pressing return will send the Enter key to game, but not dismiss the keyboard since some input boxes in game could be multi-line. - Press Keyboard (hide keyboard button) no longer trigger Enter key.
367 lines
13 KiB
Objective-C
367 lines
13 KiB
Objective-C
#import "SurfaceViewController.h"
|
|
#import "egl_bridge_ios.h"
|
|
#import "ios_uikit_bridge.h"
|
|
|
|
#include "glfw_keycodes.h"
|
|
#include "utils.h"
|
|
|
|
#include "EGL/egl.h"
|
|
|
|
#include "GLES2/gl2.h"
|
|
#include "GLES2/gl2ext.h"
|
|
|
|
#define ADD_BUTTON(NAME, KEY, RECT) \
|
|
UIButton *button_##KEY = [UIButton buttonWithType:UIButtonTypeRoundedRect]; \
|
|
button_##KEY.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth; \
|
|
[button_##KEY setTitle:NAME forState:UIControlStateNormal]; \
|
|
button_##KEY.frame = RECT; \
|
|
[button_##KEY addTarget:self action:@selector(executebtn_##KEY##_down) forControlEvents:UIControlEventTouchDown]; \
|
|
[button_##KEY addTarget:self action:@selector(executebtn_##KEY##_up) forControlEvents:UIControlEventTouchUpInside]; \
|
|
button_##KEY.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.3f]; \
|
|
button_##KEY.tintColor = [UIColor whiteColor]; \
|
|
[self.view addSubview:button_##KEY];
|
|
|
|
#define ADD_BUTTON_VISIBLE(NAME, KEY, RECT) \
|
|
ADD_BUTTON(NAME, KEY, RECT); \
|
|
togglableVisibleButtons[++togglableVisibleButtonIndex] = button_##KEY;
|
|
|
|
|
|
#define ADD_BUTTON_DEF(KEY) \
|
|
- (void)executebtn_##KEY##_down { \
|
|
[self executebtn_##KEY:1]; \
|
|
} \
|
|
- (void)executebtn_##KEY##_up { \
|
|
[self executebtn_##KEY:0]; \
|
|
} \
|
|
- (void)executebtn_##KEY:(int)held
|
|
|
|
#define ADD_BUTTON_DEF_KEY(KEY, KEYCODE) \
|
|
ADD_BUTTON_DEF(KEY) { \
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, KEYCODE, 0, held, 0); \
|
|
}
|
|
|
|
#define BTN_RECT 80.0, 30.0
|
|
#define BTN_SQUARE 50.0, 50.0
|
|
|
|
int togglableVisibleButtonIndex = -1;
|
|
UIButton* togglableVisibleButtons[100];
|
|
UIView *touchView;
|
|
UITextField *inputView;
|
|
BOOL shouldTriggerClick = NO;
|
|
|
|
// TODO: key modifiers impl
|
|
|
|
@interface SurfaceViewController ()<UITextFieldDelegate> {
|
|
}
|
|
|
|
@property (strong, nonatomic) MGLContext *context;
|
|
|
|
- (void)setupGL;
|
|
|
|
@end
|
|
|
|
@implementation SurfaceViewController
|
|
|
|
- (void)viewDidLoad
|
|
{
|
|
[super viewDidLoad];
|
|
|
|
CGRect screenBounds = [[UIScreen mainScreen] bounds];
|
|
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
|
|
|
int width = (int) roundf(screenBounds.size.width);
|
|
int height = (int) roundf(screenBounds.size.height);
|
|
|
|
savedWidth = roundf(width * screenScale);
|
|
savedHeight = roundf(height * screenScale);
|
|
|
|
touchView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
|
|
|
|
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(surfaceOnClick:)];
|
|
tapGesture.numberOfTapsRequired = 1;
|
|
tapGesture.numberOfTouchesRequired = 1;
|
|
tapGesture.cancelsTouchesInView = NO;
|
|
[touchView addGestureRecognizer:tapGesture];
|
|
|
|
UILongPressGestureRecognizer *longpressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(surfaceOnLongpress:)];
|
|
[touchView addGestureRecognizer:longpressGesture];
|
|
|
|
[self.view addSubview:touchView];
|
|
|
|
inputView = [[UITextField alloc] initWithFrame:CGRectMake(5 * 3 + 80 * 2, 5, BTN_RECT)];
|
|
inputView.delegate = self;
|
|
inputView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0f];
|
|
[inputView addTarget:self action:@selector(inputViewDidChange) forControlEvents:UIControlEventEditingChanged];
|
|
[inputView addTarget:self action:@selector(inputViewDidClick) forControlEvents:UIControlEventTouchDown];
|
|
|
|
// Custom button
|
|
// ADD_BUTTON(@"F1", f1, CGRectMake(5, 5, width, height));
|
|
|
|
ADD_BUTTON(@"GUI", special_togglebtn, CGRectMake(5, height - 5 - 50, BTN_SQUARE));
|
|
ADD_BUTTON_VISIBLE(@"Keyboard", special_keyboard, CGRectMake(5 * 3 + 80 * 2, 5, BTN_RECT));
|
|
|
|
ADD_BUTTON_VISIBLE(@"Pri", special_mouse_pri, CGRectMake(5, height - 5 * 3 - 50 * 3, BTN_SQUARE));
|
|
ADD_BUTTON_VISIBLE(@"Sec", special_mouse_sec, CGRectMake(5 * 3 + 50 * 2, height - 5 * 3 - 50 * 3, BTN_SQUARE));
|
|
|
|
ADD_BUTTON_VISIBLE(@"Debug", f3, CGRectMake(5, 5, BTN_RECT));
|
|
ADD_BUTTON_VISIBLE(@"Chat", t, CGRectMake(5 * 2 + 80, 5, BTN_RECT));
|
|
ADD_BUTTON_VISIBLE(@"Tab", tab, CGRectMake(5 * 4 + 80 * 3, 5, BTN_RECT));
|
|
ADD_BUTTON_VISIBLE(@"Opti-Zoom", c, CGRectMake(5 * 5 + 80 * 4, 5, BTN_RECT));
|
|
ADD_BUTTON_VISIBLE(@"Offhand", f, CGRectMake(5 * 6 + 80 * 5, 5, BTN_RECT));
|
|
ADD_BUTTON_VISIBLE(@"3rd", f5, CGRectMake(5, 5 * 2 + 30.0, BTN_RECT));
|
|
|
|
ADD_BUTTON_VISIBLE(@"▲", w, CGRectMake(5 * 2 + 50, height - 5 * 3 - 50 * 3, BTN_SQUARE));
|
|
ADD_BUTTON_VISIBLE(@"◀", a, CGRectMake(5, height - 5 * 2 - 50 * 2, BTN_SQUARE));
|
|
ADD_BUTTON_VISIBLE(@"▼", s, CGRectMake(5 * 2 + 50, height - 5 - 50, BTN_SQUARE));
|
|
ADD_BUTTON_VISIBLE(@"▶", d, CGRectMake(5 * 3 + 50 * 2, height - 5 * 2 - 50 * 2, BTN_SQUARE));
|
|
ADD_BUTTON_VISIBLE(@"◇", left_shift, CGRectMake(5 * 2 + 50, height - 5 * 2 - 50 * 2, BTN_SQUARE));
|
|
ADD_BUTTON_VISIBLE(@"Inv", e, CGRectMake(5 * 3 + 50 * 2, height - 5 - 50, BTN_SQUARE));
|
|
|
|
ADD_BUTTON_VISIBLE(@"⬛", space, CGRectMake(width - 5 * 2 - 50 * 2, height - 5 * 2 - 50 * 2, BTN_SQUARE));
|
|
|
|
ADD_BUTTON_VISIBLE(@"Esc", escape, CGRectMake(width - 5 - 80, height - 5 - 30, BTN_RECT));
|
|
|
|
// ADD_BUTTON_VISIBLE(@"Fullscreen", f11, CGRectMake(width - 5 - 80, 5, BTN_RECT));
|
|
|
|
[self.view addSubview:inputView];
|
|
[inputView becomeFirstResponder];
|
|
|
|
[self executebtn_special_togglebtn:0];
|
|
|
|
viewController = self;
|
|
|
|
MGLKView *view = glView = (MGLKView *) self.view;
|
|
view.drawableDepthFormat = MGLDrawableDepthFormat24;
|
|
view.enableSetNeedsDisplay = YES;
|
|
|
|
// Init GLES
|
|
self.context = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES3];
|
|
|
|
if (!self.context) {
|
|
self.context = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES2];
|
|
}
|
|
|
|
if (!self.context) {
|
|
NSLog(@"Failed to create ES context");
|
|
}
|
|
|
|
view.context = self.context;
|
|
#ifndef USE_EGL
|
|
glContext = self.context;
|
|
#endif
|
|
|
|
[MGLContext setCurrentContext:self.context];
|
|
|
|
[self setupGL];
|
|
}
|
|
|
|
- (void)surfaceOnClick:(UITapGestureRecognizer *)sender {
|
|
if (sender.state == UIGestureRecognizerStateRecognized &&
|
|
shouldTriggerClick == YES) {
|
|
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
|
CGPoint location = [sender locationInView:[sender.view superview]];
|
|
int hotbarItem = callback_SurfaceViewController_touchHotbar(location.x * screenScale, location.y * screenScale);
|
|
|
|
if (hotbarItem == -1) {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL,
|
|
isGrabbing == JNI_TRUE ? GLFW_MOUSE_BUTTON_RIGHT : GLFW_MOUSE_BUTTON_LEFT, 1, 0);
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL,
|
|
isGrabbing == JNI_TRUE ? GLFW_MOUSE_BUTTON_RIGHT : GLFW_MOUSE_BUTTON_LEFT, 0, 0);
|
|
} else {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, hotbarItem, 0, 1, 0);
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, hotbarItem, 0, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void)surfaceOnLongpress:(UILongPressGestureRecognizer *)sender
|
|
{
|
|
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
|
CGPoint location = [sender locationInView:[sender.view superview]];
|
|
int hotbarItem = callback_SurfaceViewController_touchHotbar(location.x * screenScale, location.y * screenScale);
|
|
if (sender.state == UIGestureRecognizerStateBegan) {
|
|
if (hotbarItem == -1) {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL, GLFW_MOUSE_BUTTON_LEFT, 1, 0);
|
|
} else {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_Q, 0, 1, 0);
|
|
}
|
|
} else if (sender.state == UIGestureRecognizerStateChanged) {
|
|
if (hotbarItem == -1) {
|
|
[self sendTouchPoint:location withEvent:ACTION_MOVE];
|
|
}
|
|
} else {
|
|
if (sender.state == UIGestureRecognizerStateCancelled
|
|
|| sender.state == UIGestureRecognizerStateFailed
|
|
|| sender.state == UIGestureRecognizerStateEnded)
|
|
{
|
|
if (hotbarItem == -1) {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL, GLFW_MOUSE_BUTTON_LEFT, 0, 0);
|
|
} else {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_Q, 0, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void)inputViewDidChange {
|
|
if ([inputView.text length] <= 1) {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_BACKSPACE, 0, 1, 0);
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_BACKSPACE, 0, 0, 0);
|
|
} else {
|
|
NSString *newText = [inputView.text substringFromIndex:2];
|
|
int charLength = [newText length];
|
|
for (int i = 0; i < charLength; i++) {
|
|
// Directly convert unichar to jchar which both are in UTF-16 encoding.
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendCharMods(NULL, NULL, (jchar) [newText characterAtIndex:i] /* charText[i] */, /* mods */ 0);
|
|
}
|
|
}
|
|
|
|
// Reset to default value
|
|
inputView.text = @" ";
|
|
}
|
|
|
|
-(void)inputViewDidClick {
|
|
// Zero the input field so user will no longer able to select text inside.
|
|
inputView.alpha = 0.0f;
|
|
inputView.text = @" ";
|
|
}
|
|
|
|
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_ENTER, 0, 1, 0);
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(NULL, NULL, GLFW_KEY_ENTER, 0, 0, 0);
|
|
return YES;
|
|
}
|
|
|
|
int currentVisibility = 1;
|
|
ADD_BUTTON_DEF(special_togglebtn) {
|
|
if (held == 0) {
|
|
currentVisibility = !currentVisibility;
|
|
for (int i = 0; i < togglableVisibleButtonIndex + 1; i++) {
|
|
togglableVisibleButtons[i].hidden = currentVisibility;
|
|
}
|
|
|
|
inputView.hidden = currentVisibility;
|
|
}
|
|
}
|
|
|
|
ADD_BUTTON_DEF(special_keyboard) {
|
|
if (held == 0) {
|
|
[inputView resignFirstResponder];
|
|
inputView.alpha = 1.0f;
|
|
inputView.text = @"";
|
|
}
|
|
}
|
|
|
|
ADD_BUTTON_DEF(special_mouse_pri) {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL, GLFW_MOUSE_BUTTON_LEFT, held, 0);
|
|
}
|
|
|
|
ADD_BUTTON_DEF(special_mouse_sec) {
|
|
Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(NULL, NULL, GLFW_MOUSE_BUTTON_RIGHT, held, 0);
|
|
}
|
|
|
|
ADD_BUTTON_DEF_KEY(f3, GLFW_KEY_F3)
|
|
ADD_BUTTON_DEF_KEY(f5, GLFW_KEY_F5)
|
|
// ADD_BUTTON_DEF_KEY(f11, GLFW_KEY_F11)
|
|
ADD_BUTTON_DEF_KEY(t, GLFW_KEY_T)
|
|
ADD_BUTTON_DEF_KEY(c, GLFW_KEY_C)
|
|
ADD_BUTTON_DEF_KEY(f, GLFW_KEY_F)
|
|
ADD_BUTTON_DEF_KEY(tab, GLFW_KEY_TAB)
|
|
|
|
ADD_BUTTON_DEF_KEY(w, GLFW_KEY_W)
|
|
ADD_BUTTON_DEF_KEY(a, GLFW_KEY_A)
|
|
ADD_BUTTON_DEF_KEY(s, GLFW_KEY_S)
|
|
ADD_BUTTON_DEF_KEY(d, GLFW_KEY_D)
|
|
ADD_BUTTON_DEF_KEY(e, GLFW_KEY_E)
|
|
|
|
ADD_BUTTON_DEF_KEY(left_shift, GLFW_KEY_LEFT_SHIFT)
|
|
|
|
ADD_BUTTON_DEF_KEY(space, GLFW_KEY_SPACE)
|
|
ADD_BUTTON_DEF_KEY(escape, GLFW_KEY_ESCAPE)
|
|
|
|
- (void)dealloc
|
|
{
|
|
if ([MGLContext currentContext] == self.context) {
|
|
[MGLContext setCurrentContext:nil];
|
|
}
|
|
}
|
|
|
|
- (void)setupGL
|
|
{
|
|
[MGLContext setCurrentContext:self.context];
|
|
|
|
CGRect screenBounds = [[UIScreen mainScreen] bounds];
|
|
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
|
|
|
int width = (int) roundf(screenBounds.size.width * screenScale);
|
|
int height = (int) roundf(screenBounds.size.height * screenScale);
|
|
callback_SurfaceViewController_launchMinecraft(width, height);
|
|
}
|
|
|
|
BOOL isNotifRemoved;
|
|
- (void)mglkView:(MGLKView *)view drawInRect:(CGRect)rect {
|
|
// glClearColor(0.6f, 0.6f, 0.6f, 1.0f);
|
|
// glClear(GL_COLOR_BUFFER_BIT);
|
|
// [self setNeedsDisplay]
|
|
// NSLog(@"swapbuffer");
|
|
|
|
// Remove notifications, so rendering will be manually controlled!
|
|
if (isNotifRemoved == NO) {
|
|
isNotifRemoved = YES;
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
name:MGLKApplicationWillResignActiveNotification
|
|
object:nil];
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
name:MGLKApplicationDidBecomeActiveNotification
|
|
object:nil];
|
|
}
|
|
|
|
[super pause];
|
|
}
|
|
|
|
- (void)sendTouchEvent:(NSSet *)touches withEvent:(int)event
|
|
{
|
|
UITouch* touchEvent = [touches anyObject];
|
|
if ([touchEvent view] == touchView) {
|
|
CGPoint locationInView = [touchEvent locationInView:touchView];
|
|
[self sendTouchPoint:locationInView withEvent:event];
|
|
}
|
|
}
|
|
|
|
- (void)sendTouchPoint:(CGPoint)location withEvent:(int)event{
|
|
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
|
if (callback_SurfaceViewController_touchHotbar(location.x * screenScale, location.y * screenScale) == -1) {
|
|
callback_SurfaceViewController_onTouch(event, location.x * screenScale, location.y * screenScale);
|
|
}
|
|
|
|
// Java_org_lwjgl_glfw_CallbackBridge_nativeSendCursorPos(NULL, NULL, location.x * screenScale, location.y * screenScale);
|
|
}
|
|
|
|
int touchesMovedCount;
|
|
// Equals to Android ACTION_DOWN
|
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
|
{
|
|
[super touchesBegan: touches withEvent: event];
|
|
[self sendTouchEvent: touches withEvent: ACTION_DOWN];
|
|
touchesMovedCount = 0;
|
|
shouldTriggerClick = YES;
|
|
}
|
|
|
|
// Equals to Android ACTION_MOVE
|
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
|
{
|
|
[super touchesMoved: touches withEvent: event];
|
|
[self sendTouchEvent: touches withEvent: ACTION_MOVE];
|
|
if (touchesMovedCount >= 1) {
|
|
shouldTriggerClick = NO;
|
|
} else ++touchesMovedCount;
|
|
}
|
|
|
|
// Equals to Android ACTION_UP
|
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
|
{
|
|
[super touchesEnded: touches withEvent: event];
|
|
[self sendTouchEvent: touches withEvent: ACTION_UP];
|
|
}
|
|
|
|
@end |