A lot of more changes

* Custom controls:
- Unfinished v2 control
- Auto generate default.json, removed internal fallback control
- Compatible with Android's dp (might need scaling)
- Implemented properties: keycodes, bgColor, strokeColor, strokeWidth,
cornerRadius

* Other changes
- Updated MetalANGLE to 0.0.7
- Updated gl4es 1.1.5

* TODO:
- Control converter
- Drawer buttons
- Multiple keys support (?)
- Implement properties: opacity, isSwipeable, isToggle,
passThruEnabled, (maybe more?)
This commit is contained in:
Duy Tran Khanh committed 2021-07-23 16:51:51 +07:00
1 parent 3ac9a2f85f
commit c896da08bb
17 files changed
+343 -152

No files matched your search

+1
View File
@@ -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
+41 -46
View File
@@ -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 () <UIPopoverPresentationControllerDelegate>{
}
@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
+3 -1
View File
@@ -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";
+1 -1
View File
@@ -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];
+11 -11
View File
@@ -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];
}
}
+37 -49
View File
@@ -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 ()<UITextFieldDelegate, UIPointerInteractionDelegate> {
}
@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:
+3 -3
View File
@@ -1,17 +1,17 @@
#import <UIKit/UIKit.h>
/**
* 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;
+53 -37
View File
@@ -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
@@ -0,0 +1,6 @@
#import <UIKit/UIKit.h>
UIColor* convertARGB2UIColor(int argb);
int convertUIColor2ARGB(UIColor* color);
void convertV1ToV2(NSMutableDictionary* input);
void generateAndSaveDefaultControl();
@@ -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
)];
*/
}
@@ -57,8 +57,8 @@ extern "C" {
#define EGL_VERSION_1_0 1
typedef unsigned int EGLBoolean;
typedef void *EGLDisplay;
#include <EGL/eglplatform.h>
#include <KHR/khrplatform.h>
#include "eglplatform.h"
#include "../KHR/khrplatform.h"
typedef void *EGLConfig;
typedef void *EGLSurface;
typedef void *EGLContext;
@@ -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"
@@ -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;
@@ -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
Binary file not shown.