Path: blob/main/Natives/CustomControlsViewController.m
589 views
#import "CustomControlsViewController.h"1#import "DBNumberedSlider.h"2#import "FileListViewController.h"3#import "LauncherPreferences.h"4#import "ios_uikit_bridge.h"56#import "customcontrols/ControlDrawer.h"7#import "customcontrols/ControlJoystick.h"8#import "customcontrols/CustomControlsUtils.h"910#include "glfw_keycodes.h"11#include "utils.h"1213@implementation ControlHandleView14// Nothing15@end1617@interface CustomControlsViewController () <UIGestureRecognizerDelegate, UIPopoverPresentationControllerDelegate>{18}1920@property(nonatomic) NSString* currentFileName;21@property(nonatomic) CGRect selectedPoint;22@property(nonatomic) UINavigationBar* navigationBar;2324@end2526@implementation CustomControlsViewController27#define isInGame [self.presentingViewController respondsToSelector:@selector(loadCustomControls)]2829- (void)viewDidLoad30{31[super viewDidLoad];32[self.undoManager removeAllActions];33self.view.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.5];34isControlModifiable = YES;3536[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];37[self setNeedsUpdateOfHomeIndicatorAutoHidden];3839CGRect screenBounds = [[UIScreen mainScreen] bounds];40UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets;4142UILabel *guideLabel = [[UILabel alloc] initWithFrame:self.view.frame];43guideLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;44guideLabel.numberOfLines = 0;45guideLabel.textAlignment = NSTextAlignmentCenter;46guideLabel.textColor = UIColor.whiteColor;47guideLabel.text = localize(@"custom_controls.hint", nil);48[self.view addSubview:guideLabel];4950self.ctrlView = [[ControlLayout alloc] initWithFrame:getSafeArea()];51self.ctrlView.layer.borderColor = UIColor.labelColor.CGColor;52[self.view addSubview:self.ctrlView];5354// Prepare the navigation bar for safe area customization55UINavigationItem *navigationItem = [[UINavigationItem alloc] init];56UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"None", @"Default", @"Custom"]];57[segmentedControl addTarget:self action:@selector(changeSafeAreaSelection:) forControlEvents:UIControlEventValueChanged];58[segmentedControl setEnabled:(insets.left+insets.right)>0 forSegmentAtIndex:1];59[self loadSafeAreaSelectionFor:segmentedControl];60navigationItem.titleView = segmentedControl;61navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(actionMenuSafeAreaCancel)];62navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionMenuSafeAreaDone)];63self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44.0)];64self.navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;65self.navigationBar.hidden = YES;66self.navigationBar.items = @[navigationItem];67self.navigationBar.translucent = YES;68[self.view addSubview:self.navigationBar];6970CGFloat buttonScale = getPrefFloat(@"control.button_scale") / 100.0;7172self.resizeView = [[ControlHandleView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];73self.resizeView.backgroundColor = self.view.tintColor;74self.resizeView.layer.cornerRadius = self.resizeView.frame.size.width / 2;75self.resizeView.clipsToBounds = YES;76self.resizeView.hidden = YES;77[self.resizeView addGestureRecognizer:[[UIPanGestureRecognizer alloc]78initWithTarget:self action:@selector(onTouch:)]];79[self.view addSubview:self.resizeView];8081UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panControlArea:)];82panGesture.delegate = self;83panGesture.maximumNumberOfTouches = 1;84[self.ctrlView addGestureRecognizer:panGesture];8586UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchControlArea:)];87pinchGesture.delegate = self;88[self.ctrlView addGestureRecognizer:pinchGesture];8990UILongPressGestureRecognizer *longpressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showControlPopover:)];91longpressGesture.minimumPressDuration = 0.5;92[self.ctrlView addGestureRecognizer:longpressGesture];93NSString *fileName = self.getDefaultCtrl();94self.currentFileName = [fileName stringByDeletingPathExtension];95[self loadControlFile:fileName];96}9798- (void)viewWillDisappear:(BOOL)animated {99[super viewWillDisappear:animated];100isControlModifiable = NO;101if (isInGame) {102[self.presentingViewController performSelector:@selector(loadCustomControls)];103}104}105106- (BOOL)gestureRecognizer:(UIGestureRecognizer *)sender shouldReceiveTouch:(UITouch *)touch {107return sender.view != self.view || !CGRectContainsPoint(self.resizeView.frame, [sender locationInView:self.view]);108}109/*110- (BOOL)gestureRecognizer:(UIGestureRecognizer *)sender shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {111return YES;112}113*/114- (void)panControlArea:(UIPanGestureRecognizer *)sender {115static CGPoint previous;116if (sender.state == UIGestureRecognizerStateBegan) {117[self setButtonMenuVisibleForView:nil];118self.resizeView.hidden = self.ctrlView.layer.borderWidth == 0;119self.resizeView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;120previous = [sender locationInView:self.view];121return;122} else if (self.navigationBar.hidden) {123return;124}125126CGPoint current = [sender locationInView:self.view];127128CGRect rect = self.ctrlView.frame;129rect.origin.x = clamp(rect.origin.x + current.x - previous.x, 0, self.view.frame.size.width - rect.size.width);130rect.origin.y = clamp(rect.origin.y + current.y - previous.y, 0, self.view.frame.size.height - rect.size.height);131self.ctrlView.frame = rect;132133self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.ctrlView.frame) - self.resizeView.frame.size.width, CGRectGetMaxY(self.ctrlView.frame) - self.resizeView.frame.size.height, self.resizeView.frame.size.width, self.resizeView.frame.size.height);134135previous = current;136}137138- (void)pinchControlArea:(UIPinchGestureRecognizer *)sender {139if (sender.numberOfTouches < 2 || self.navigationBar.hidden) {140return;141}142143static CGPoint previous;144CGPoint current = [sender locationInView:self.view];145if (sender.state == UIGestureRecognizerStateBegan) {146previous = current;147return;148}149150self.ctrlView.frame = CGRectMake(151clamp(self.ctrlView.frame.origin.x + current.x - previous.x, 0, self.view.frame.size.width - self.ctrlView.frame.size.width),152clamp(self.ctrlView.frame.origin.y + current.y - previous.y, 0, self.view.frame.size.height - self.ctrlView.frame.size.height),153clamp(self.ctrlView.frame.size.width * sender.scale, self.view.frame.size.width / 2, self.view.frame.size.width),154clamp(self.ctrlView.frame.size.height * sender.scale, self.view.frame.size.height / 2, self.view.frame.size.height)155);156self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.ctrlView.frame), CGRectGetMaxY(self.ctrlView.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);157158previous = current;159160sender.scale = 1.0;161}162163- (void)loadControlFile:(NSString *)file {164[self.ctrlView loadControlFile:file];165for (ControlButton *button in self.ctrlView.subviews) {166[button addGestureRecognizer:[[UITapGestureRecognizer alloc]167initWithTarget:self action:@selector(showControlPopover:)]];168[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]169initWithTarget:self action:@selector(onTouch:)]];170}171}172173- (void)viewDidLayoutSubviews {174if (self.navigationBar.hidden) {175self.ctrlView.frame = getSafeArea();176}177178// Update dynamic position for each view179for (UIView *view in self.ctrlView.subviews) {180if ([view isKindOfClass:[ControlButton class]]) {181[(ControlButton *)view update];182}183}184}185186- (void)changeSafeAreaSelection:(UISegmentedControl *)sender {187switch (sender.selectedSegmentIndex) {188case 0:189self.ctrlView.frame = self.view.frame;190break;191case 1:192self.ctrlView.frame = UIEdgeInsetsInsetRect(self.view.frame, getDefaultSafeArea());193break;194case 2:195self.ctrlView.frame = getSafeArea();196break;197}198self.ctrlView.userInteractionEnabled = sender.selectedSegmentIndex == 2;199self.resizeView.hidden = sender.selectedSegmentIndex != 2;200}201202- (void)loadSafeAreaSelectionFor:(UISegmentedControl *)control {203if (CGRectEqualToRect(self.ctrlView.frame, UIScreen.mainScreen.bounds)) {204control.selectedSegmentIndex = 0;205} else {206control.selectedSegmentIndex = !CGRectEqualToRect(self.ctrlView.frame, UIEdgeInsetsInsetRect(self.view.frame, getDefaultSafeArea())) + 1;207}208}209210- (void)showControlPopover:(UIGestureRecognizer *)sender {211self.currentGesture = sender;212213if (sender.state != UIGestureRecognizerStateBegan &&214sender.state != UIGestureRecognizerStateEnded) {215return;216}217218UIMenuController *menuController = [UIMenuController sharedMenuController];219220if (![sender.view isKindOfClass:[ControlButton class]]) {221UIMenuItem *actionExit = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.exit", nil) action:@selector(actionMenuExit)];222UIMenuItem *actionSave = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.save", nil) action:@selector(actionMenuSave)];223UIMenuItem *actionLoad = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.load", nil) action:@selector(actionMenuLoad)];224UIMenuItem *actionSafeArea = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.safe_area", nil) action:@selector(actionMenuSafeArea)];225UIMenuItem *actionAddButton = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.add_button", nil) action:@selector(actionMenuAddButton)];226UIMenuItem *actionAddDrawer = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.add_drawer", nil) action:@selector(actionMenuAddDrawer)];227UIMenuItem *actionAddJoystick = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.add_joystick", nil) action:@selector(actionMenuAddJoystick)];228[menuController setMenuItems:@[actionExit, actionSave, actionLoad, actionSafeArea, actionAddButton, actionAddDrawer, actionAddJoystick]];229230CGPoint point = [sender locationInView:sender.view];231self.selectedPoint = CGRectMake(point.x, point.y, 1.0, 1.0);232} else {233UIMenuItem *actionEdit = [[UIMenuItem alloc] initWithTitle:localize(@"Edit", nil) action:@selector(actionMenuBtnEdit)];234UIMenuItem *actionCopy = [[UIMenuItem alloc] initWithTitle:localize(@"Copy", nil) action:@selector(actionMenuBtnCopy)];235UIMenuItem *actionDelete = [[UIMenuItem alloc] initWithTitle:localize(@"Remove", nil) action:@selector(actionMenuBtnDelete)];236if ([sender.view isKindOfClass:[ControlDrawer class]]) {237UIMenuItem *actionAddSubButton = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.button_menu.add_subbutton", nil) action:@selector(actionMenuAddSubButton)];238[menuController setMenuItems:@[actionEdit, /* actionCopy, */ actionDelete, actionAddSubButton]];239} else {240[menuController setMenuItems:@[actionEdit, /* actionCopy, */ actionDelete]];241}242self.selectedPoint = sender.view.bounds;243}244245if (sender.view != self.ctrlView) {246[self.ctrlView becomeFirstResponder];247}248[sender.view becomeFirstResponder];249250self.resizeView.hidden = sender.view == self.ctrlView;251[self setButtonMenuVisibleForView:sender.view];252}253254- (void)actionMenuExit {255if (self.undoManager.canUndo) {256[self actionMenuSaveWithExit:YES];257return;258}259[self dismissViewControllerAnimated:!isInGame completion:nil];260}261262- (void)actionMenuSaveWithExit:(BOOL)exit {263UIAlertController *controller = [UIAlertController alertControllerWithTitle: localize(@"custom_controls.control_menu.save", nil)264message:exit?localize(@"custom_controls.control_menu.exit.warn", nil):@""265preferredStyle:UIAlertControllerStyleAlert];266[controller addTextFieldWithConfigurationHandler:^(UITextField *textField) {267textField.placeholder = @"Name";268textField.text = self.currentFileName;269textField.clearButtonMode = UITextFieldViewModeWhileEditing;270textField.borderStyle = UITextBorderStyleRoundedRect;271}];272[controller addAction:[UIAlertAction actionWithTitle:localize(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {273NSArray *textFields = controller.textFields;274UITextField *field = textFields[0];275NSError *error;276NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self.ctrlView.layoutDictionary options:NSJSONWritingPrettyPrinted error:&error];277if (jsonData == nil) {278showDialog(localize(@"custom_controls.control_menu.save.error.json", nil), error.localizedDescription);279return;280}281BOOL success = [jsonData writeToFile:[NSString stringWithFormat:@"%s/controlmap/%@.json", getenv("POJAV_HOME"), field.text] options:NSDataWritingAtomic error:&error];282if (!success) {283showDialog(localize(@"custom_controls.control_menu.save.error.write", nil), error.localizedDescription);284return;285}286287if (exit) {288[self dismissViewControllerAnimated:!isInGame completion:nil];289}290291self.currentFileName = field.text;292[self.undoManager removeAllActions];293}]];294if (exit) {295[controller addAction:[UIAlertAction actionWithTitle:localize(@"custom_controls.control_menu.discard_changes", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {296[self dismissViewControllerAnimated:!isInGame completion:nil];297}]];298}299[controller addAction:[UIAlertAction actionWithTitle:localize(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]];300[self presentViewController:controller animated:YES completion:nil];301}302303- (void)actionMenuSave {304[self actionMenuSaveWithExit:NO];305}306307- (void)actionOpenFilePicker:(void (^)(NSString *name))handler {308FileListViewController *vc = [[FileListViewController alloc] init];309vc.listPath = [NSString stringWithFormat:@"%s/controlmap", getenv("POJAV_HOME")];310vc.whenItemSelected = handler;311vc.modalPresentationStyle = UIModalPresentationPopover;312vc.preferredContentSize = CGSizeMake(350, 250);313314UIPopoverPresentationController *popoverController = [vc popoverPresentationController];315popoverController.sourceView = self.view;316popoverController.sourceRect = self.selectedPoint;317popoverController.permittedArrowDirections = UIPopoverArrowDirectionAny;318popoverController.delegate = self;319[self presentViewController:vc animated:YES completion:nil];320}321322- (void)actionMenuLoad {323[self actionOpenFilePicker:^void(NSString* name) {324self.currentFileName = name;325name = [NSString stringWithFormat:@"%@.json", name];326[self loadControlFile:name];327self.setDefaultCtrl(name);328}];329}330331- (void)actionMenuSafeArea {332// Set _UIBarBackground alpha to 0.8333self.navigationBar.subviews[0].alpha = 0.8;334335BOOL isCustom = ((UISegmentedControl *)self.navigationBar.items[0].titleView).selectedSegmentIndex == 2;336337self.navigationBar.hidden = !self.navigationBar.hidden;338self.ctrlView.layer.borderWidth = self.navigationBar.hidden ? 0 : 2;339self.ctrlView.userInteractionEnabled = self.navigationBar.hidden || isCustom;340self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.ctrlView.frame), CGRectGetMaxY(self.ctrlView.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);341self.resizeView.hidden = self.navigationBar.hidden || !isCustom;342self.resizeView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;343self.resizeView.target = nil;344}345346- (void)actionMenuSafeAreaCancel {347self.ctrlView.frame = getSafeArea();348[self actionMenuSafeArea];349}350351- (void)actionMenuSafeAreaDone {352setSafeArea(self.ctrlView.frame);353[self actionMenuSafeArea];354}355356- (void)actionMenuAddButtonWithDrawer:(ControlDrawer *)drawer {357NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];358dict[@"name"] = @"New";359dict[@"keycodes"] = @[@0, @0, @0, @0].mutableCopy;360dict[@"dynamicX"] = @"0";361dict[@"dynamicY"] = @"0";362dict[@"width"] = @(50.0);363dict[@"height"] = @(50.0);364dict[@"opacity"] = @(1);365dict[@"cornerRadius"] = @(0);366dict[@"bgColor"] = @(0x4d000000);367ControlButton *button;368if (drawer == nil) {369dict[@"displayInGame"] = dict[@"displayInMenu"] = @YES;370button = [ControlButton buttonWithProperties:dict];371[self doAddButton:button atIndex:@([self.ctrlView.layoutDictionary[@"mControlDataList"] count])];372[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];373[button update];374} else {375button = [ControlSubButton buttonWithProperties:dict];376((ControlSubButton *)button).parentDrawer = drawer;377[self doAddButton:button atIndex:@(drawer.buttons.count)];378[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];379[button update];380[drawer syncButtons];381}382383[button addGestureRecognizer:[[UITapGestureRecognizer alloc]384initWithTarget:self action:@selector(showControlPopover:)]];385[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]386initWithTarget:self action:@selector(onTouch:)]];387}388389- (void)actionMenuAddButton {390[self actionMenuAddButtonWithDrawer:nil];391}392393- (void)actionMenuAddDrawer {394NSMutableDictionary *properties = [[NSMutableDictionary alloc] init];395properties[@"name"] = @"New";396properties[@"dynamicX"] = @"0";397properties[@"dynamicY"] = @"0";398properties[@"width"] = @(50.0);399properties[@"height"] = @(50.0);400properties[@"opacity"] = @(1);401properties[@"cornerRadius"] = @(0);402properties[@"bgColor"] = @(0x4d000000);403properties[@"displayInGame"] = properties[@"displayInMenu"] = @YES;404NSMutableDictionary *data = [[NSMutableDictionary alloc] init];405data[@"orientation"] = @"FREE";406data[@"properties"] = properties;407data[@"buttonProperties"] = [[NSMutableArray alloc] init];408ControlDrawer *button = [ControlDrawer buttonWithData:data];409[self doAddButton:button atIndex:@([self.ctrlView.layoutDictionary[@"mDrawerDataList"] count])];410[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];411[button update];412413[button addGestureRecognizer:[[UITapGestureRecognizer alloc]414initWithTarget:self action:@selector(showControlPopover:)]];415[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]416initWithTarget:self action:@selector(onTouch:)]];417}418419- (void)actionMenuAddSubButton {420self.selectedPoint = CGRectMake(self.currentGesture.view.frame.origin.x + 25.0, self.currentGesture.view.frame.origin.y + 25.0, 1.0, 1.0);421[self actionMenuAddButtonWithDrawer:(ControlDrawer *)self.currentGesture.view];422}423424- (void)actionMenuAddJoystick {425NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];426dict[@"dynamicX"] = @"0";427dict[@"dynamicY"] = @"0";428dict[@"width"] = @(100.0);429dict[@"height"] = @(100.0);430dict[@"opacity"] = @(1);431dict[@"bgColor"] = @(0x4d000000);432dict[@"strokeColor"] = @(0xffffffff);433dict[@"displayInGame"] = dict[@"displayInMenu"] = @YES;434dict[@"forwardLock"] = @NO;435ControlJoystick *button = [ControlJoystick buttonWithProperties:dict];436[self doAddButton:button atIndex:@([self.ctrlView.layoutDictionary[@"mJoystickDataList"] count])];437[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];438[button update];439[button addGestureRecognizer:[[UITapGestureRecognizer alloc]440initWithTarget:self action:@selector(showControlPopover:)]];441[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]442initWithTarget:self action:@selector(onTouch:)]];443}444445- (void)actionMenuBtnCopy {446// copy447}448449- (void)actionMenuBtnDelete {450self.resizeView.hidden = YES;451ControlButton *button = (ControlButton *)self.currentGesture.view;452[self doRemoveButton:button];453}454455- (void)actionMenuBtnEdit {456CCMenuViewController *vc = [[CCMenuViewController alloc] init];457vc.modalPresentationStyle = UIModalPresentationOverFullScreen;458vc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;459vc.preferredContentSize = self.view.frame.size;460if (![self.currentGesture isKindOfClass:[UILongPressGestureRecognizer class]]) {461vc.targetButton = (ControlButton *)self.currentGesture.view;462}463[self presentViewController:vc animated:YES completion:nil];464}465466- (void)setButtonMenuVisibleForView:(UIView *)view {467self.resizeView.layer.maskedCorners = kCALayerMaxXMaxYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;468self.resizeView.target = (ControlButton *)view;469UIMenuController *menuController = [UIMenuController sharedMenuController];470if (view) {471[menuController showMenuFromView:view rect:self.selectedPoint];472} else {473[menuController hideMenu];474}475476if (view) {477CGPoint origin = [self.ctrlView convertPoint:view.frame.origin toView:self.view];478self.resizeView.frame = CGRectMake(origin.x + view.frame.size.width, origin.y + view.frame.size.height, self.resizeView.frame.size.width, self.resizeView.frame.size.height);479}480}481482- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {483return UIRectEdgeAll;484}485486- (BOOL)prefersHomeIndicatorAutoHidden {487return getPrefBool(@"debug.debug_hide_home_indicator");488}489490- (BOOL)prefersStatusBarHidden {491return YES;492}493494- (void)onTouchAreaHandleView:(UIPanGestureRecognizer *)sender {495if (sender.state != UIGestureRecognizerStateChanged) return;496CGPoint translation = [sender translationInView:sender.view];497498// Perform safe area resize499CGRect targetFrame = self.ctrlView.frame;500targetFrame.size.width += translation.x;501targetFrame.size.height += translation.y;502self.ctrlView.frame = targetFrame;503504// Keep track of handle view location505targetFrame = self.resizeView.frame;506targetFrame.origin.x = CGRectGetMaxX(self.ctrlView.frame) - targetFrame.size.width;507targetFrame.origin.y = CGRectGetMaxY(self.ctrlView.frame) - targetFrame.size.height;508self.resizeView.frame = targetFrame;509510[sender setTranslation:CGPointZero inView:sender.view];511}512513- (void)onTouchButtonHandleView:(UIPanGestureRecognizer *)sender {514static CGRect origButtonRect;515516CGPoint translation = [sender translationInView:sender.view];517CGFloat width, height;518519switch (sender.state) {520case UIGestureRecognizerStateBegan: {521// Save old button frame522origButtonRect = self.resizeView.target.frame;523} break;524case UIGestureRecognizerStateChanged: {525// Perform button resize526width = MAX(10, [self.resizeView.target.properties[@"width"] floatValue] + translation.x);527height = MAX(10, [self.resizeView.target.properties[@"height"] floatValue] + translation.y);528self.resizeView.target.properties[@"width"] = @(width);529self.resizeView.target.properties[@"height"] = @(height);530[self.resizeView.target update];531[sender setTranslation:CGPointZero inView:sender.view];532533// Keep track of handle view location534self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.resizeView.target.frame), CGRectGetMaxY(self.resizeView.target.frame),535self.resizeView.frame.size.width, self.resizeView.frame.size.height);536} break;537case UIGestureRecognizerStateCancelled:538case UIGestureRecognizerStateEnded: {539[self doMoveOrResizeButton:self.resizeView.target from:origButtonRect to:self.resizeView.target.frame];540} break;541default: break;542}543}544545- (void)onTouch:(UIPanGestureRecognizer *)sender {546static CGRect origButtonRect;547548if ([sender.view isKindOfClass:ControlHandleView.class]) {549if (self.resizeView.target == nil) {550[self onTouchAreaHandleView:sender];551} else if ([self.resizeView.target isKindOfClass:ControlButton.class]) {552[self onTouchButtonHandleView:sender];553}554return;555}556557CGPoint translation = [sender translationInView:sender.view];558559ControlButton *button = (ControlButton *)sender.view;560if ([button isKindOfClass:ControlSubButton.class] &&561![((ControlSubButton *)button).parentDrawer.drawerData[@"orientation"] isEqualToString:@"FREE"]) return;562563switch (sender.state) {564case UIGestureRecognizerStateBegan: {565origButtonRect = button.frame;566[self setButtonMenuVisibleForView:nil];567self.resizeView.hidden = NO;568self.resizeView.target = button;569} break;570case UIGestureRecognizerStateChanged: {571//button.center = CGPointMake(button.center.x + translation.x, button.center.y + translation.y);572[button snapAndAlignX:clamp(button.frame.origin.x+translation.x, 0, self.ctrlView.frame.size.width - button.frame.size.width) Y:clamp(button.frame.origin.y+translation.y, 0, self.ctrlView.frame.size.height - button.frame.size.height)];573[sender setTranslation:CGPointZero inView:button];574self.resizeView.frame = CGRectMake(CGRectGetMaxX(button.frame), CGRectGetMaxY(button.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);575} break;576case UIGestureRecognizerStateCancelled:577case UIGestureRecognizerStateEnded: {578[self doMoveOrResizeButton:button from:origButtonRect to:button.frame];579} break;580default: break;581}582}583584#pragma mark - UIPopoverPresentationControllerDelegate585- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection {586return UIModalPresentationNone;587}588589@end590591#define TAG_SLIDER_STROKEWIDTH 10592593#define VISIBILITY_ALWAYS 0594#define VISIBILITY_IN_GAME 1595#define VISIBILITY_IN_MENU 2596597#pragma mark - CCMenuViewController598599CGFloat currentY;600601@interface CCMenuViewController () <UIPickerViewDataSource, UIPickerViewDelegate> {602}603604@property(nonatomic) NSMutableArray *keyCodeMap, *keyValueMap;605@property(nonatomic) NSArray *arrOrientation, *arrVisibility;606@property(nonatomic) NSMutableDictionary* oldProperties;607608@property UITextField *activeField;609@property(nonatomic) UIScrollView* scrollView;610@property(nonatomic) UITextField *editName, *editSizeWidth, *editSizeHeight;611@property(nonatomic) UITextView* editMapping;612@property(nonatomic) UIPickerView* pickerMapping;613@property(nonatomic) UISegmentedControl *ctrlOrientation, *ctrlVisibility;614@property(nonatomic) UISwitch *switchFwdLock, *switchToggleable, *switchMousePass, *switchSwipeable;615@property(nonatomic) UIColorWell *colorWellBackground, *colorWellStroke;616@property(nonatomic) DBNumberedSlider *sliderStrokeWidth, *sliderCornerRadius, *sliderOpacity;617618@end619620@implementation CCMenuViewController621622- (UILabel*)addLabel:(NSString *)name {623UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0, currentY, 0.0, 0.0)];624label.text = name;625label.numberOfLines = 0;626[label sizeToFit];627[self.scrollView addSubview:label];628return label;629}630631- (void)viewDidLoad {632[super viewDidLoad];633634self.keyCodeMap = [[NSMutableArray alloc] init];635self.keyValueMap = [[NSMutableArray alloc] init];636initKeycodeTable(self.keyCodeMap, self.keyValueMap);637638self.oldProperties = self.targetButton.properties.mutableCopy;639currentY = 6.0;640641CGFloat shortest = MIN(self.view.frame.size.width, self.view.frame.size.height);642CGFloat tempW = MIN(self.view.frame.size.width * 0.75, shortest);643CGFloat tempH = MIN(self.view.frame.size.height * 0.6, shortest);644645UIBlurEffectStyle blurStyle = UIBlurEffectStyleSystemMaterial;646UIVisualEffectView *blurView;647blurView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:blurStyle]];648blurView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;649blurView.frame = CGRectMake(650(self.view.frame.size.width - MAX(tempW, tempH))/2,651(self.view.frame.size.height - MIN(tempW, tempH))/2,652MAX(tempW, tempH), MIN(tempW, tempH));653blurView.layer.cornerRadius = 10.0;654blurView.clipsToBounds = YES;655[self.view addSubview:blurView];656657UIBarButtonItem *btnFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];658659UIToolbar *popoverToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, blurView.frame.size.width, 44.0)];660UIPanGestureRecognizer *dragVCGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragViewController:)];661dragVCGesture.minimumNumberOfTouches = 1;662dragVCGesture.maximumNumberOfTouches = 1;663[popoverToolbar addGestureRecognizer:dragVCGesture];664665UIBarButtonItem *popoverCancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(actionEditCancel)];666UIBarButtonItem *popoverDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionEditFinish)];667popoverToolbar.items = @[popoverCancelButton, btnFlexibleSpace, popoverDoneButton];668[blurView.contentView addSubview:popoverToolbar];669670self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5.0, popoverToolbar.frame.size.height, blurView.frame.size.width - 10.0, blurView.frame.size.height - popoverToolbar.frame.size.height)];671self.scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;672[blurView.contentView addSubview:self.scrollView];673674UIToolbar *editPickToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, blurView.frame.size.width, 44.0)];675676UIBarButtonItem *editDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeTextField)];677editPickToolbar.items = @[btnFlexibleSpace, editDoneButton];678679CGFloat width = blurView.frame.size.width - 10.0;680CGFloat height = blurView.frame.size.height - 10.0;681682683// Property: Name684if (![self.targetButton isKindOfClass:ControlJoystick.class]) {685UILabel *labelName = [self addLabel:localize(@"custom_controls.button_edit.name", nil)];686self.editName = [[UITextField alloc] initWithFrame:CGRectMake(labelName.frame.size.width + 5.0, currentY, width - labelName.frame.size.width - 5.0, labelName.frame.size.height)];687[self.editName addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];688[self.editName addTarget:self.editName action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];689self.editName.placeholder = localize(@"custom_controls.button_edit.name", nil);690self.editName.returnKeyType = UIReturnKeyDone;691self.editName.text = self.targetButton.properties[@"name"];692[self.scrollView addSubview:self.editName];693currentY += labelName.frame.size.height + 15.0;694}695696if (![self.targetButton isKindOfClass:ControlSubButton.class] ||697[((ControlSubButton *)self.targetButton).parentDrawer.drawerData[@"orientation"] isEqualToString:@"FREE"]) {698// Property: Size699UILabel *labelSize = [self addLabel:localize(@"custom_controls.button_edit.size", nil)];700// width / 2.0 + (labelSize.frame.size.width + 4.0) / 2.0701CGFloat editSizeWidthValue = (width - labelSize.frame.size.width) / 2 - labelSize.frame.size.height / 2;702UILabel *labelSizeX = [[UILabel alloc] initWithFrame:CGRectMake(labelSize.frame.size.width + editSizeWidthValue, labelSize.frame.origin.y, labelSize.frame.size.height, labelSize.frame.size.height)];703labelSizeX.text = @"x";704[self.scrollView addSubview:labelSizeX];705self.editSizeWidth = [[UITextField alloc] initWithFrame:CGRectMake(labelSize.frame.size.width, labelSize.frame.origin.y, editSizeWidthValue, labelSize.frame.size.height)];706[self.editSizeWidth addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];707[self.editSizeWidth addTarget:self.editSizeWidth action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];708self.editSizeWidth.keyboardType = UIKeyboardTypeDecimalPad;709self.editSizeWidth.placeholder = @"width";710self.editSizeWidth.returnKeyType = UIReturnKeyDone;711self.editSizeWidth.text = [self.targetButton.properties[@"width"] stringValue];712self.editSizeWidth.textAlignment = NSTextAlignmentCenter;713[self.scrollView addSubview:self.editSizeWidth];714self.editSizeHeight = [[UITextField alloc] initWithFrame:CGRectMake(labelSizeX.frame.origin.x + labelSizeX.frame.size.width, labelSize.frame.origin.y, editSizeWidthValue, labelSize.frame.size.height)];715[self.editSizeHeight addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];716[self.editSizeHeight addTarget:self.editSizeHeight action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];717self.editSizeHeight.keyboardType = UIKeyboardTypeDecimalPad;718self.editSizeHeight.placeholder = @"height";719self.editSizeHeight.returnKeyType = UIReturnKeyDone;720self.editSizeHeight.text = [self.targetButton.properties[@"height"] stringValue];721self.editSizeHeight.textAlignment = NSTextAlignmentCenter;722[self.scrollView addSubview:self.editSizeHeight];723currentY += labelSize.frame.size.height + 15.0;724}725726727if ([self.targetButton isKindOfClass:ControlDrawer.class]) {728// Property: Orientation729self.arrOrientation = @[@"DOWN", @"LEFT", @"UP", @"RIGHT", @"FREE"];730UILabel *labelOrientation = [self addLabel:localize(@"custom_controls.button_edit.orientation", nil)];731self.ctrlOrientation = [[UISegmentedControl alloc] initWithItems:self.arrOrientation];732[self.ctrlOrientation addTarget:self action:@selector(orientationValueChanged:) forControlEvents:UIControlEventValueChanged];733self.ctrlOrientation.frame = CGRectMake(labelOrientation.frame.size.width + 5.0, currentY - 5.0, width - labelOrientation.frame.size.width - 5.0, 30.0);734self.ctrlOrientation.selectedSegmentIndex = [self.arrOrientation indexOfObject:735((ControlDrawer *)self.targetButton).drawerData[@"orientation"]];736[self.scrollView addSubview:self.ctrlOrientation];737currentY += labelOrientation.frame.size.height + 15.0;738} else if ([self.targetButton isKindOfClass:ControlJoystick.class]) {739// Property: Forward lock740UILabel *labelFwdLock = [self addLabel:localize(@"custom_controls.button_edit.forward_lock", nil)];741self.switchFwdLock = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];742[self.switchFwdLock setOn:[self.targetButton.properties[@"forwardLock"] boolValue] animated:NO];743[self.scrollView addSubview:self.switchFwdLock];744currentY += labelFwdLock.frame.size.height + 15.0;745} else {746// Property: Mapping747UILabel *labelMapping = [self addLabel:localize(@"custom_controls.button_edit.mapping", nil)];748749self.editMapping = [[UITextView alloc] initWithFrame:CGRectMake(0,0,1,1)];750self.editMapping.text = @"\n\n\n";751[self.editMapping sizeToFit];752self.editMapping.scrollEnabled = NO;753self.editMapping.frame = CGRectMake(labelMapping.frame.size.width + 5.0, labelMapping.frame.origin.y, width - labelMapping.frame.size.width - 5.0, self.editMapping.frame.size.height);754755self.pickerMapping = [[UIPickerView alloc] init];756self.pickerMapping.delegate = self;757self.pickerMapping.dataSource = self;758[self.pickerMapping reloadAllComponents];759for (int i = 0; i < 4; i++) {760[self.pickerMapping selectRow:[self.keyValueMap indexOfObject:self.targetButton.properties[@"keycodes"][i]] inComponent:i animated:NO];761}762[self pickerView:self.pickerMapping didSelectRow:0 inComponent:0];763764self.editMapping.inputAccessoryView = editPickToolbar;765self.editMapping.inputView = self.pickerMapping;766[self.scrollView addSubview:self.editMapping];767currentY += self.editMapping.frame.size.height + 15.0;768}769770771if (![self.targetButton isKindOfClass:ControlJoystick.class]) {772// Property: Toggleable773UILabel *labelToggleable = [self addLabel:localize(@"custom_controls.button_edit.toggleable", nil)];774self.switchToggleable = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];775[self.switchToggleable setOn:[self.targetButton.properties[@"isToggle"] boolValue] animated:NO];776[self.scrollView addSubview:self.switchToggleable];777currentY += labelToggleable.frame.size.height + 15.0;778779780// Property: Mouse pass781UILabel *labelMousePass = [self addLabel:localize(@"custom_controls.button_edit.mouse_pass", nil)];782self.switchMousePass = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];783[self.switchMousePass setOn:[self.targetButton.properties[@"passThruEnabled"] boolValue]];784[self.scrollView addSubview:self.switchMousePass];785currentY += labelMousePass.frame.size.height + 15.0;786787788// Property: Swipeable789UILabel *labelSwipeable = [self addLabel:localize(@"custom_controls.button_edit.swipeable", nil)];790self.switchSwipeable = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];791[self.switchSwipeable setOn:[self.targetButton.properties[@"isSwipeable"] boolValue]];792[self.scrollView addSubview:self.switchSwipeable];793currentY += labelSwipeable.frame.size.height + 15.0;794}795796797// Property: Background color798UILabel *labelBGColor = [self addLabel:localize(@"custom_controls.button_edit.bg_color", nil)];799self.colorWellBackground = [[UIColorWell alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];800[self.colorWellBackground addTarget:self action:@selector(colorWellChanged) forControlEvents:UIControlEventValueChanged];801self.colorWellBackground.selectedColor = convertARGB2UIColor([self.targetButton.properties[@"bgColor"] intValue]);802[self.scrollView addSubview:self.colorWellBackground];803currentY += labelBGColor.frame.size.height + 15.0;804805// Property: Stroke width806UILabel *labelStrokeWidth = [self addLabel:localize(@"custom_controls.button_edit.stroke_width", nil)];807self.sliderStrokeWidth = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelStrokeWidth.frame.size.width + 5.0, currentY - 5.0, width - labelStrokeWidth.frame.size.width - 5.0, 30.0)];808self.sliderStrokeWidth.continuous = YES;809self.sliderStrokeWidth.maximumValue = MAX([self.targetButton.properties[@"width"] intValue], [self.targetButton.properties[@"height"] intValue]) / 2;810self.sliderStrokeWidth.tag = TAG_SLIDER_STROKEWIDTH;811self.sliderStrokeWidth.value = [self.targetButton.properties[@"strokeWidth"] intValue];812[self.sliderStrokeWidth addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];813[self.scrollView addSubview:self.sliderStrokeWidth];814currentY += labelStrokeWidth.frame.size.height + 15.0;815816817// Property: Stroke color818UILabel *labelStrokeColor = [self addLabel:localize(@"custom_controls.button_edit.stroke_color", nil)];819self.colorWellStroke = [[UIColorWell alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];820[self.colorWellStroke addTarget:self action:@selector(colorWellChanged) forControlEvents:UIControlEventValueChanged];821self.colorWellStroke.selectedColor = convertARGB2UIColor([self.targetButton.properties[@"strokeColor"] intValue]);822[self.scrollView addSubview:self.colorWellStroke];823currentY += labelStrokeColor.frame.size.height + 15.0;824825826// Property: Corner radius827if (![self.targetButton isKindOfClass:ControlJoystick.class]) {828UILabel *labelCornerRadius = [self addLabel:localize(@"custom_controls.button_edit.corner_radius", nil)];829self.sliderCornerRadius = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelCornerRadius.frame.size.width + 5.0, currentY - 5.0, width - labelCornerRadius.frame.size.width - 5.0, 30.0)];830self.sliderCornerRadius.continuous = YES;831self.sliderCornerRadius.maximumValue = 100;832self.sliderCornerRadius.value = [self.targetButton.properties[@"cornerRadius"] intValue];833[self.sliderCornerRadius addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];834[self.scrollView addSubview:self.sliderCornerRadius];835currentY += labelCornerRadius.frame.size.height + 15.0;836}837838839// Property: Button Opacity840UILabel *labelOpacity = [self addLabel:localize(@"custom_controls.button_edit.opacity", nil)];841self.sliderOpacity = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelOpacity.frame.size.width + 5.0, currentY - 5.0, width - labelOpacity.frame.size.width - 5.0, 30.0)];842self.sliderOpacity.continuous = YES;843self.sliderOpacity.minimumValue = 1;844self.sliderOpacity.maximumValue = 100;845self.sliderOpacity.value = [self.targetButton.properties[@"opacity"] floatValue] * 100.0;846[self.sliderOpacity addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];847[self.scrollView addSubview:self.sliderOpacity];848currentY += labelOpacity.frame.size.height + 15.0;849850851// Property: Visibility852self.arrVisibility = @[localize(@"Always", nil), localize(@"In game", nil), localize(@"In menu", nil)];853UILabel *labelVisibility = [self addLabel:localize(@"custom_controls.button_edit.visibility", nil)];854self.ctrlVisibility = [[UISegmentedControl alloc] initWithItems:self.arrVisibility];855[self.ctrlVisibility addTarget:self action:@selector(visibilityValueChanged:) forControlEvents:UIControlEventValueChanged];856self.ctrlVisibility.frame = CGRectMake(labelVisibility.frame.size.width + 5.0, currentY - 5.0, width - labelVisibility.frame.size.width - 5.0, 30.0);857BOOL displayInGame = [self.targetButton.properties[@"displayInGame"] boolValue];858BOOL displayInMenu = [self.targetButton.properties[@"displayInMenu"] boolValue];859if (displayInGame && displayInMenu) {860self.ctrlVisibility.selectedSegmentIndex = VISIBILITY_ALWAYS;861} else if (displayInGame) {862self.ctrlVisibility.selectedSegmentIndex = VISIBILITY_IN_GAME;863} else if (displayInMenu) {864self.ctrlVisibility.selectedSegmentIndex = VISIBILITY_IN_MENU;865} // else the segment is not chosen866[self.scrollView addSubview:self.ctrlVisibility];867currentY += labelVisibility.frame.size.height + 15.0;868869self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, currentY);870}871872#pragma mark - Gesture callback873- (void)dragViewController:(UIPanGestureRecognizer *)sender {874static CGPoint lastPoint;875CGPoint point = [sender translationInView:self.view];876if (sender.state != UIGestureRecognizerStateBegan) {877CGRect rect = self.view.subviews[0].frame;878rect.origin.x = clamp(rect.origin.x - lastPoint.x + point.x, -self.view.frame.size.width/2, self.view.frame.size.width - sender.view.frame.size.width/2);879rect.origin.y = clamp(rect.origin.y - lastPoint.y + point.y, 0, self.view.frame.size.height - sender.view.frame.size.height);880self.view.subviews[0].frame = rect;881}882lastPoint = point;883}884885#pragma mark - Color picker functions886887- (void)colorWellChanged {888self.targetButton.properties[@"bgColor"] = @(convertUIColor2ARGB(self.colorWellBackground.selectedColor));889self.targetButton.properties[@"strokeColor"] = @(convertUIColor2ARGB(self.colorWellStroke.selectedColor));890[self.targetButton update];891}892893- (void)textFieldEditingChanged {894self.targetButton.properties[@"name"] = self.editName.text;895self.targetButton.properties[@"width"] = @([self.editSizeWidth.text floatValue]);896self.targetButton.properties[@"height"] = @([self.editSizeHeight.text floatValue]);897[self.targetButton update];898}899900#pragma mark - Control editor901- (void)actionEditCancel {902self.targetButton.properties = self.oldProperties;903[self.targetButton update];904[self dismissViewControllerAnimated:YES completion:nil];905}906907- (void)actionEditFinish {908if (self.switchFwdLock) {909self.targetButton.properties[@"forwardLock"] = @(self.switchFwdLock.isOn);910}911self.targetButton.properties[@"isToggle"] = @(self.switchToggleable.isOn);912self.targetButton.properties[@"passThruEnabled"] = @(self.switchMousePass.isOn);913self.targetButton.properties[@"isSwipeable"] = @(self.switchSwipeable.isOn);914915NSMutableDictionary *newProperties = self.targetButton.properties.mutableCopy;916917for (NSString *key in self.oldProperties) {918if ([self.oldProperties[key] isEqual:newProperties[key]]) {919[newProperties removeObjectForKey:key];920}921}922923[(CustomControlsViewController *)self.presentingViewController924doUpdateButton:self.targetButton from:self.oldProperties to:newProperties];925self.oldProperties = nil;926[self dismissViewControllerAnimated:YES completion:nil];927}928929- (void)orientationValueChanged:(UISegmentedControl *)sender {930((ControlDrawer *)self.targetButton).drawerData[@"orientation"] =931self.arrOrientation[sender.selectedSegmentIndex];932[(ControlDrawer *)self.targetButton syncButtons];933}934935- (void)sliderValueChanged:(DBNumberedSlider *)sender {936if (sender.tag == TAG_SLIDER_STROKEWIDTH) {937self.colorWellStroke.enabled = sender.value != 0;938self.targetButton.properties[@"strokeWidth"] = @((NSInteger) self.sliderStrokeWidth.value);939} else {940[sender setValue:(NSInteger)sender.value animated:NO];941self.targetButton.properties[@"cornerRadius"] = @((NSInteger) self.sliderCornerRadius.value);942self.targetButton.properties[@"opacity"] = @(self.sliderOpacity.value / 100.0);943}944[self.targetButton update];945}946947- (void)visibilityValueChanged:(UISegmentedControl *)sender {948self.targetButton.properties[@"displayInGame"] = [NSNumber numberWithBool:sender.selectedSegmentIndex != VISIBILITY_IN_MENU];949self.targetButton.properties[@"displayInMenu"] = [NSNumber numberWithBool:sender.selectedSegmentIndex != VISIBILITY_IN_GAME];950}951952#pragma mark - UIPickerView stuff953- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view954{955UILabel *label = (UILabel *)view;956if (label == nil) {957label = [UILabel new];958label.adjustsFontSizeToFitWidth = YES;959label.minimumScaleFactor = 0.5;960label.textAlignment = NSTextAlignmentCenter;961}962label.text = [self pickerView:pickerView titleForRow:row forComponent:component];963964return label;965}966967- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {968self.editMapping.text = [NSString stringWithFormat:@"1: %@\n2: %@\n3: %@\n4: %@",969self.keyCodeMap[[pickerView selectedRowInComponent:0]],970self.keyCodeMap[[pickerView selectedRowInComponent:1]],971self.keyCodeMap[[pickerView selectedRowInComponent:2]],972self.keyCodeMap[[pickerView selectedRowInComponent:3]]973];974975for (int i = 0; i < 4; i++) {976self.targetButton.properties[@"keycodes"][i] = self.keyValueMap[[self.pickerMapping selectedRowInComponent:i]];977}978}979980- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {981return 4;982}983984- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {985return self.keyCodeMap.count;986}987988- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {989return self.keyCodeMap[row];990}991992- (void)closeTextField {993[self.editMapping endEditing:YES];994}995996@end997998999