diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt index 1367bf12..e450a103 100644 --- a/Natives/CMakeLists.txt +++ b/Natives/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(pojavexec SHARED SurfaceViewController.m UpdateHistoryViewController.m customcontrols/ControlButton.m + customcontrols/CustomControlsUtils.m egl_bridge.m external/DBNumberedSlider/Classes/DBNumberedSlider.m input_bridge_v3.m diff --git a/Natives/CustomControlsViewController.m b/Natives/CustomControlsViewController.m index 3100be11..206a580a 100644 --- a/Natives/CustomControlsViewController.m +++ b/Natives/CustomControlsViewController.m @@ -6,17 +6,23 @@ #include "glfw_keycodes.h" #include "utils.h" +// CGRectOffset(RECT, notchOffset, 0) #define ADD_BUTTON(NAME, KEY, RECT, VISIBLE) \ - ControlButton *button_##KEY = [ControlButton initWithName:NAME keycode:KEY rect:CGRectOffset(RECT, notchOffset, 0) transparency:0.0f]; \ + ControlButton *button_##KEY = [ControlButton initWithName:NAME keycode:KEY rect:CGRectMake(RECT.origin.x * buttonScale, RECT.origin.y * buttonScale, RECT.size.width * buttonScale, RECT.size.height * buttonScale) transparency:0.0f]; \ [button_##KEY addGestureRecognizer:[[UITapGestureRecognizer alloc] \ initWithTarget:self action:@selector(showControlPopover:)]]; \ [self.view addSubview:button_##KEY]; +#define APPLY_SCALE(KEY) \ + KEY = @([(NSNumber *)KEY floatValue] * savedScale / currentScale); + int notchOffset; @interface CustomControlsViewController () { } +@property (nonatomic, strong) NSMutableDictionary* cc_dictionary; + // - (void)method @end @@ -39,80 +45,57 @@ int notchOffset; } CGRect screenBounds = [[UIScreen mainScreen] bounds]; - CGFloat screenScale = [[UIScreen mainScreen] scale]; UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets; int width = (int) roundf(screenBounds.size.width); int height = (int) roundf(screenBounds.size.height); notchOffset = insets.left; width = width - notchOffset * 2; CGFloat buttonScale = ((NSNumber *) getPreference(@"button_scale")).floatValue / 100.0; - CGFloat rectBtnWidth = 80.0 * buttonScale; - CGFloat rectBtnHeight = 30.0 * buttonScale; - CGFloat squareBtnSize = 50.0 * buttonScale; - + UILongPressGestureRecognizer *longpressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showControlPopover:)]; longpressGesture.minimumPressDuration = 0.5; [self.view addGestureRecognizer:longpressGesture]; - - // Temporary fallback controls - BOOL cc_fallback = YES; - NSString *controlFilePath = [NSString stringWithFormat:@"%s/%@", getenv("POJAV_PATH_CONTROL"), (NSString *)getPreference(@"default_ctrl")]; NSError *cc_error; NSString *cc_data = [NSString stringWithContentsOfFile:controlFilePath encoding:NSUTF8StringEncoding error:&cc_error]; if (cc_error != nil) { - NSLog(@"Error: could not read \"%@\", falling back to default control, error: %@", controlFilePath, cc_error.localizedDescription); + NSLog(@"Error: could not read %@: %@", controlFilePath, cc_error.localizedDescription); + showDialog(self, @"Error", [NSString stringWithFormat:@"Could not read %@: %@", controlFilePath, cc_error.localizedDescription]); } else { NSData* cc_objc_data = [cc_data dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *cc_dictionary = [NSJSONSerialization JSONObjectWithData:cc_objc_data options:kNilOptions error:&cc_error]; + self.cc_dictionary = [NSJSONSerialization JSONObjectWithData:cc_objc_data options:NSJSONReadingMutableContainers error:&cc_error]; if (cc_error != nil) { showDialog(self, @"Error parsing JSON", cc_error.localizedDescription); } else { - NSArray *cc_controlDataList = (NSArray *) [cc_dictionary valueForKey:@"mControlDataList"]; + NSMutableArray *cc_controlDataList = self.cc_dictionary[@"mControlDataList"]; + CGFloat currentScale = ((NSNumber *)self.cc_dictionary[@"scaledAt"]).floatValue; + CGFloat savedScale = ((NSNumber *)getPreference(@"button_scale")).floatValue; + int cc_version = ((NSNumber *)self.cc_dictionary[@"version"]).intValue; for (int i = 0; i < (int) cc_controlDataList.count; i++) { - ControlButton *button = [ControlButton initWithProperties:(NSMutableDictionary *)cc_controlDataList[i]]; + NSMutableDictionary *cc_buttonDict = cc_controlDataList[i]; + if (cc_version < 2) { + showDialog(self, @"Notice", @"Custom controls v1 to v2 was not implemented!"); + return; + //convertV1ToV2(cc_buttonDict); + } + APPLY_SCALE(cc_buttonDict[@"width"]); + APPLY_SCALE(cc_buttonDict[@"height"]); + APPLY_SCALE(cc_buttonDict[@"strokeWidth"]); + + ControlButton *button = [ControlButton initWithProperties:cc_buttonDict]; [button addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showControlPopover:)]]; [self.view addSubview:button]; } - cc_fallback = NO; + self.cc_dictionary[@"scaledAt"] = @(savedScale); } } - - if (cc_fallback == YES) { - ADD_BUTTON(@"GUI", SPECIALBTN_TOGGLECTRL, CGRectMake(5, height - 5 - squareBtnSize, squareBtnSize, squareBtnSize), NO); - ADD_BUTTON(@"Keyboard", SPECIALBTN_KEYBOARD, CGRectMake(5 * 3 + rectBtnWidth * 2, 5, rectBtnWidth, rectBtnHeight), YES); - - ADD_BUTTON(@"Pri", SPECIALBTN_MOUSEPRI, CGRectMake(5, height - 5 * 3 - squareBtnSize * 3, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"Sec", SPECIALBTN_MOUSESEC, CGRectMake(5 * 3 + squareBtnSize * 2, height - 5 * 3 - squareBtnSize * 3, squareBtnSize, squareBtnSize), YES); - - ADD_BUTTON(@"Debug", GLFW_KEY_F3, CGRectMake(5, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"Chat", GLFW_KEY_T, CGRectMake(5 * 2 + rectBtnWidth, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"Tab", GLFW_KEY_TAB, CGRectMake(5 * 4 + rectBtnWidth * 3, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"Opti-Zoom", GLFW_KEY_C, CGRectMake(5 * 5 + rectBtnWidth * 4, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"Offhand", GLFW_KEY_F, CGRectMake(5 * 6 + rectBtnWidth * 5, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"3rd", GLFW_KEY_F5, CGRectMake(5, 5 * 2 + rectBtnHeight, rectBtnWidth, rectBtnHeight), YES); - - ADD_BUTTON(@"▲", GLFW_KEY_W, CGRectMake(5 * 2 + squareBtnSize, height - 5 * 3 - squareBtnSize * 3, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"◀", GLFW_KEY_A, CGRectMake(5, height - 5 * 2 - squareBtnSize * 2, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"▼", GLFW_KEY_S, CGRectMake(5 * 2 + squareBtnSize, height - 5 - squareBtnSize, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"▶", GLFW_KEY_D, CGRectMake(5 * 3 + squareBtnSize * 2, height - 5 * 2 - squareBtnSize * 2, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"◇", GLFW_KEY_LEFT_SHIFT, CGRectMake(5 * 2 + squareBtnSize, height - 5 * 2 - squareBtnSize * 2, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"Inv", GLFW_KEY_E, CGRectMake(5 * 3 + squareBtnSize * 2, height - 5 - squareBtnSize, squareBtnSize, squareBtnSize), YES); - - ADD_BUTTON(@"⬛", GLFW_KEY_SPACE, CGRectMake(width - 5 * 2 - squareBtnSize * 2, height - 5 * 2 - squareBtnSize * 2, squareBtnSize, squareBtnSize), YES); - - ADD_BUTTON(@"Esc", GLFW_KEY_ESCAPE, CGRectMake(width - 5 - rectBtnWidth, height - 5 - rectBtnHeight, rectBtnWidth, rectBtnHeight), YES); - - // ADD_BUTTON(@"Fullscreen", f11, CGRectMake(width - 5 - rectBtnWidth, 5, rectBtnWidth, rectBtnHeight), YES); - } -} +} - (void)showControlPopover:(UIGestureRecognizer *)sender { - NSLog(@"Got Gesture = %@", sender); switch (sender.state) { case UIGestureRecognizerStateBegan: if (![sender isKindOfClass:[UILongPressGestureRecognizer class]]) { @@ -181,7 +164,19 @@ int notchOffset; - (void)viewDidLoad { [super viewDidLoad]; - + UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [button setTitle:@"This is not yet finished. Click here to exit" forState:UIControlStateNormal]; + button.frame = self.view.frame; + [button addTarget:self action:@selector(tempExit) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:button]; +} + +- (void)tempExit { + [self dismissViewControllerAnimated:YES completion:nil]; + [((UINavigationController *)self.presentingViewController) setNavigationBarHidden:NO animated:YES]; + [((UINavigationController *)self.presentingViewController) popViewControllerAnimated:YES]; + // [((UINavigationController *)self.presentingViewController).topViewController dismissViewControllerAnimated:YES completion:nil]; + // NSLog(@"ok=%@", ((UINavigationController *)self.presentingViewController).topViewController); } @end diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m index ec85d4d5..8514d436 100644 --- a/Natives/JavaLauncher.m +++ b/Natives/JavaLauncher.m @@ -18,6 +18,7 @@ #include "utils.h" #include "JavaLauncher.h" +#import "customcontrols/CustomControlsUtils.h" #import "LauncherPreferences.h" // PojavLancher: fixme: are these wrong? @@ -197,6 +198,7 @@ int launchJVM(int argc, char *argv[]) { sprintf(controlPath, "%s/controlmap", homeDir); mkdir(controlPath, S_IRWXU | S_IRWXG | S_IRWXO); setenv("POJAV_PATH_CONTROL", controlPath, 1); + generateAndSaveDefaultControl(); char classpath[10000]; @@ -263,7 +265,7 @@ int launchJVM(int argc, char *argv[]) { if (!started) { // Setup Caciocavallo - margv[margc++] = "-Djava.awt.headless=true"; + margv[margc++] = "-Djava.awt.headless=true"; // TODO: register natives to make this false margv[margc++] = "-Dcacio.font.fontmanager=sun.awt.X11FontManager"; margv[margc++] = "-Dcacio.font.fontscaler=sun.font.FreetypeFontScaler"; margv[margc++] = "-Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel"; diff --git a/Natives/LauncherPreferencesViewController.m b/Natives/LauncherPreferencesViewController.m index 5857ab1c..d5cfa201 100644 --- a/Natives/LauncherPreferencesViewController.m +++ b/Natives/LauncherPreferencesViewController.m @@ -42,7 +42,7 @@ UITextField* versionTextField; } UILabel *btnsizeTextView = [[UILabel alloc] initWithFrame:CGRectMake(4.0, 8.0, 0.0, 30.0)]; - btnsizeTextView.text = @"Button scale: "; + btnsizeTextView.text = @"Button scale (%)"; btnsizeTextView.numberOfLines = 0; btnsizeTextView.textAlignment = NSTextAlignmentCenter; [btnsizeTextView sizeToFit]; diff --git a/Natives/LoginViewController.m b/Natives/LoginViewController.m index e922dcdb..24ab5c58 100644 --- a/Natives/LoginViewController.m +++ b/Natives/LoginViewController.m @@ -363,21 +363,21 @@ void loginAccountInput(UINavigationController *controller, int type, const char* @interface LoginListViewController () { } +@property(nonatomic, strong) NSMutableArray *accountList; + @end @implementation LoginListViewController -NSMutableArray *accountList; - - (void)viewDidLoad { [super viewDidLoad]; [self setTitle:@"Select account"]; - if (accountList == nil) { - accountList = [NSMutableArray array]; + if (self.accountList == nil) { + self.accountList = [NSMutableArray array]; } else { - [accountList removeAllObjects]; + [self.accountList removeAllObjects]; } // List accounts @@ -395,7 +395,7 @@ NSMutableArray *accountList; continue; } else if ([@(dir->d_name) hasSuffix:@".json"]) { NSString *trimmedName= [@(dir->d_name) substringToIndex:((int)[@(dir->d_name) length] - 5)]; - [accountList addObject:trimmedName]; + [self.accountList addObject:trimmedName]; } } closedir(d); @@ -411,7 +411,7 @@ NSMutableArray *accountList; - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [accountList count]; + return [self.accountList count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath @@ -423,24 +423,24 @@ NSMutableArray *accountList; cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; } - cell.textLabel.text = [accountList objectAtIndex:indexPath.row]; + cell.textLabel.text = [self.accountList objectAtIndex:indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self dismissViewControllerAnimated:YES completion:nil]; - NSString *str = [accountList objectAtIndex:indexPath.row]; + NSString *str = [self.accountList objectAtIndex:indexPath.row]; loginAccountInput((UINavigationController *)self.presentingViewController, TYPE_SELECTACC, [str UTF8String]); } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { - NSString *str = [accountList objectAtIndex:indexPath.row]; + NSString *str = [self.accountList objectAtIndex:indexPath.row]; char accPath[2048]; sprintf(accPath, "%s/accounts/%s.json", getenv("POJAV_HOME"), [str UTF8String]); remove(accPath); - [accountList removeObjectAtIndex:indexPath.row]; + [self.accountList removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m index fc594c5b..ee00946a 100644 --- a/Natives/SurfaceViewController.m +++ b/Natives/SurfaceViewController.m @@ -18,7 +18,7 @@ // #define DEBUG_VISIBLE_TEXT_FIELD #define ADD_BUTTON(NAME, KEY, RECT, VISIBLE) \ - ControlButton *button_##KEY = [ControlButton initWithName:NAME keycode:KEY rect:CGRectOffset(RECT, notchOffset, 0) transparency:0.0f]; \ + ControlButton *button_##KEY = [ControlButton initWithName:NAME keycode:KEY rect:CGRectMake(RECT.origin.x * buttonScale, RECT.origin.y * buttonScale, RECT.size.width * buttonScale, RECT.size.height * buttonScale) transparency:0.0f]; \ [button_##KEY addTarget:self action:@selector(executebtn_down:) forControlEvents:UIControlEventTouchDown]; \ [button_##KEY addTarget:self action:@selector(executebtn_up:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; \ [self.view addSubview:button_##KEY]; \ @@ -26,6 +26,9 @@ togglableVisibleButtons[++togglableVisibleButtonIndex] = button_##KEY; \ } +#define APPLY_SCALE(KEY) \ + KEY = @([(NSNumber *)KEY floatValue] * savedScale / currentScale); + #define INPUT_SPACE_CHAR @" " #define INPUT_SPACE_LENGTH 20 @@ -47,7 +50,8 @@ int notchOffset; @interface SurfaceViewController () { } -@property (strong, nonatomic) MGLContext *context; +@property (nonatomic, strong) MGLContext *context; +@property (nonatomic, strong) NSMutableDictionary* cc_dictionary; - (void)setupGL; @@ -77,6 +81,7 @@ int notchOffset; notchOffset = insets.left; width = width - notchOffset * 2; + CGFloat buttonScale = ((NSNumber *) getPreference(@"button_scale")).floatValue / 100.0; UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(surfaceOnClick:)]; tapGesture.numberOfTapsRequired = 1; @@ -102,16 +107,11 @@ int notchOffset; [touchView addGestureRecognizer:mouseWheelGesture]; } - CGFloat buttonScale = ((NSNumber *) getPreference(@"button_scale")).floatValue / 100.0; - CGFloat rectBtnWidth = 80.0 * buttonScale; - CGFloat rectBtnHeight = 30.0 * buttonScale; - CGFloat squareBtnSize = 50.0 * buttonScale; - #ifndef DEBUG_VISIBLE_TEXT_FIELD - inputView = [[UITextField alloc] initWithFrame:CGRectMake(5 * 3 + rectBtnWidth * 2, 5, rectBtnWidth, rectBtnHeight)]; + inputView = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 1, 1)]; inputView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0f]; #else - inputView = [[UITextField alloc] initWithFrame:CGRectMake(5 * 3 + rectBtnWidth * 2, 5 * 2 + rectBtnHeight, 200, rectBtnHeight)]; + inputView = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 1, 1)]; inputView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.5f]; inputLengthView = [[UILabel alloc] initWithFrame:CGRectMake(5 * 2 + rectBtnWidth, 5 * 2 + rectBtnHeight, rectBtnWidth, rectBtnHeight)]; @@ -126,65 +126,52 @@ int notchOffset; // Custom button // ADD_BUTTON(@"F1", f1, CGRectMake(5, 5, width, height)); - // Temporary fallback controls - BOOL cc_fallback = YES; - NSString *controlFilePath = [NSString stringWithFormat:@"%s/%@", getenv("POJAV_PATH_CONTROL"), (NSString *)getPreference(@"default_ctrl")]; NSError *cc_error; NSString *cc_data = [NSString stringWithContentsOfFile:controlFilePath encoding:NSUTF8StringEncoding error:&cc_error]; if (cc_error != nil) { - NSLog(@"Error: could not read \"%@\", falling back to default control, error: %@", controlFilePath, cc_error.localizedDescription); + NSLog(@"Error: could not read %@: %@", controlFilePath, cc_error.localizedDescription); + showDialog(self, @"Error", [NSString stringWithFormat:@"Could not read %@: %@", controlFilePath, cc_error.localizedDescription]); } else { NSData* cc_objc_data = [cc_data dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *cc_dictionary = [NSJSONSerialization JSONObjectWithData:cc_objc_data options:kNilOptions error:&cc_error]; + self.cc_dictionary = [NSJSONSerialization JSONObjectWithData:cc_objc_data options:NSJSONReadingMutableContainers error:&cc_error]; if (cc_error != nil) { showDialog(self, @"Error parsing JSON", cc_error.localizedDescription); } else { - NSArray *cc_controlDataList = (NSArray *) [cc_dictionary valueForKey:@"mControlDataList"]; + NSMutableArray *cc_controlDataList = self.cc_dictionary[@"mControlDataList"]; + CGFloat currentScale = ((NSNumber *)self.cc_dictionary[@"scaledAt"]).floatValue; + CGFloat savedScale = ((NSNumber *)getPreference(@"button_scale")).floatValue; + int cc_version = ((NSNumber *)self.cc_dictionary[@"version"]).intValue; for (int i = 0; i < (int) cc_controlDataList.count; i++) { - ControlButton *button = [ControlButton initWithProperties:(NSMutableDictionary *)cc_controlDataList[i]]; + NSMutableDictionary *cc_buttonDict = cc_controlDataList[i]; + if (cc_version < 2) { + showDialog(self, @"Notice", @"Custom controls v1 to v2 was not implemented!"); + return; + //convertV1ToV2(cc_buttonDict); + } + APPLY_SCALE(cc_buttonDict[@"width"]); + APPLY_SCALE(cc_buttonDict[@"height"]); + APPLY_SCALE(cc_buttonDict[@"strokeWidth"]); + + ControlButton *button = [ControlButton initWithProperties:cc_buttonDict]; [button addTarget:self action:@selector(executebtn_down:) forControlEvents:UIControlEventTouchDown]; - [button addTarget:self action:@selector(executebtn_up:) forControlEvents:UIControlEventTouchUpInside]; - [button addTarget:self action:@selector(executebtn_up:) forControlEvents:UIControlEventTouchUpOutside]; + [button addTarget:self action:@selector(executebtn_up:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; [self.view addSubview:button]; - if ([(NSNumber *) [button.properties valueForKey:@"keycode"] intValue] != SPECIALBTN_TOGGLECTRL) { + + int firstKeycode = ((NSNumber *)cc_buttonDict[@"keycodes"][0]).intValue; + if (firstKeycode == SPECIALBTN_KEYBOARD) { + inputView.frame = button.frame; + } + if (firstKeycode != SPECIALBTN_TOGGLECTRL) { togglableVisibleButtons[++togglableVisibleButtonIndex] = button; } } - cc_fallback = NO; + self.cc_dictionary[@"scaledAt"] = @(savedScale); } } - if (cc_fallback == YES) { - ADD_BUTTON(@"GUI", SPECIALBTN_TOGGLECTRL, CGRectMake(5, height - 5 - squareBtnSize, squareBtnSize, squareBtnSize), NO); - ADD_BUTTON(@"Keyboard", SPECIALBTN_KEYBOARD, CGRectMake(5 * 3 + rectBtnWidth * 2, 5, rectBtnWidth, rectBtnHeight), YES); - - ADD_BUTTON(@"Pri", SPECIALBTN_MOUSEPRI, CGRectMake(5, height - 5 * 3 - squareBtnSize * 3, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"Sec", SPECIALBTN_MOUSESEC, CGRectMake(5 * 3 + squareBtnSize * 2, height - 5 * 3 - squareBtnSize * 3, squareBtnSize, squareBtnSize), YES); - - ADD_BUTTON(@"Debug", GLFW_KEY_F3, CGRectMake(5, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"Chat", GLFW_KEY_T, CGRectMake(5 * 2 + rectBtnWidth, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"Tab", GLFW_KEY_TAB, CGRectMake(5 * 4 + rectBtnWidth * 3, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"Opti-Zoom", GLFW_KEY_C, CGRectMake(5 * 5 + rectBtnWidth * 4, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"Offhand", GLFW_KEY_F, CGRectMake(5 * 6 + rectBtnWidth * 5, 5, rectBtnWidth, rectBtnHeight), YES); - ADD_BUTTON(@"3rd", GLFW_KEY_F5, CGRectMake(5, 5 * 2 + rectBtnHeight, rectBtnWidth, rectBtnHeight), YES); - - ADD_BUTTON(@"▲", GLFW_KEY_W, CGRectMake(5 * 2 + squareBtnSize, height - 5 * 3 - squareBtnSize * 3, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"◀", GLFW_KEY_A, CGRectMake(5, height - 5 * 2 - squareBtnSize * 2, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"▼", GLFW_KEY_S, CGRectMake(5 * 2 + squareBtnSize, height - 5 - squareBtnSize, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"▶", GLFW_KEY_D, CGRectMake(5 * 3 + squareBtnSize * 2, height - 5 * 2 - squareBtnSize * 2, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"◇", GLFW_KEY_LEFT_SHIFT, CGRectMake(5 * 2 + squareBtnSize, height - 5 * 2 - squareBtnSize * 2, squareBtnSize, squareBtnSize), YES); - ADD_BUTTON(@"Inv", GLFW_KEY_E, CGRectMake(5 * 3 + squareBtnSize * 2, height - 5 - squareBtnSize, squareBtnSize, squareBtnSize), YES); - - ADD_BUTTON(@"⬛", GLFW_KEY_SPACE, CGRectMake(width - 5 * 2 - squareBtnSize * 2, height - 5 * 2 - squareBtnSize * 2, squareBtnSize, squareBtnSize), YES); - - ADD_BUTTON(@"Esc", GLFW_KEY_ESCAPE, CGRectMake(width - 5 - rectBtnWidth, height - 5 - rectBtnHeight, rectBtnWidth, rectBtnHeight), YES); - - // ADD_BUTTON(@"Fullscreen", f11, CGRectMake(width - 5 - rectBtnWidth, 5, rectBtnWidth, rectBtnHeight), YES); - } - [self.view addSubview:inputView]; [self executebtn_special_togglebtn:0]; @@ -557,7 +544,8 @@ int currentVisibility = 1; - (void) executebtn:(UIButton *)sender withAction:(int)action { ControlButton *button = (ControlButton *)sender; int held = action == ACTION_DOWN; - int keycode = [(NSNumber *) [button.properties valueForKey:@"keycode"] intValue]; + // TODO v2: mulitple keys support + int keycode = ((NSNumber *)button.properties[@"keycodes"][0]).intValue; if (keycode < 0) { switch (keycode) { case SPECIALBTN_KEYBOARD: diff --git a/Natives/customcontrols/ControlButton.h b/Natives/customcontrols/ControlButton.h index b01aefa2..55113ebb 100644 --- a/Natives/customcontrols/ControlButton.h +++ b/Natives/customcontrols/ControlButton.h @@ -1,17 +1,17 @@ #import /** - * Custom controls have same format as Android. + * Custom controls have similar format as Android. * * Android - iOS: * ControlButton - same - * ControlData - NSArray with JSON components + * ControlData - NSDictionary */ @interface ControlButton : UIButton { } -@property (nonatomic, retain) NSMutableDictionary* properties; +@property (nonatomic, strong) NSMutableDictionary* properties; + (id)initWithProperties:(NSMutableDictionary *)propArray; + (id)initWithName:(NSString *)name keycode:(int)keycode rect:(CGRect)rect transparency:(float)transparency; diff --git a/Natives/customcontrols/ControlButton.m b/Natives/customcontrols/ControlButton.m index 5d424371..8970dbf2 100644 --- a/Natives/customcontrols/ControlButton.m +++ b/Natives/customcontrols/ControlButton.m @@ -1,14 +1,11 @@ #import "ControlButton.h" +#import "CustomControlsUtils.h" #import "../LauncherPreferences.h" #define INSERT_VALUE(KEY, VALUE) \ string = [string stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"${%@}", @(KEY)] withString:VALUE]; -#define NUM2F(x) [(NSNumber *)x floatValue] - -float getScreenScale() { - return (float) (((NSNumber *) getPreference(@"button_scale")).floatValue / 50.0); //[[UIScreen mainScreen] scale]; -} +#define NUM2F(x) (x == nil ? 0 : [(NSNumber *)x floatValue]) @implementation ControlButton @synthesize properties; @@ -25,11 +22,9 @@ float getScreenScale() { + (id)initWithProperties:(NSMutableDictionary *)propArray { ControlButton *instance = [ControlButton buttonWithType:UIButtonTypeRoundedRect]; - [instance setTitle:[propArray valueForKey:@"name"] - forState:UIControlStateNormal]; + [instance setTitle:propArray[@"name"] forState:UIControlStateNormal]; instance.autoresizingMask = UIViewAutoresizingFlexibleWidth; instance.tintColor = [UIColor whiteColor]; - instance.properties = propArray; [instance update]; @@ -37,31 +32,29 @@ float getScreenScale() { } + (id)initWithName:(NSString *)name keycode:(int)keycode rect:(CGRect)rect transparency:(float)transparency { - float screenScale = getScreenScale(); - NSMutableDictionary *properties = [[NSMutableDictionary alloc] init]; - [properties setObject:name forKey:@"name"]; - [properties setObject:@(rect.origin.x * screenScale) forKey:@"x"]; - [properties setObject:@(rect.origin.y * screenScale) forKey:@"y"]; - [properties setObject:@(rect.size.width * screenScale) forKey:@"width"]; - [properties setObject:@(rect.size.height * screenScale) forKey:@"height"]; - [properties setObject:@(keycode) forKey:@"keycode"]; - [properties setObject:@(transparency) forKey:@"transparency"]; + properties[@"name"] = name; + properties[@"x"] = @(rect.origin.x); + properties[@"y"] = @(rect.origin.y); + properties[@"width"] = @(rect.size.width); + properties[@"height"] = @(rect.size.height); + properties[@"keycode"] = @(keycode); + properties[@"transparency"] = @(transparency); + properties[@"cornerRadius"] = @(0); return [ControlButton initWithProperties:properties]; } - (float)insertDynamicPos:(NSString*)string { CGRect screenBounds = [[UIScreen mainScreen] bounds]; - float screenScale = getScreenScale(); UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets; // width: offset the notch parts - int screenWidth = (int) roundf((screenBounds.size.width - insets.left - insets.right) * screenScale); - int screenHeight = (int) roundf(screenBounds.size.height * screenScale); + int screenWidth = (int) roundf(screenBounds.size.width - insets.left - insets.right); + int screenHeight = (int) roundf(screenBounds.size.height); - float width = NUM2F([self.properties valueForKey:@"width"]); - float height = NUM2F([self.properties valueForKey:@"height"]); + float width = NUM2F(self.properties[@"width"]); + float height = NUM2F(self.properties[@"height"]); // Insert value to ${variable} INSERT_VALUE("top", @"0"); @@ -72,50 +65,73 @@ float getScreenScale() { INSERT_VALUE("height", ([NSString stringWithFormat:@"%f", height])); INSERT_VALUE("screen_width", ([NSString stringWithFormat:@"%d", screenWidth])); INSERT_VALUE("screen_height", ([NSString stringWithFormat:@"%d", screenHeight])); - INSERT_VALUE("margin", ([NSString stringWithFormat:@"%f", 2.0 * screenScale])); // FIXME is this correct? + INSERT_VALUE("margin", ([NSString stringWithFormat:@"%f", 2.0])); // FIXME is this correct? // NSLog(@"Final math: %@", string); - // Calculate, because the dynamic position contains some math equations + // Calculate, since the dynamic position contains some math equations NSExpression *expression = [NSExpression expressionWithFormat:string]; return [[expression expressionValueWithObject:nil context:nil] floatValue]; } +- (void)setDefaultValueForKey:(NSString *)key value:(id)value { + if (self.properties[key] == nil || self.properties[key] == [NSNull null]) { + self.properties[key] = value; + } +} + - (void)update { // net/kdt/pojavlaunch/customcontrols/ControlData.update() - float screenScale = getScreenScale(); UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets; - NSString *propDynamicX = (NSString *) [self.properties valueForKey:@"dynamicX"]; - NSString *propDynamicY = (NSString *) [self.properties valueForKey:@"dynamicY"]; - float propX = NUM2F([self.properties valueForKey:@"x"]); - float propY = NUM2F([self.properties valueForKey:@"y"]); - float propW = NUM2F([self.properties valueForKey:@"width"]); - float propH = NUM2F([self.properties valueForKey:@"height"]); + NSString *propDynamicX = (NSString *) self.properties[@"dynamicX"]; + NSString *propDynamicY = (NSString *) self.properties[@"dynamicY"]; + + float propX = NUM2F(self.properties[@"x"]); + float propY = NUM2F(self.properties[@"y"]); + float propW = NUM2F(self.properties[@"width"]); + float propH = NUM2F(self.properties[@"height"]); + float propCornerRadius = NUM2F(self.properties[@"cornerRadius"]); + float propStrokeWidth = NUM2F(self.properties[@"strokeWidth"]); + int propBackgroundColor = ((NSNumber *)self.properties[@"bgColor"]).intValue; + int propStrokeColor = ((NSNumber *)self.properties[@"strokeColor"]).intValue; + + // isRound is deprecated, only keep for old Android's controls backwards compatibility + [self setDefaultValueForKey:@"isRound" value:@(NO)]; + BOOL propIsRound = self.properties[@"isRound"]; + [self setDefaultValueForKey:@"cornerRadius" value:@(propIsRound ? 8.0 : 0)]; // If dynamic position is null, set value to fixed position if (propDynamicX == nil) { propDynamicX = [NSString stringWithFormat:@"%f", propX]; - [self.properties setObject:propDynamicX forKey:@"dynamicX"]; + self.properties[@"dynamicX"] = propDynamicX; } if (propDynamicY == nil) { propDynamicY = [NSString stringWithFormat:@"%f", propY]; - [self.properties setObject:propDynamicY forKey:@"dynamicY"]; + self.properties[@"dynamicY"] = propDynamicY; } // Calculate dynamic position propX = [self insertDynamicPos:propDynamicX]; propY = [self insertDynamicPos:propDynamicY]; // Set back to fixed position -/* [self.properties setObject:@(propX) forKey:@"x"]; [self.properties setObject:@(propY) forKey:@"y"]; -*/ // Update other properties - self.frame = CGRectMake(propX / screenScale + insets.left, propY / screenScale, propW / screenScale, propH / screenScale); + self.frame = CGRectMake(propX + insets.left, propY, propW, propH); self.alpha = 1.0f - NUM2F([properties valueForKey:@"transparency"]) / 100.0f; - self.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.3f]; + // self.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.3f]; + self.backgroundColor = convertARGB2UIColor(propBackgroundColor); + + self.layer.borderColor = [convertARGB2UIColor(propStrokeColor) CGColor]; + if (propCornerRadius > 0) { + self.layer.cornerRadius = self.frame.size.width / 200 * propCornerRadius; + } + if (propStrokeWidth > 0) { + self.layer.borderWidth = self.frame.size.width / propStrokeWidth; + } + self.clipsToBounds = YES; } @end diff --git a/Natives/customcontrols/CustomControlsUtils.h b/Natives/customcontrols/CustomControlsUtils.h new file mode 100644 index 00000000..55533fb1 --- /dev/null +++ b/Natives/customcontrols/CustomControlsUtils.h @@ -0,0 +1,6 @@ +#import + +UIColor* convertARGB2UIColor(int argb); +int convertUIColor2ARGB(UIColor* color); +void convertV1ToV2(NSMutableDictionary* input); +void generateAndSaveDefaultControl(); diff --git a/Natives/customcontrols/CustomControlsUtils.m b/Natives/customcontrols/CustomControlsUtils.m new file mode 100644 index 00000000..337d7a57 --- /dev/null +++ b/Natives/customcontrols/CustomControlsUtils.m @@ -0,0 +1,171 @@ +#import "CustomControlsUtils.h" +#include "../glfw_keycodes.h" +#include "../utils.h" + +NSMutableDictionary* createButton(NSString* name, int* keycodes, NSString* dynamicX, NSString* dynamicY, CGFloat width, CGFloat height) { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + dict[@"name"] = name; + dict[@"keycodes"] = [[NSMutableArray alloc] init]; + for (int i = 0; i < 4; i++) { + [dict[@"keycodes"] addObject:@(keycodes[i])]; + } + dict[@"dynamicX"] = dynamicX; + dict[@"dynamicY"] = dynamicY; + dict[@"width"] = @(width); + dict[@"height"] = @(height); + return dict; +} + +UIColor* convertARGB2UIColor(int argb) { + return [UIColor + colorWithRed:((argb>>16)&0xFF)/255.0 + green:((argb>>8)&0xFF)/255.0 + blue:((argb>>0)&0xFF)/255.0 + alpha:((argb>>24)&0xFF)/255.0]; +} + +int convertUIColor2ARGB(UIColor* color) { + // TODO +} + +void convertV1ToV2(NSMutableDictionary* input) { + // TODO +} + +void generateAndSaveDefaultControl() { + // Generate a V2 control + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + dict[@"version"] = @(2); + dict[@"scaledAt"] = @(100); + dict[@"mControlDataList"] = [[NSMutableArray alloc] init]; + [dict[@"mControlDataList"] addObject:createButton(@"Keyboard", + (int[]){SPECIALBTN_KEYBOARD,0,0,0}, + @"${margin} * 3 + ${width} * 2", + @"${margin}", + 160.0, 60.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"GUI", + (int[]){SPECIALBTN_TOGGLECTRL,0,0,0}, + @"${margin}", + @"${bottom} - ${margin}", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"PRI", + (int[]){SPECIALBTN_MOUSEPRI,0,0,0}, + @"${margin}", + @"${screen_height} - ${margin} * 3 - ${height} * 3", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"SEC", + (int[]){SPECIALBTN_MOUSESEC,0,0,0}, + @"${margin} * 3 + ${width} * 2", + @"${screen_height} - ${margin} * 3 - ${height} * 3", + 100.0, 100.0 + )]; +/* // TODO: virtual mouse + [dict[@"mControlDataList"] addObject:createButton(@"Mouse", + (int[]){SPECIALBTN_VIRTUALMOUSE,0,0,0}, + @"${right}", + @"${margin}", + 160.0, 60.0 + )]; +*/ + [dict[@"mControlDataList"] addObject:createButton(@"Debug", + (int[]){GLFW_KEY_F3,0,0,0}, + @"${margin}", + @"${margin}", + 160.0, 60.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"Chat", + (int[]){GLFW_KEY_T,0,0,0}, + @"${margin} * 2 + ${width}", + @"${margin}", + 160.0, 60.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"Tab", + (int[]){GLFW_KEY_TAB,0,0,0}, + @"${margin} * 4 + ${width} * 3", + @"${margin}", + 160.0, 60.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"Opti-Zoom", + (int[]){GLFW_KEY_C,0,0,0}, + @"${margin} * 5 + ${width} * 4", + @"${margin}", + 160.0, 60.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"Offhand", + (int[]){GLFW_KEY_F,0,0,0}, + @"${margin} * 6 + ${width} * 5", + @"${margin}", + 160.0, 60.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"3rd", + (int[]){GLFW_KEY_F5,0,0,0}, + @"${margin}", + @"${margin} * 2 + ${height}", + 160.0, 60.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"▲", + (int[]){GLFW_KEY_W,0,0,0}, + @"${margin} * 2 + ${width}", + @"${bottom} - ${margin} * 3 - ${height} * 2", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"◀", + (int[]){GLFW_KEY_A,0,0,0}, + @"${margin}", + @"${bottom} - ${margin} * 2 - ${height}", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"▼", + (int[]){GLFW_KEY_S,0,0,0}, + @"${margin} * 2 + ${width}", + @"${bottom} - ${margin}", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"▶", + (int[]){GLFW_KEY_D,0,0,0}, + @"${margin} * 3 + ${width} * 2", + @"${bottom} - ${margin} * 2 - ${height}", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"Inv", + (int[]){GLFW_KEY_E,0,0,0}, + @"${margin} * 3 + ${width} * 2", + @"${bottom} - ${margin}", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"◇", + (int[]){GLFW_KEY_LEFT_SHIFT,0,0,0}, + @"${margin} * 2 + ${width}", + @"${screen_height} - ${margin} * 2 - ${height} * 2", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"⬛", + (int[]){GLFW_KEY_SPACE,0,0,0}, + @"${right} - ${margin} * 2 - ${width}", + @"${bottom} - ${margin} * 2 - ${height}", + 100.0, 100.0 + )]; + [dict[@"mControlDataList"] addObject:createButton(@"Esc", + (int[]){GLFW_KEY_ESCAPE,0,0,0}, + @"${right} - ${margin}", + @"${bottom} - ${margin}", + 160.0, 60.0 + )]; + NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath: + [@(getenv("POJAV_PATH_CONTROL")) stringByAppendingString:@"/default.json"] append:NO]; + [os open]; + [NSJSONSerialization writeJSONObject:dict toStream:os options:NSJSONWritingPrettyPrinted error:nil]; + [os close]; + +/* + [dict[@"mControlDataList"] addObject:createButton(@"NAME", + {SPECIALBTN_KEYBOARD,0,0,0}, + @"DYNAMICX", + @"DYNAMICY", + WIDTHHEIGHT + )]; +*/ +} diff --git a/Natives/resources/Frameworks/MetalANGLE.framework/Headers/EGL/egl.h b/Natives/resources/Frameworks/MetalANGLE.framework/Headers/EGL/egl.h index 94babc22..9a87290a 100644 --- a/Natives/resources/Frameworks/MetalANGLE.framework/Headers/EGL/egl.h +++ b/Natives/resources/Frameworks/MetalANGLE.framework/Headers/EGL/egl.h @@ -57,8 +57,8 @@ extern "C" { #define EGL_VERSION_1_0 1 typedef unsigned int EGLBoolean; typedef void *EGLDisplay; -#include -#include +#include "eglplatform.h" +#include "../KHR/khrplatform.h" typedef void *EGLConfig; typedef void *EGLSurface; typedef void *EGLContext; diff --git a/Natives/resources/Frameworks/MetalANGLE.framework/Headers/GLES2/gl2ext.h b/Natives/resources/Frameworks/MetalANGLE.framework/Headers/GLES2/gl2ext.h index 0ee082a3..313023e9 100644 --- a/Natives/resources/Frameworks/MetalANGLE.framework/Headers/GLES2/gl2ext.h +++ b/Natives/resources/Frameworks/MetalANGLE.framework/Headers/GLES2/gl2ext.h @@ -3612,6 +3612,11 @@ GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask); #define GL_SHADER_BINARY_VIV 0x8FC4 #endif /* GL_VIV_shader_binary */ +#ifndef GL_MGL_timeline_semaphore +#define GL_MGL_timeline_semaphore 1 +#define GL_TIMELINE_SEMAPHORE_VALUE_MGL 0x9595 +#endif + /* ANGLE GLES2 extensions */ #include "gl2ext_angle.h" diff --git a/Natives/resources/Frameworks/MetalANGLE.framework/Headers/MGLContext.h b/Natives/resources/Frameworks/MetalANGLE.framework/Headers/MGLContext.h index d00cb1ee..6bd8b5df 100644 --- a/Natives/resources/Frameworks/MetalANGLE.framework/Headers/MGLContext.h +++ b/Natives/resources/Frameworks/MetalANGLE.framework/Headers/MGLContext.h @@ -6,6 +6,8 @@ #import "MGLLayer.h" +#include "EGL/egl.h" + NS_ASSUME_NONNULL_BEGIN typedef enum MGLRenderingAPI : int @@ -27,10 +29,12 @@ typedef enum MGLRenderingAPI : int // contexts. - (id)initWithAPI:(MGLRenderingAPI)api sharegroup:(MGLSharegroup *_Nullable)sharegroup; -- (MGLRenderingAPI)API; +@property(nonatomic, readonly) MGLRenderingAPI API; @property(readonly) MGLSharegroup *sharegroup; +@property(nonatomic, readonly) EGLDisplay eglDisplay; + // Present the content of layer on screen as soon as possible. - (BOOL)present:(MGLLayer *)layer; diff --git a/Natives/resources/Frameworks/MetalANGLE.framework/Headers/MGLKViewController.h b/Natives/resources/Frameworks/MetalANGLE.framework/Headers/MGLKViewController.h index a2b501e3..ad22b63d 100644 --- a/Natives/resources/Frameworks/MetalANGLE.framework/Headers/MGLKViewController.h +++ b/Natives/resources/Frameworks/MetalANGLE.framework/Headers/MGLKViewController.h @@ -31,10 +31,13 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly) NSInteger framesDisplayed; @property(nonatomic, readonly) NSTimeInterval timeSinceLastUpdate; -@property(weak, nonatomic, readonly) MGLKView *glView; +@property(nonatomic, getter=isPaused) BOOL paused; +@property(nonatomic) BOOL pauseOnWillResignActive; +@property(nonatomic) BOOL resumeOnDidBecomeActive; - (void)pause; - (void)resume; +@property(weak, nonatomic, readonly) MGLKView *glView; @end diff --git a/Natives/resources/Frameworks/MetalANGLE.framework/Info.plist b/Natives/resources/Frameworks/MetalANGLE.framework/Info.plist index 8b0f9458..73907dcf 100644 Binary files a/Natives/resources/Frameworks/MetalANGLE.framework/Info.plist and b/Natives/resources/Frameworks/MetalANGLE.framework/Info.plist differ diff --git a/Natives/resources/Frameworks/MetalANGLE.framework/MetalANGLE b/Natives/resources/Frameworks/MetalANGLE.framework/MetalANGLE index c2196713..0c1dda07 100755 Binary files a/Natives/resources/Frameworks/MetalANGLE.framework/MetalANGLE and b/Natives/resources/Frameworks/MetalANGLE.framework/MetalANGLE differ diff --git a/Natives/resources/Frameworks/libgl4es_115.dylib b/Natives/resources/Frameworks/libgl4es_115.dylib index b27b76bb..3ea73986 100644 Binary files a/Natives/resources/Frameworks/libgl4es_115.dylib and b/Natives/resources/Frameworks/libgl4es_115.dylib differ