Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/PojavLauncher_iOS
Path: blob/main/Natives/CustomControlsViewController.m
589 views
1
#import "CustomControlsViewController.h"
2
#import "DBNumberedSlider.h"
3
#import "FileListViewController.h"
4
#import "LauncherPreferences.h"
5
#import "ios_uikit_bridge.h"
6
7
#import "customcontrols/ControlDrawer.h"
8
#import "customcontrols/ControlJoystick.h"
9
#import "customcontrols/CustomControlsUtils.h"
10
11
#include "glfw_keycodes.h"
12
#include "utils.h"
13
14
@implementation ControlHandleView
15
// Nothing
16
@end
17
18
@interface CustomControlsViewController () <UIGestureRecognizerDelegate, UIPopoverPresentationControllerDelegate>{
19
}
20
21
@property(nonatomic) NSString* currentFileName;
22
@property(nonatomic) CGRect selectedPoint;
23
@property(nonatomic) UINavigationBar* navigationBar;
24
25
@end
26
27
@implementation CustomControlsViewController
28
#define isInGame [self.presentingViewController respondsToSelector:@selector(loadCustomControls)]
29
30
- (void)viewDidLoad
31
{
32
[super viewDidLoad];
33
[self.undoManager removeAllActions];
34
self.view.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.5];
35
isControlModifiable = YES;
36
37
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
38
[self setNeedsUpdateOfHomeIndicatorAutoHidden];
39
40
CGRect screenBounds = [[UIScreen mainScreen] bounds];
41
UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets;
42
43
UILabel *guideLabel = [[UILabel alloc] initWithFrame:self.view.frame];
44
guideLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
45
guideLabel.numberOfLines = 0;
46
guideLabel.textAlignment = NSTextAlignmentCenter;
47
guideLabel.textColor = UIColor.whiteColor;
48
guideLabel.text = localize(@"custom_controls.hint", nil);
49
[self.view addSubview:guideLabel];
50
51
self.ctrlView = [[ControlLayout alloc] initWithFrame:getSafeArea()];
52
self.ctrlView.layer.borderColor = UIColor.labelColor.CGColor;
53
[self.view addSubview:self.ctrlView];
54
55
// Prepare the navigation bar for safe area customization
56
UINavigationItem *navigationItem = [[UINavigationItem alloc] init];
57
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"None", @"Default", @"Custom"]];
58
[segmentedControl addTarget:self action:@selector(changeSafeAreaSelection:) forControlEvents:UIControlEventValueChanged];
59
[segmentedControl setEnabled:(insets.left+insets.right)>0 forSegmentAtIndex:1];
60
[self loadSafeAreaSelectionFor:segmentedControl];
61
navigationItem.titleView = segmentedControl;
62
navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(actionMenuSafeAreaCancel)];
63
navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionMenuSafeAreaDone)];
64
self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44.0)];
65
self.navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
66
self.navigationBar.hidden = YES;
67
self.navigationBar.items = @[navigationItem];
68
self.navigationBar.translucent = YES;
69
[self.view addSubview:self.navigationBar];
70
71
CGFloat buttonScale = getPrefFloat(@"control.button_scale") / 100.0;
72
73
self.resizeView = [[ControlHandleView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
74
self.resizeView.backgroundColor = self.view.tintColor;
75
self.resizeView.layer.cornerRadius = self.resizeView.frame.size.width / 2;
76
self.resizeView.clipsToBounds = YES;
77
self.resizeView.hidden = YES;
78
[self.resizeView addGestureRecognizer:[[UIPanGestureRecognizer alloc]
79
initWithTarget:self action:@selector(onTouch:)]];
80
[self.view addSubview:self.resizeView];
81
82
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panControlArea:)];
83
panGesture.delegate = self;
84
panGesture.maximumNumberOfTouches = 1;
85
[self.ctrlView addGestureRecognizer:panGesture];
86
87
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchControlArea:)];
88
pinchGesture.delegate = self;
89
[self.ctrlView addGestureRecognizer:pinchGesture];
90
91
UILongPressGestureRecognizer *longpressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showControlPopover:)];
92
longpressGesture.minimumPressDuration = 0.5;
93
[self.ctrlView addGestureRecognizer:longpressGesture];
94
NSString *fileName = self.getDefaultCtrl();
95
self.currentFileName = [fileName stringByDeletingPathExtension];
96
[self loadControlFile:fileName];
97
}
98
99
- (void)viewWillDisappear:(BOOL)animated {
100
[super viewWillDisappear:animated];
101
isControlModifiable = NO;
102
if (isInGame) {
103
[self.presentingViewController performSelector:@selector(loadCustomControls)];
104
}
105
}
106
107
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)sender shouldReceiveTouch:(UITouch *)touch {
108
return sender.view != self.view || !CGRectContainsPoint(self.resizeView.frame, [sender locationInView:self.view]);
109
}
110
/*
111
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)sender shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
112
return YES;
113
}
114
*/
115
- (void)panControlArea:(UIPanGestureRecognizer *)sender {
116
static CGPoint previous;
117
if (sender.state == UIGestureRecognizerStateBegan) {
118
[self setButtonMenuVisibleForView:nil];
119
self.resizeView.hidden = self.ctrlView.layer.borderWidth == 0;
120
self.resizeView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;
121
previous = [sender locationInView:self.view];
122
return;
123
} else if (self.navigationBar.hidden) {
124
return;
125
}
126
127
CGPoint current = [sender locationInView:self.view];
128
129
CGRect rect = self.ctrlView.frame;
130
rect.origin.x = clamp(rect.origin.x + current.x - previous.x, 0, self.view.frame.size.width - rect.size.width);
131
rect.origin.y = clamp(rect.origin.y + current.y - previous.y, 0, self.view.frame.size.height - rect.size.height);
132
self.ctrlView.frame = rect;
133
134
self.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);
135
136
previous = current;
137
}
138
139
- (void)pinchControlArea:(UIPinchGestureRecognizer *)sender {
140
if (sender.numberOfTouches < 2 || self.navigationBar.hidden) {
141
return;
142
}
143
144
static CGPoint previous;
145
CGPoint current = [sender locationInView:self.view];
146
if (sender.state == UIGestureRecognizerStateBegan) {
147
previous = current;
148
return;
149
}
150
151
self.ctrlView.frame = CGRectMake(
152
clamp(self.ctrlView.frame.origin.x + current.x - previous.x, 0, self.view.frame.size.width - self.ctrlView.frame.size.width),
153
clamp(self.ctrlView.frame.origin.y + current.y - previous.y, 0, self.view.frame.size.height - self.ctrlView.frame.size.height),
154
clamp(self.ctrlView.frame.size.width * sender.scale, self.view.frame.size.width / 2, self.view.frame.size.width),
155
clamp(self.ctrlView.frame.size.height * sender.scale, self.view.frame.size.height / 2, self.view.frame.size.height)
156
);
157
self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.ctrlView.frame), CGRectGetMaxY(self.ctrlView.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);
158
159
previous = current;
160
161
sender.scale = 1.0;
162
}
163
164
- (void)loadControlFile:(NSString *)file {
165
[self.ctrlView loadControlFile:file];
166
for (ControlButton *button in self.ctrlView.subviews) {
167
[button addGestureRecognizer:[[UITapGestureRecognizer alloc]
168
initWithTarget:self action:@selector(showControlPopover:)]];
169
[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]
170
initWithTarget:self action:@selector(onTouch:)]];
171
}
172
}
173
174
- (void)viewDidLayoutSubviews {
175
if (self.navigationBar.hidden) {
176
self.ctrlView.frame = getSafeArea();
177
}
178
179
// Update dynamic position for each view
180
for (UIView *view in self.ctrlView.subviews) {
181
if ([view isKindOfClass:[ControlButton class]]) {
182
[(ControlButton *)view update];
183
}
184
}
185
}
186
187
- (void)changeSafeAreaSelection:(UISegmentedControl *)sender {
188
switch (sender.selectedSegmentIndex) {
189
case 0:
190
self.ctrlView.frame = self.view.frame;
191
break;
192
case 1:
193
self.ctrlView.frame = UIEdgeInsetsInsetRect(self.view.frame, getDefaultSafeArea());
194
break;
195
case 2:
196
self.ctrlView.frame = getSafeArea();
197
break;
198
}
199
self.ctrlView.userInteractionEnabled = sender.selectedSegmentIndex == 2;
200
self.resizeView.hidden = sender.selectedSegmentIndex != 2;
201
}
202
203
- (void)loadSafeAreaSelectionFor:(UISegmentedControl *)control {
204
if (CGRectEqualToRect(self.ctrlView.frame, UIScreen.mainScreen.bounds)) {
205
control.selectedSegmentIndex = 0;
206
} else {
207
control.selectedSegmentIndex = !CGRectEqualToRect(self.ctrlView.frame, UIEdgeInsetsInsetRect(self.view.frame, getDefaultSafeArea())) + 1;
208
}
209
}
210
211
- (void)showControlPopover:(UIGestureRecognizer *)sender {
212
self.currentGesture = sender;
213
214
if (sender.state != UIGestureRecognizerStateBegan &&
215
sender.state != UIGestureRecognizerStateEnded) {
216
return;
217
}
218
219
UIMenuController *menuController = [UIMenuController sharedMenuController];
220
221
if (![sender.view isKindOfClass:[ControlButton class]]) {
222
UIMenuItem *actionExit = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.exit", nil) action:@selector(actionMenuExit)];
223
UIMenuItem *actionSave = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.save", nil) action:@selector(actionMenuSave)];
224
UIMenuItem *actionLoad = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.load", nil) action:@selector(actionMenuLoad)];
225
UIMenuItem *actionSafeArea = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.safe_area", nil) action:@selector(actionMenuSafeArea)];
226
UIMenuItem *actionAddButton = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.add_button", nil) action:@selector(actionMenuAddButton)];
227
UIMenuItem *actionAddDrawer = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.add_drawer", nil) action:@selector(actionMenuAddDrawer)];
228
UIMenuItem *actionAddJoystick = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.control_menu.add_joystick", nil) action:@selector(actionMenuAddJoystick)];
229
[menuController setMenuItems:@[actionExit, actionSave, actionLoad, actionSafeArea, actionAddButton, actionAddDrawer, actionAddJoystick]];
230
231
CGPoint point = [sender locationInView:sender.view];
232
self.selectedPoint = CGRectMake(point.x, point.y, 1.0, 1.0);
233
} else {
234
UIMenuItem *actionEdit = [[UIMenuItem alloc] initWithTitle:localize(@"Edit", nil) action:@selector(actionMenuBtnEdit)];
235
UIMenuItem *actionCopy = [[UIMenuItem alloc] initWithTitle:localize(@"Copy", nil) action:@selector(actionMenuBtnCopy)];
236
UIMenuItem *actionDelete = [[UIMenuItem alloc] initWithTitle:localize(@"Remove", nil) action:@selector(actionMenuBtnDelete)];
237
if ([sender.view isKindOfClass:[ControlDrawer class]]) {
238
UIMenuItem *actionAddSubButton = [[UIMenuItem alloc] initWithTitle:localize(@"custom_controls.button_menu.add_subbutton", nil) action:@selector(actionMenuAddSubButton)];
239
[menuController setMenuItems:@[actionEdit, /* actionCopy, */ actionDelete, actionAddSubButton]];
240
} else {
241
[menuController setMenuItems:@[actionEdit, /* actionCopy, */ actionDelete]];
242
}
243
self.selectedPoint = sender.view.bounds;
244
}
245
246
if (sender.view != self.ctrlView) {
247
[self.ctrlView becomeFirstResponder];
248
}
249
[sender.view becomeFirstResponder];
250
251
self.resizeView.hidden = sender.view == self.ctrlView;
252
[self setButtonMenuVisibleForView:sender.view];
253
}
254
255
- (void)actionMenuExit {
256
if (self.undoManager.canUndo) {
257
[self actionMenuSaveWithExit:YES];
258
return;
259
}
260
[self dismissViewControllerAnimated:!isInGame completion:nil];
261
}
262
263
- (void)actionMenuSaveWithExit:(BOOL)exit {
264
UIAlertController *controller = [UIAlertController alertControllerWithTitle: localize(@"custom_controls.control_menu.save", nil)
265
message:exit?localize(@"custom_controls.control_menu.exit.warn", nil):@""
266
preferredStyle:UIAlertControllerStyleAlert];
267
[controller addTextFieldWithConfigurationHandler:^(UITextField *textField) {
268
textField.placeholder = @"Name";
269
textField.text = self.currentFileName;
270
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
271
textField.borderStyle = UITextBorderStyleRoundedRect;
272
}];
273
[controller addAction:[UIAlertAction actionWithTitle:localize(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
274
NSArray *textFields = controller.textFields;
275
UITextField *field = textFields[0];
276
NSError *error;
277
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self.ctrlView.layoutDictionary options:NSJSONWritingPrettyPrinted error:&error];
278
if (jsonData == nil) {
279
showDialog(localize(@"custom_controls.control_menu.save.error.json", nil), error.localizedDescription);
280
return;
281
}
282
BOOL success = [jsonData writeToFile:[NSString stringWithFormat:@"%s/controlmap/%@.json", getenv("POJAV_HOME"), field.text] options:NSDataWritingAtomic error:&error];
283
if (!success) {
284
showDialog(localize(@"custom_controls.control_menu.save.error.write", nil), error.localizedDescription);
285
return;
286
}
287
288
if (exit) {
289
[self dismissViewControllerAnimated:!isInGame completion:nil];
290
}
291
292
self.currentFileName = field.text;
293
[self.undoManager removeAllActions];
294
}]];
295
if (exit) {
296
[controller addAction:[UIAlertAction actionWithTitle:localize(@"custom_controls.control_menu.discard_changes", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
297
[self dismissViewControllerAnimated:!isInGame completion:nil];
298
}]];
299
}
300
[controller addAction:[UIAlertAction actionWithTitle:localize(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
301
[self presentViewController:controller animated:YES completion:nil];
302
}
303
304
- (void)actionMenuSave {
305
[self actionMenuSaveWithExit:NO];
306
}
307
308
- (void)actionOpenFilePicker:(void (^)(NSString *name))handler {
309
FileListViewController *vc = [[FileListViewController alloc] init];
310
vc.listPath = [NSString stringWithFormat:@"%s/controlmap", getenv("POJAV_HOME")];
311
vc.whenItemSelected = handler;
312
vc.modalPresentationStyle = UIModalPresentationPopover;
313
vc.preferredContentSize = CGSizeMake(350, 250);
314
315
UIPopoverPresentationController *popoverController = [vc popoverPresentationController];
316
popoverController.sourceView = self.view;
317
popoverController.sourceRect = self.selectedPoint;
318
popoverController.permittedArrowDirections = UIPopoverArrowDirectionAny;
319
popoverController.delegate = self;
320
[self presentViewController:vc animated:YES completion:nil];
321
}
322
323
- (void)actionMenuLoad {
324
[self actionOpenFilePicker:^void(NSString* name) {
325
self.currentFileName = name;
326
name = [NSString stringWithFormat:@"%@.json", name];
327
[self loadControlFile:name];
328
self.setDefaultCtrl(name);
329
}];
330
}
331
332
- (void)actionMenuSafeArea {
333
// Set _UIBarBackground alpha to 0.8
334
self.navigationBar.subviews[0].alpha = 0.8;
335
336
BOOL isCustom = ((UISegmentedControl *)self.navigationBar.items[0].titleView).selectedSegmentIndex == 2;
337
338
self.navigationBar.hidden = !self.navigationBar.hidden;
339
self.ctrlView.layer.borderWidth = self.navigationBar.hidden ? 0 : 2;
340
self.ctrlView.userInteractionEnabled = self.navigationBar.hidden || isCustom;
341
self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.ctrlView.frame), CGRectGetMaxY(self.ctrlView.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);
342
self.resizeView.hidden = self.navigationBar.hidden || !isCustom;
343
self.resizeView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;
344
self.resizeView.target = nil;
345
}
346
347
- (void)actionMenuSafeAreaCancel {
348
self.ctrlView.frame = getSafeArea();
349
[self actionMenuSafeArea];
350
}
351
352
- (void)actionMenuSafeAreaDone {
353
setSafeArea(self.ctrlView.frame);
354
[self actionMenuSafeArea];
355
}
356
357
- (void)actionMenuAddButtonWithDrawer:(ControlDrawer *)drawer {
358
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
359
dict[@"name"] = @"New";
360
dict[@"keycodes"] = @[@0, @0, @0, @0].mutableCopy;
361
dict[@"dynamicX"] = @"0";
362
dict[@"dynamicY"] = @"0";
363
dict[@"width"] = @(50.0);
364
dict[@"height"] = @(50.0);
365
dict[@"opacity"] = @(1);
366
dict[@"cornerRadius"] = @(0);
367
dict[@"bgColor"] = @(0x4d000000);
368
ControlButton *button;
369
if (drawer == nil) {
370
dict[@"displayInGame"] = dict[@"displayInMenu"] = @YES;
371
button = [ControlButton buttonWithProperties:dict];
372
[self doAddButton:button atIndex:@([self.ctrlView.layoutDictionary[@"mControlDataList"] count])];
373
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
374
[button update];
375
} else {
376
button = [ControlSubButton buttonWithProperties:dict];
377
((ControlSubButton *)button).parentDrawer = drawer;
378
[self doAddButton:button atIndex:@(drawer.buttons.count)];
379
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
380
[button update];
381
[drawer syncButtons];
382
}
383
384
[button addGestureRecognizer:[[UITapGestureRecognizer alloc]
385
initWithTarget:self action:@selector(showControlPopover:)]];
386
[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]
387
initWithTarget:self action:@selector(onTouch:)]];
388
}
389
390
- (void)actionMenuAddButton {
391
[self actionMenuAddButtonWithDrawer:nil];
392
}
393
394
- (void)actionMenuAddDrawer {
395
NSMutableDictionary *properties = [[NSMutableDictionary alloc] init];
396
properties[@"name"] = @"New";
397
properties[@"dynamicX"] = @"0";
398
properties[@"dynamicY"] = @"0";
399
properties[@"width"] = @(50.0);
400
properties[@"height"] = @(50.0);
401
properties[@"opacity"] = @(1);
402
properties[@"cornerRadius"] = @(0);
403
properties[@"bgColor"] = @(0x4d000000);
404
properties[@"displayInGame"] = properties[@"displayInMenu"] = @YES;
405
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
406
data[@"orientation"] = @"FREE";
407
data[@"properties"] = properties;
408
data[@"buttonProperties"] = [[NSMutableArray alloc] init];
409
ControlDrawer *button = [ControlDrawer buttonWithData:data];
410
[self doAddButton:button atIndex:@([self.ctrlView.layoutDictionary[@"mDrawerDataList"] count])];
411
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
412
[button update];
413
414
[button addGestureRecognizer:[[UITapGestureRecognizer alloc]
415
initWithTarget:self action:@selector(showControlPopover:)]];
416
[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]
417
initWithTarget:self action:@selector(onTouch:)]];
418
}
419
420
- (void)actionMenuAddSubButton {
421
self.selectedPoint = CGRectMake(self.currentGesture.view.frame.origin.x + 25.0, self.currentGesture.view.frame.origin.y + 25.0, 1.0, 1.0);
422
[self actionMenuAddButtonWithDrawer:(ControlDrawer *)self.currentGesture.view];
423
}
424
425
- (void)actionMenuAddJoystick {
426
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
427
dict[@"dynamicX"] = @"0";
428
dict[@"dynamicY"] = @"0";
429
dict[@"width"] = @(100.0);
430
dict[@"height"] = @(100.0);
431
dict[@"opacity"] = @(1);
432
dict[@"bgColor"] = @(0x4d000000);
433
dict[@"strokeColor"] = @(0xffffffff);
434
dict[@"displayInGame"] = dict[@"displayInMenu"] = @YES;
435
dict[@"forwardLock"] = @NO;
436
ControlJoystick *button = [ControlJoystick buttonWithProperties:dict];
437
[self doAddButton:button atIndex:@([self.ctrlView.layoutDictionary[@"mJoystickDataList"] count])];
438
[button snapAndAlignX:self.selectedPoint.origin.x-25.0 Y:self.selectedPoint.origin.y-25.0];
439
[button update];
440
[button addGestureRecognizer:[[UITapGestureRecognizer alloc]
441
initWithTarget:self action:@selector(showControlPopover:)]];
442
[button addGestureRecognizer:[[UIPanGestureRecognizer alloc]
443
initWithTarget:self action:@selector(onTouch:)]];
444
}
445
446
- (void)actionMenuBtnCopy {
447
// copy
448
}
449
450
- (void)actionMenuBtnDelete {
451
self.resizeView.hidden = YES;
452
ControlButton *button = (ControlButton *)self.currentGesture.view;
453
[self doRemoveButton:button];
454
}
455
456
- (void)actionMenuBtnEdit {
457
CCMenuViewController *vc = [[CCMenuViewController alloc] init];
458
vc.modalPresentationStyle = UIModalPresentationOverFullScreen;
459
vc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
460
vc.preferredContentSize = self.view.frame.size;
461
if (![self.currentGesture isKindOfClass:[UILongPressGestureRecognizer class]]) {
462
vc.targetButton = (ControlButton *)self.currentGesture.view;
463
}
464
[self presentViewController:vc animated:YES completion:nil];
465
}
466
467
- (void)setButtonMenuVisibleForView:(UIView *)view {
468
self.resizeView.layer.maskedCorners = kCALayerMaxXMaxYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner;
469
self.resizeView.target = (ControlButton *)view;
470
UIMenuController *menuController = [UIMenuController sharedMenuController];
471
if (view) {
472
[menuController showMenuFromView:view rect:self.selectedPoint];
473
} else {
474
[menuController hideMenu];
475
}
476
477
if (view) {
478
CGPoint origin = [self.ctrlView convertPoint:view.frame.origin toView:self.view];
479
self.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);
480
}
481
}
482
483
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
484
return UIRectEdgeAll;
485
}
486
487
- (BOOL)prefersHomeIndicatorAutoHidden {
488
return getPrefBool(@"debug.debug_hide_home_indicator");
489
}
490
491
- (BOOL)prefersStatusBarHidden {
492
return YES;
493
}
494
495
- (void)onTouchAreaHandleView:(UIPanGestureRecognizer *)sender {
496
if (sender.state != UIGestureRecognizerStateChanged) return;
497
CGPoint translation = [sender translationInView:sender.view];
498
499
// Perform safe area resize
500
CGRect targetFrame = self.ctrlView.frame;
501
targetFrame.size.width += translation.x;
502
targetFrame.size.height += translation.y;
503
self.ctrlView.frame = targetFrame;
504
505
// Keep track of handle view location
506
targetFrame = self.resizeView.frame;
507
targetFrame.origin.x = CGRectGetMaxX(self.ctrlView.frame) - targetFrame.size.width;
508
targetFrame.origin.y = CGRectGetMaxY(self.ctrlView.frame) - targetFrame.size.height;
509
self.resizeView.frame = targetFrame;
510
511
[sender setTranslation:CGPointZero inView:sender.view];
512
}
513
514
- (void)onTouchButtonHandleView:(UIPanGestureRecognizer *)sender {
515
static CGRect origButtonRect;
516
517
CGPoint translation = [sender translationInView:sender.view];
518
CGFloat width, height;
519
520
switch (sender.state) {
521
case UIGestureRecognizerStateBegan: {
522
// Save old button frame
523
origButtonRect = self.resizeView.target.frame;
524
} break;
525
case UIGestureRecognizerStateChanged: {
526
// Perform button resize
527
width = MAX(10, [self.resizeView.target.properties[@"width"] floatValue] + translation.x);
528
height = MAX(10, [self.resizeView.target.properties[@"height"] floatValue] + translation.y);
529
self.resizeView.target.properties[@"width"] = @(width);
530
self.resizeView.target.properties[@"height"] = @(height);
531
[self.resizeView.target update];
532
[sender setTranslation:CGPointZero inView:sender.view];
533
534
// Keep track of handle view location
535
self.resizeView.frame = CGRectMake(CGRectGetMaxX(self.resizeView.target.frame), CGRectGetMaxY(self.resizeView.target.frame),
536
self.resizeView.frame.size.width, self.resizeView.frame.size.height);
537
} break;
538
case UIGestureRecognizerStateCancelled:
539
case UIGestureRecognizerStateEnded: {
540
[self doMoveOrResizeButton:self.resizeView.target from:origButtonRect to:self.resizeView.target.frame];
541
} break;
542
default: break;
543
}
544
}
545
546
- (void)onTouch:(UIPanGestureRecognizer *)sender {
547
static CGRect origButtonRect;
548
549
if ([sender.view isKindOfClass:ControlHandleView.class]) {
550
if (self.resizeView.target == nil) {
551
[self onTouchAreaHandleView:sender];
552
} else if ([self.resizeView.target isKindOfClass:ControlButton.class]) {
553
[self onTouchButtonHandleView:sender];
554
}
555
return;
556
}
557
558
CGPoint translation = [sender translationInView:sender.view];
559
560
ControlButton *button = (ControlButton *)sender.view;
561
if ([button isKindOfClass:ControlSubButton.class] &&
562
![((ControlSubButton *)button).parentDrawer.drawerData[@"orientation"] isEqualToString:@"FREE"]) return;
563
564
switch (sender.state) {
565
case UIGestureRecognizerStateBegan: {
566
origButtonRect = button.frame;
567
[self setButtonMenuVisibleForView:nil];
568
self.resizeView.hidden = NO;
569
self.resizeView.target = button;
570
} break;
571
case UIGestureRecognizerStateChanged: {
572
//button.center = CGPointMake(button.center.x + translation.x, button.center.y + translation.y);
573
[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)];
574
[sender setTranslation:CGPointZero inView:button];
575
self.resizeView.frame = CGRectMake(CGRectGetMaxX(button.frame), CGRectGetMaxY(button.frame), self.resizeView.frame.size.width, self.resizeView.frame.size.height);
576
} break;
577
case UIGestureRecognizerStateCancelled:
578
case UIGestureRecognizerStateEnded: {
579
[self doMoveOrResizeButton:button from:origButtonRect to:button.frame];
580
} break;
581
default: break;
582
}
583
}
584
585
#pragma mark - UIPopoverPresentationControllerDelegate
586
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection {
587
return UIModalPresentationNone;
588
}
589
590
@end
591
592
#define TAG_SLIDER_STROKEWIDTH 10
593
594
#define VISIBILITY_ALWAYS 0
595
#define VISIBILITY_IN_GAME 1
596
#define VISIBILITY_IN_MENU 2
597
598
#pragma mark - CCMenuViewController
599
600
CGFloat currentY;
601
602
@interface CCMenuViewController () <UIPickerViewDataSource, UIPickerViewDelegate> {
603
}
604
605
@property(nonatomic) NSMutableArray *keyCodeMap, *keyValueMap;
606
@property(nonatomic) NSArray *arrOrientation, *arrVisibility;
607
@property(nonatomic) NSMutableDictionary* oldProperties;
608
609
@property UITextField *activeField;
610
@property(nonatomic) UIScrollView* scrollView;
611
@property(nonatomic) UITextField *editName, *editSizeWidth, *editSizeHeight;
612
@property(nonatomic) UITextView* editMapping;
613
@property(nonatomic) UIPickerView* pickerMapping;
614
@property(nonatomic) UISegmentedControl *ctrlOrientation, *ctrlVisibility;
615
@property(nonatomic) UISwitch *switchFwdLock, *switchToggleable, *switchMousePass, *switchSwipeable;
616
@property(nonatomic) UIColorWell *colorWellBackground, *colorWellStroke;
617
@property(nonatomic) DBNumberedSlider *sliderStrokeWidth, *sliderCornerRadius, *sliderOpacity;
618
619
@end
620
621
@implementation CCMenuViewController
622
623
- (UILabel*)addLabel:(NSString *)name {
624
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0, currentY, 0.0, 0.0)];
625
label.text = name;
626
label.numberOfLines = 0;
627
[label sizeToFit];
628
[self.scrollView addSubview:label];
629
return label;
630
}
631
632
- (void)viewDidLoad {
633
[super viewDidLoad];
634
635
self.keyCodeMap = [[NSMutableArray alloc] init];
636
self.keyValueMap = [[NSMutableArray alloc] init];
637
initKeycodeTable(self.keyCodeMap, self.keyValueMap);
638
639
self.oldProperties = self.targetButton.properties.mutableCopy;
640
currentY = 6.0;
641
642
CGFloat shortest = MIN(self.view.frame.size.width, self.view.frame.size.height);
643
CGFloat tempW = MIN(self.view.frame.size.width * 0.75, shortest);
644
CGFloat tempH = MIN(self.view.frame.size.height * 0.6, shortest);
645
646
UIBlurEffectStyle blurStyle = UIBlurEffectStyleSystemMaterial;
647
UIVisualEffectView *blurView;
648
blurView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:blurStyle]];
649
blurView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
650
blurView.frame = CGRectMake(
651
(self.view.frame.size.width - MAX(tempW, tempH))/2,
652
(self.view.frame.size.height - MIN(tempW, tempH))/2,
653
MAX(tempW, tempH), MIN(tempW, tempH));
654
blurView.layer.cornerRadius = 10.0;
655
blurView.clipsToBounds = YES;
656
[self.view addSubview:blurView];
657
658
UIBarButtonItem *btnFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
659
660
UIToolbar *popoverToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, blurView.frame.size.width, 44.0)];
661
UIPanGestureRecognizer *dragVCGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragViewController:)];
662
dragVCGesture.minimumNumberOfTouches = 1;
663
dragVCGesture.maximumNumberOfTouches = 1;
664
[popoverToolbar addGestureRecognizer:dragVCGesture];
665
666
UIBarButtonItem *popoverCancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(actionEditCancel)];
667
UIBarButtonItem *popoverDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionEditFinish)];
668
popoverToolbar.items = @[popoverCancelButton, btnFlexibleSpace, popoverDoneButton];
669
[blurView.contentView addSubview:popoverToolbar];
670
671
self.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)];
672
self.scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
673
[blurView.contentView addSubview:self.scrollView];
674
675
UIToolbar *editPickToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, blurView.frame.size.width, 44.0)];
676
677
UIBarButtonItem *editDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeTextField)];
678
editPickToolbar.items = @[btnFlexibleSpace, editDoneButton];
679
680
CGFloat width = blurView.frame.size.width - 10.0;
681
CGFloat height = blurView.frame.size.height - 10.0;
682
683
684
// Property: Name
685
if (![self.targetButton isKindOfClass:ControlJoystick.class]) {
686
UILabel *labelName = [self addLabel:localize(@"custom_controls.button_edit.name", nil)];
687
self.editName = [[UITextField alloc] initWithFrame:CGRectMake(labelName.frame.size.width + 5.0, currentY, width - labelName.frame.size.width - 5.0, labelName.frame.size.height)];
688
[self.editName addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];
689
[self.editName addTarget:self.editName action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
690
self.editName.placeholder = localize(@"custom_controls.button_edit.name", nil);
691
self.editName.returnKeyType = UIReturnKeyDone;
692
self.editName.text = self.targetButton.properties[@"name"];
693
[self.scrollView addSubview:self.editName];
694
currentY += labelName.frame.size.height + 15.0;
695
}
696
697
if (![self.targetButton isKindOfClass:ControlSubButton.class] ||
698
[((ControlSubButton *)self.targetButton).parentDrawer.drawerData[@"orientation"] isEqualToString:@"FREE"]) {
699
// Property: Size
700
UILabel *labelSize = [self addLabel:localize(@"custom_controls.button_edit.size", nil)];
701
// width / 2.0 + (labelSize.frame.size.width + 4.0) / 2.0
702
CGFloat editSizeWidthValue = (width - labelSize.frame.size.width) / 2 - labelSize.frame.size.height / 2;
703
UILabel *labelSizeX = [[UILabel alloc] initWithFrame:CGRectMake(labelSize.frame.size.width + editSizeWidthValue, labelSize.frame.origin.y, labelSize.frame.size.height, labelSize.frame.size.height)];
704
labelSizeX.text = @"x";
705
[self.scrollView addSubview:labelSizeX];
706
self.editSizeWidth = [[UITextField alloc] initWithFrame:CGRectMake(labelSize.frame.size.width, labelSize.frame.origin.y, editSizeWidthValue, labelSize.frame.size.height)];
707
[self.editSizeWidth addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];
708
[self.editSizeWidth addTarget:self.editSizeWidth action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
709
self.editSizeWidth.keyboardType = UIKeyboardTypeDecimalPad;
710
self.editSizeWidth.placeholder = @"width";
711
self.editSizeWidth.returnKeyType = UIReturnKeyDone;
712
self.editSizeWidth.text = [self.targetButton.properties[@"width"] stringValue];
713
self.editSizeWidth.textAlignment = NSTextAlignmentCenter;
714
[self.scrollView addSubview:self.editSizeWidth];
715
self.editSizeHeight = [[UITextField alloc] initWithFrame:CGRectMake(labelSizeX.frame.origin.x + labelSizeX.frame.size.width, labelSize.frame.origin.y, editSizeWidthValue, labelSize.frame.size.height)];
716
[self.editSizeHeight addTarget:self action:@selector(textFieldEditingChanged) forControlEvents:UIControlEventEditingChanged];
717
[self.editSizeHeight addTarget:self.editSizeHeight action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
718
self.editSizeHeight.keyboardType = UIKeyboardTypeDecimalPad;
719
self.editSizeHeight.placeholder = @"height";
720
self.editSizeHeight.returnKeyType = UIReturnKeyDone;
721
self.editSizeHeight.text = [self.targetButton.properties[@"height"] stringValue];
722
self.editSizeHeight.textAlignment = NSTextAlignmentCenter;
723
[self.scrollView addSubview:self.editSizeHeight];
724
currentY += labelSize.frame.size.height + 15.0;
725
}
726
727
728
if ([self.targetButton isKindOfClass:ControlDrawer.class]) {
729
// Property: Orientation
730
self.arrOrientation = @[@"DOWN", @"LEFT", @"UP", @"RIGHT", @"FREE"];
731
UILabel *labelOrientation = [self addLabel:localize(@"custom_controls.button_edit.orientation", nil)];
732
self.ctrlOrientation = [[UISegmentedControl alloc] initWithItems:self.arrOrientation];
733
[self.ctrlOrientation addTarget:self action:@selector(orientationValueChanged:) forControlEvents:UIControlEventValueChanged];
734
self.ctrlOrientation.frame = CGRectMake(labelOrientation.frame.size.width + 5.0, currentY - 5.0, width - labelOrientation.frame.size.width - 5.0, 30.0);
735
self.ctrlOrientation.selectedSegmentIndex = [self.arrOrientation indexOfObject:
736
((ControlDrawer *)self.targetButton).drawerData[@"orientation"]];
737
[self.scrollView addSubview:self.ctrlOrientation];
738
currentY += labelOrientation.frame.size.height + 15.0;
739
} else if ([self.targetButton isKindOfClass:ControlJoystick.class]) {
740
// Property: Forward lock
741
UILabel *labelFwdLock = [self addLabel:localize(@"custom_controls.button_edit.forward_lock", nil)];
742
self.switchFwdLock = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];
743
[self.switchFwdLock setOn:[self.targetButton.properties[@"forwardLock"] boolValue] animated:NO];
744
[self.scrollView addSubview:self.switchFwdLock];
745
currentY += labelFwdLock.frame.size.height + 15.0;
746
} else {
747
// Property: Mapping
748
UILabel *labelMapping = [self addLabel:localize(@"custom_controls.button_edit.mapping", nil)];
749
750
self.editMapping = [[UITextView alloc] initWithFrame:CGRectMake(0,0,1,1)];
751
self.editMapping.text = @"\n\n\n";
752
[self.editMapping sizeToFit];
753
self.editMapping.scrollEnabled = NO;
754
self.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);
755
756
self.pickerMapping = [[UIPickerView alloc] init];
757
self.pickerMapping.delegate = self;
758
self.pickerMapping.dataSource = self;
759
[self.pickerMapping reloadAllComponents];
760
for (int i = 0; i < 4; i++) {
761
[self.pickerMapping selectRow:[self.keyValueMap indexOfObject:self.targetButton.properties[@"keycodes"][i]] inComponent:i animated:NO];
762
}
763
[self pickerView:self.pickerMapping didSelectRow:0 inComponent:0];
764
765
self.editMapping.inputAccessoryView = editPickToolbar;
766
self.editMapping.inputView = self.pickerMapping;
767
[self.scrollView addSubview:self.editMapping];
768
currentY += self.editMapping.frame.size.height + 15.0;
769
}
770
771
772
if (![self.targetButton isKindOfClass:ControlJoystick.class]) {
773
// Property: Toggleable
774
UILabel *labelToggleable = [self addLabel:localize(@"custom_controls.button_edit.toggleable", nil)];
775
self.switchToggleable = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];
776
[self.switchToggleable setOn:[self.targetButton.properties[@"isToggle"] boolValue] animated:NO];
777
[self.scrollView addSubview:self.switchToggleable];
778
currentY += labelToggleable.frame.size.height + 15.0;
779
780
781
// Property: Mouse pass
782
UILabel *labelMousePass = [self addLabel:localize(@"custom_controls.button_edit.mouse_pass", nil)];
783
self.switchMousePass = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];
784
[self.switchMousePass setOn:[self.targetButton.properties[@"passThruEnabled"] boolValue]];
785
[self.scrollView addSubview:self.switchMousePass];
786
currentY += labelMousePass.frame.size.height + 15.0;
787
788
789
// Property: Swipeable
790
UILabel *labelSwipeable = [self addLabel:localize(@"custom_controls.button_edit.swipeable", nil)];
791
self.switchSwipeable = [[UISwitch alloc] initWithFrame:CGRectMake(width - 62.0, currentY - 5.0, 50.0, 30)];
792
[self.switchSwipeable setOn:[self.targetButton.properties[@"isSwipeable"] boolValue]];
793
[self.scrollView addSubview:self.switchSwipeable];
794
currentY += labelSwipeable.frame.size.height + 15.0;
795
}
796
797
798
// Property: Background color
799
UILabel *labelBGColor = [self addLabel:localize(@"custom_controls.button_edit.bg_color", nil)];
800
self.colorWellBackground = [[UIColorWell alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];
801
[self.colorWellBackground addTarget:self action:@selector(colorWellChanged) forControlEvents:UIControlEventValueChanged];
802
self.colorWellBackground.selectedColor = convertARGB2UIColor([self.targetButton.properties[@"bgColor"] intValue]);
803
[self.scrollView addSubview:self.colorWellBackground];
804
currentY += labelBGColor.frame.size.height + 15.0;
805
806
// Property: Stroke width
807
UILabel *labelStrokeWidth = [self addLabel:localize(@"custom_controls.button_edit.stroke_width", nil)];
808
self.sliderStrokeWidth = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelStrokeWidth.frame.size.width + 5.0, currentY - 5.0, width - labelStrokeWidth.frame.size.width - 5.0, 30.0)];
809
self.sliderStrokeWidth.continuous = YES;
810
self.sliderStrokeWidth.maximumValue = MAX([self.targetButton.properties[@"width"] intValue], [self.targetButton.properties[@"height"] intValue]) / 2;
811
self.sliderStrokeWidth.tag = TAG_SLIDER_STROKEWIDTH;
812
self.sliderStrokeWidth.value = [self.targetButton.properties[@"strokeWidth"] intValue];
813
[self.sliderStrokeWidth addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
814
[self.scrollView addSubview:self.sliderStrokeWidth];
815
currentY += labelStrokeWidth.frame.size.height + 15.0;
816
817
818
// Property: Stroke color
819
UILabel *labelStrokeColor = [self addLabel:localize(@"custom_controls.button_edit.stroke_color", nil)];
820
self.colorWellStroke = [[UIColorWell alloc] initWithFrame:CGRectMake(width - 42.0, currentY - 5.0, 30.0, 30.0)];
821
[self.colorWellStroke addTarget:self action:@selector(colorWellChanged) forControlEvents:UIControlEventValueChanged];
822
self.colorWellStroke.selectedColor = convertARGB2UIColor([self.targetButton.properties[@"strokeColor"] intValue]);
823
[self.scrollView addSubview:self.colorWellStroke];
824
currentY += labelStrokeColor.frame.size.height + 15.0;
825
826
827
// Property: Corner radius
828
if (![self.targetButton isKindOfClass:ControlJoystick.class]) {
829
UILabel *labelCornerRadius = [self addLabel:localize(@"custom_controls.button_edit.corner_radius", nil)];
830
self.sliderCornerRadius = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelCornerRadius.frame.size.width + 5.0, currentY - 5.0, width - labelCornerRadius.frame.size.width - 5.0, 30.0)];
831
self.sliderCornerRadius.continuous = YES;
832
self.sliderCornerRadius.maximumValue = 100;
833
self.sliderCornerRadius.value = [self.targetButton.properties[@"cornerRadius"] intValue];
834
[self.sliderCornerRadius addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
835
[self.scrollView addSubview:self.sliderCornerRadius];
836
currentY += labelCornerRadius.frame.size.height + 15.0;
837
}
838
839
840
// Property: Button Opacity
841
UILabel *labelOpacity = [self addLabel:localize(@"custom_controls.button_edit.opacity", nil)];
842
self.sliderOpacity = [[DBNumberedSlider alloc] initWithFrame:CGRectMake(labelOpacity.frame.size.width + 5.0, currentY - 5.0, width - labelOpacity.frame.size.width - 5.0, 30.0)];
843
self.sliderOpacity.continuous = YES;
844
self.sliderOpacity.minimumValue = 1;
845
self.sliderOpacity.maximumValue = 100;
846
self.sliderOpacity.value = [self.targetButton.properties[@"opacity"] floatValue] * 100.0;
847
[self.sliderOpacity addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
848
[self.scrollView addSubview:self.sliderOpacity];
849
currentY += labelOpacity.frame.size.height + 15.0;
850
851
852
// Property: Visibility
853
self.arrVisibility = @[localize(@"Always", nil), localize(@"In game", nil), localize(@"In menu", nil)];
854
UILabel *labelVisibility = [self addLabel:localize(@"custom_controls.button_edit.visibility", nil)];
855
self.ctrlVisibility = [[UISegmentedControl alloc] initWithItems:self.arrVisibility];
856
[self.ctrlVisibility addTarget:self action:@selector(visibilityValueChanged:) forControlEvents:UIControlEventValueChanged];
857
self.ctrlVisibility.frame = CGRectMake(labelVisibility.frame.size.width + 5.0, currentY - 5.0, width - labelVisibility.frame.size.width - 5.0, 30.0);
858
BOOL displayInGame = [self.targetButton.properties[@"displayInGame"] boolValue];
859
BOOL displayInMenu = [self.targetButton.properties[@"displayInMenu"] boolValue];
860
if (displayInGame && displayInMenu) {
861
self.ctrlVisibility.selectedSegmentIndex = VISIBILITY_ALWAYS;
862
} else if (displayInGame) {
863
self.ctrlVisibility.selectedSegmentIndex = VISIBILITY_IN_GAME;
864
} else if (displayInMenu) {
865
self.ctrlVisibility.selectedSegmentIndex = VISIBILITY_IN_MENU;
866
} // else the segment is not chosen
867
[self.scrollView addSubview:self.ctrlVisibility];
868
currentY += labelVisibility.frame.size.height + 15.0;
869
870
self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, currentY);
871
}
872
873
#pragma mark - Gesture callback
874
- (void)dragViewController:(UIPanGestureRecognizer *)sender {
875
static CGPoint lastPoint;
876
CGPoint point = [sender translationInView:self.view];
877
if (sender.state != UIGestureRecognizerStateBegan) {
878
CGRect rect = self.view.subviews[0].frame;
879
rect.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);
880
rect.origin.y = clamp(rect.origin.y - lastPoint.y + point.y, 0, self.view.frame.size.height - sender.view.frame.size.height);
881
self.view.subviews[0].frame = rect;
882
}
883
lastPoint = point;
884
}
885
886
#pragma mark - Color picker functions
887
888
- (void)colorWellChanged {
889
self.targetButton.properties[@"bgColor"] = @(convertUIColor2ARGB(self.colorWellBackground.selectedColor));
890
self.targetButton.properties[@"strokeColor"] = @(convertUIColor2ARGB(self.colorWellStroke.selectedColor));
891
[self.targetButton update];
892
}
893
894
- (void)textFieldEditingChanged {
895
self.targetButton.properties[@"name"] = self.editName.text;
896
self.targetButton.properties[@"width"] = @([self.editSizeWidth.text floatValue]);
897
self.targetButton.properties[@"height"] = @([self.editSizeHeight.text floatValue]);
898
[self.targetButton update];
899
}
900
901
#pragma mark - Control editor
902
- (void)actionEditCancel {
903
self.targetButton.properties = self.oldProperties;
904
[self.targetButton update];
905
[self dismissViewControllerAnimated:YES completion:nil];
906
}
907
908
- (void)actionEditFinish {
909
if (self.switchFwdLock) {
910
self.targetButton.properties[@"forwardLock"] = @(self.switchFwdLock.isOn);
911
}
912
self.targetButton.properties[@"isToggle"] = @(self.switchToggleable.isOn);
913
self.targetButton.properties[@"passThruEnabled"] = @(self.switchMousePass.isOn);
914
self.targetButton.properties[@"isSwipeable"] = @(self.switchSwipeable.isOn);
915
916
NSMutableDictionary *newProperties = self.targetButton.properties.mutableCopy;
917
918
for (NSString *key in self.oldProperties) {
919
if ([self.oldProperties[key] isEqual:newProperties[key]]) {
920
[newProperties removeObjectForKey:key];
921
}
922
}
923
924
[(CustomControlsViewController *)self.presentingViewController
925
doUpdateButton:self.targetButton from:self.oldProperties to:newProperties];
926
self.oldProperties = nil;
927
[self dismissViewControllerAnimated:YES completion:nil];
928
}
929
930
- (void)orientationValueChanged:(UISegmentedControl *)sender {
931
((ControlDrawer *)self.targetButton).drawerData[@"orientation"] =
932
self.arrOrientation[sender.selectedSegmentIndex];
933
[(ControlDrawer *)self.targetButton syncButtons];
934
}
935
936
- (void)sliderValueChanged:(DBNumberedSlider *)sender {
937
if (sender.tag == TAG_SLIDER_STROKEWIDTH) {
938
self.colorWellStroke.enabled = sender.value != 0;
939
self.targetButton.properties[@"strokeWidth"] = @((NSInteger) self.sliderStrokeWidth.value);
940
} else {
941
[sender setValue:(NSInteger)sender.value animated:NO];
942
self.targetButton.properties[@"cornerRadius"] = @((NSInteger) self.sliderCornerRadius.value);
943
self.targetButton.properties[@"opacity"] = @(self.sliderOpacity.value / 100.0);
944
}
945
[self.targetButton update];
946
}
947
948
- (void)visibilityValueChanged:(UISegmentedControl *)sender {
949
self.targetButton.properties[@"displayInGame"] = [NSNumber numberWithBool:sender.selectedSegmentIndex != VISIBILITY_IN_MENU];
950
self.targetButton.properties[@"displayInMenu"] = [NSNumber numberWithBool:sender.selectedSegmentIndex != VISIBILITY_IN_GAME];
951
}
952
953
#pragma mark - UIPickerView stuff
954
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
955
{
956
UILabel *label = (UILabel *)view;
957
if (label == nil) {
958
label = [UILabel new];
959
label.adjustsFontSizeToFitWidth = YES;
960
label.minimumScaleFactor = 0.5;
961
label.textAlignment = NSTextAlignmentCenter;
962
}
963
label.text = [self pickerView:pickerView titleForRow:row forComponent:component];
964
965
return label;
966
}
967
968
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
969
self.editMapping.text = [NSString stringWithFormat:@"1: %@\n2: %@\n3: %@\n4: %@",
970
self.keyCodeMap[[pickerView selectedRowInComponent:0]],
971
self.keyCodeMap[[pickerView selectedRowInComponent:1]],
972
self.keyCodeMap[[pickerView selectedRowInComponent:2]],
973
self.keyCodeMap[[pickerView selectedRowInComponent:3]]
974
];
975
976
for (int i = 0; i < 4; i++) {
977
self.targetButton.properties[@"keycodes"][i] = self.keyValueMap[[self.pickerMapping selectedRowInComponent:i]];
978
}
979
}
980
981
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
982
return 4;
983
}
984
985
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
986
return self.keyCodeMap.count;
987
}
988
989
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
990
return self.keyCodeMap[row];
991
}
992
993
- (void)closeTextField {
994
[self.editMapping endEditing:YES];
995
}
996
997
@end
998
999