diff --git a/macos/mkxp-z.xcodeproj/project.pbxproj b/macos/mkxp-z.xcodeproj/project.pbxproj index 7ab8da9a..cb794e42 100644 --- a/macos/mkxp-z.xcodeproj/project.pbxproj +++ b/macos/mkxp-z.xcodeproj/project.pbxproj @@ -60,7 +60,6 @@ 3B10EDB82568E95E00372D13 /* soundemitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED652568E95D00372D13 /* soundemitter.cpp */; }; 3B10EDB92568E95E00372D13 /* audiostream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED662568E95D00372D13 /* audiostream.cpp */; }; 3B10EDBA2568E95E00372D13 /* vorbissource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED6A2568E95D00372D13 /* vorbissource.cpp */; }; - 3B10EDBB2568E95E00372D13 /* settingsmenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED6E2568E95D00372D13 /* settingsmenu.cpp */; }; 3B10EDBC2568E95E00372D13 /* windowvx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED722568E95D00372D13 /* windowvx.cpp */; }; 3B10EDBD2568E95E00372D13 /* bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED732568E95D00372D13 /* bitmap.cpp */; }; 3B10EDBE2568E95E00372D13 /* window.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED742568E95D00372D13 /* window.cpp */; }; @@ -155,7 +154,6 @@ 3B1C239B25A19C600075EF5D /* keybindings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED472568E95D00372D13 /* keybindings.cpp */; }; 3B1C239C25A19C600075EF5D /* filesystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED542568E95D00372D13 /* filesystem.cpp */; }; 3B1C239D25A19C600075EF5D /* binding-mri.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10EDF02568E96A00372D13 /* binding-mri.cpp */; }; - 3B1C239E25A19C600075EF5D /* settingsmenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED6E2568E95D00372D13 /* settingsmenu.cpp */; }; 3B1C239F25A19C600075EF5D /* eventthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED352568E95D00372D13 /* eventthread.cpp */; }; 3B1C23A025A19C600075EF5D /* viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED9E2568E95E00372D13 /* viewport.cpp */; }; 3B1C23A125A19C600075EF5D /* gl-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED832568E95E00372D13 /* gl-debug.cpp */; }; @@ -240,6 +238,10 @@ 3B3F7D2C25B1A73A00EA5F1C /* SettingsMenuController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3B3F7D2925B1A73A00EA5F1C /* SettingsMenuController.mm */; }; 3B3F7D2D25B1A73A00EA5F1C /* SettingsMenuController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3B3F7D2925B1A73A00EA5F1C /* SettingsMenuController.mm */; }; 3B426F77256BA847009EA00F /* libsigc-2.0.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B426F76256BA847009EA00F /* libsigc-2.0.a */; }; + 3B480E9D25DCD166001686B4 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B480E9C25DCD166001686B4 /* GameController.framework */; }; + 3B480E9F25DCD174001686B4 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B480E9E25DCD16D001686B4 /* GameController.framework */; }; + 3B480EA025DCD175001686B4 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B480E9E25DCD16D001686B4 /* GameController.framework */; }; + 3B480EA125DCD176001686B4 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B480E9E25DCD16D001686B4 /* GameController.framework */; }; 3B522DA9259BAA42003301C4 /* libfluidsynth.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B522DA1259BAA13003301C4 /* libfluidsynth.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 3B522DAA259BAA4A003301C4 /* libfluidsynth.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B522DA1259BAA13003301C4 /* libfluidsynth.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 3B522DAB259BAA4C003301C4 /* libfluidsynth.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B522DA1259BAA13003301C4 /* libfluidsynth.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; @@ -318,7 +320,6 @@ 3BC65CF32584EDC60063AFF1 /* keybindings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED472568E95D00372D13 /* keybindings.cpp */; }; 3BC65CF42584EDC60063AFF1 /* filesystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED542568E95D00372D13 /* filesystem.cpp */; }; 3BC65CF52584EDC60063AFF1 /* binding-mri.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10EDF02568E96A00372D13 /* binding-mri.cpp */; }; - 3BC65CF62584EDC60063AFF1 /* settingsmenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED6E2568E95D00372D13 /* settingsmenu.cpp */; }; 3BC65CF72584EDC60063AFF1 /* eventthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED352568E95D00372D13 /* eventthread.cpp */; }; 3BC65CF82584EDC60063AFF1 /* viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED9E2568E95E00372D13 /* viewport.cpp */; }; 3BC65CF92584EDC60063AFF1 /* gl-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED832568E95E00372D13 /* gl-debug.cpp */; }; @@ -413,7 +414,6 @@ 3BC65DB42584F3AD0063AFF1 /* keybindings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED472568E95D00372D13 /* keybindings.cpp */; }; 3BC65DB52584F3AD0063AFF1 /* filesystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED542568E95D00372D13 /* filesystem.cpp */; }; 3BC65DB62584F3AD0063AFF1 /* binding-mri.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10EDF02568E96A00372D13 /* binding-mri.cpp */; }; - 3BC65DB72584F3AD0063AFF1 /* settingsmenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED6E2568E95D00372D13 /* settingsmenu.cpp */; }; 3BC65DB82584F3AD0063AFF1 /* eventthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED352568E95D00372D13 /* eventthread.cpp */; }; 3BC65DB92584F3AD0063AFF1 /* viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED9E2568E95E00372D13 /* viewport.cpp */; }; 3BC65DBA2584F3AD0063AFF1 /* gl-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B10ED832568E95E00372D13 /* gl-debug.cpp */; }; @@ -953,6 +953,9 @@ 3B426F6F256B8AC0009EA00F /* fs_impl.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = fs_impl.hpp; sourceTree = ""; }; 3B426F70256B8AC0009EA00F /* fs_std_fwd.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = fs_std_fwd.hpp; sourceTree = ""; }; 3B426F76256BA847009EA00F /* libsigc-2.0.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libsigc-2.0.a"; path = "Dependencies/build-macosx-x86_64/lib/libsigc-2.0.a"; sourceTree = ""; }; + 3B480E9325DCBDD6001686B4 /* sdl_codes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sdl_codes.h; path = views/sdl_codes.h; sourceTree = ""; }; + 3B480E9C25DCD166001686B4 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; + 3B480E9E25DCD16D001686B4 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; 3B522DA1259BAA13003301C4 /* libfluidsynth.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfluidsynth.dylib; path = Dependencies/Frameworks/libfluidsynth.dylib; sourceTree = ""; }; 3B522DB2259BC037003301C4 /* net.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = net.h; sourceTree = ""; }; 3B522DBD259BD046003301C4 /* httplib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = httplib.h; sourceTree = ""; }; @@ -1089,6 +1092,7 @@ 3B1C23D825A19C600075EF5D /* CoreVideo.framework in Frameworks */, 3B1C23D925A19C600075EF5D /* CoreGraphics.framework in Frameworks */, 3B1C23DA25A19C600075EF5D /* libbz2.tbd in Frameworks */, + 3B480EA125DCD176001686B4 /* GameController.framework in Frameworks */, 3B1C23DB25A19C600075EF5D /* libruby.3.0.dylib in Frameworks */, 3B1C23DC25A19C600075EF5D /* CoreAudio.framework in Frameworks */, 3B1C23DD25A19C600075EF5D /* AudioToolbox.framework in Frameworks */, @@ -1140,6 +1144,7 @@ 3B5E1F1125A881FB0086FFDC /* libGLESv2.dylib in Frameworks */, 3BC65D342584EDC60063AFF1 /* Foundation.framework in Frameworks */, 3B1C230725A142620075EF5D /* libruby.3.0.dylib in Frameworks */, + 3B480EA025DCD175001686B4 /* GameController.framework in Frameworks */, 3BC65D612584EED10063AFF1 /* libogg.a in Frameworks */, 3BC65D352584EDC60063AFF1 /* CoreFoundation.framework in Frameworks */, 3BC65D362584EDC60063AFF1 /* libz.tbd in Frameworks */, @@ -1182,6 +1187,7 @@ 3B5E1F0F25A881FB0086FFDC /* libGLESv2.dylib in Frameworks */, 3BC65E212584F4290063AFF1 /* libopenal.a in Frameworks */, 3B1C230E25A144BF0075EF5D /* libruby.3.0.dylib in Frameworks */, + 3B480E9D25DCD166001686B4 /* GameController.framework in Frameworks */, 3BC65DFF2584F3AD0063AFF1 /* Foundation.framework in Frameworks */, 3BC65E242584F4290063AFF1 /* libvorbisfile.a in Frameworks */, 3BC65E012584F3AD0063AFF1 /* CoreFoundation.framework in Frameworks */, @@ -1223,6 +1229,7 @@ 3B10EC612568D40C00372D13 /* CoreVideo.framework in Frameworks */, 3B10EC5C2568D40500372D13 /* CoreGraphics.framework in Frameworks */, 3BE081592568D3A60006849F /* libbz2.tbd in Frameworks */, + 3B480E9F25DCD174001686B4 /* GameController.framework in Frameworks */, 3B1C230B25A144A10075EF5D /* libruby.3.0.dylib in Frameworks */, 3B10EC632568D40C00372D13 /* CoreAudio.framework in Frameworks */, 3BA08E9B256638C900449CFF /* AudioToolbox.framework in Frameworks */, @@ -1571,6 +1578,7 @@ 3B3F7D1725B19DEC00EA5F1C /* settingsmenu.xib */, 3B3F7D2925B1A73A00EA5F1C /* SettingsMenuController.mm */, 3B3F7D3025B1A79F00EA5F1C /* SettingsMenuController.h */, + 3B480E9325DCBDD6001686B4 /* sdl_codes.h */, ); name = MacOS; sourceTree = ""; @@ -1686,6 +1694,7 @@ 3BD2B46425651BEB003DAD8A /* System */ = { isa = PBXGroup; children = ( + 3B480E9E25DCD16D001686B4 /* GameController.framework */, 3BD2B47A256534BA003DAD8A /* IOKit.framework */, 3BE081552568D3A60006849F /* Carbon.framework */, 3BE081582568D3A60006849F /* AppKit.framework */, @@ -1746,6 +1755,7 @@ 3BDB23E5256455A400C4A63D /* Frameworks */ = { isa = PBXGroup; children = ( + 3B480E9C25DCD166001686B4 /* GameController.framework */, 3B1C241F25A1A84D0075EF5D /* Steam */, 3BC65D792584F3030063AFF1 /* Universal */, 3BC65D492584EE690063AFF1 /* ARM64 */, @@ -2058,7 +2068,6 @@ 3B1C239B25A19C600075EF5D /* keybindings.cpp in Sources */, 3B1C239C25A19C600075EF5D /* filesystem.cpp in Sources */, 3B1C239D25A19C600075EF5D /* binding-mri.cpp in Sources */, - 3B1C239E25A19C600075EF5D /* settingsmenu.cpp in Sources */, 3B1C239F25A19C600075EF5D /* eventthread.cpp in Sources */, 3B1C23A025A19C600075EF5D /* viewport.cpp in Sources */, 3B1C23A125A19C600075EF5D /* gl-debug.cpp in Sources */, @@ -2143,7 +2152,6 @@ 3BC65CF32584EDC60063AFF1 /* keybindings.cpp in Sources */, 3BC65CF42584EDC60063AFF1 /* filesystem.cpp in Sources */, 3BC65CF52584EDC60063AFF1 /* binding-mri.cpp in Sources */, - 3BC65CF62584EDC60063AFF1 /* settingsmenu.cpp in Sources */, 3BC65CF72584EDC60063AFF1 /* eventthread.cpp in Sources */, 3BC65CF82584EDC60063AFF1 /* viewport.cpp in Sources */, 3BC65CF92584EDC60063AFF1 /* gl-debug.cpp in Sources */, @@ -2220,7 +2228,6 @@ 3BC65DB42584F3AD0063AFF1 /* keybindings.cpp in Sources */, 3BC65DB52584F3AD0063AFF1 /* filesystem.cpp in Sources */, 3BC65DB62584F3AD0063AFF1 /* binding-mri.cpp in Sources */, - 3BC65DB72584F3AD0063AFF1 /* settingsmenu.cpp in Sources */, 3BC65DB82584F3AD0063AFF1 /* eventthread.cpp in Sources */, 3BC65DB92584F3AD0063AFF1 /* viewport.cpp in Sources */, 3BC65DBA2584F3AD0063AFF1 /* gl-debug.cpp in Sources */, @@ -2297,7 +2304,6 @@ 3B10EDA92568E95E00372D13 /* keybindings.cpp in Sources */, 3B10EDAD2568E95E00372D13 /* filesystem.cpp in Sources */, 3B10EE092568E96A00372D13 /* binding-mri.cpp in Sources */, - 3B10EDBB2568E95E00372D13 /* settingsmenu.cpp in Sources */, 3B10EDA62568E95E00372D13 /* eventthread.cpp in Sources */, 3B10EDD02568E95E00372D13 /* viewport.cpp in Sources */, 3B10EDC52568E95E00372D13 /* gl-debug.cpp in Sources */, diff --git a/macos/views/SettingsMenuController.h b/macos/views/SettingsMenuController.h index 28977827..b2004355 100644 --- a/macos/views/SettingsMenuController.h +++ b/macos/views/SettingsMenuController.h @@ -19,6 +19,8 @@ +(SettingsMenu*)openWindow; +-(SettingsMenu*)setWindow:(NSWindow*)window; +-(SettingsMenu*)raise; @end #endif /* SettingsMenuController_h */ diff --git a/macos/views/SettingsMenuController.mm b/macos/views/SettingsMenuController.mm index fb4cbcea..136bc385 100644 --- a/macos/views/SettingsMenuController.mm +++ b/macos/views/SettingsMenuController.mm @@ -5,10 +5,21 @@ // Created by ゾロアーク on 1/15/21. // +// This is a pretty rudimentary keybinding menu, and it replaces the normal one +// for macOS. The normal one basically just doesn't seem to work with ANGLE, +// so I cooked this one up in a hurry despite knowing next to zero about Xcode's +// interface builder in general. + +// Yes, it is still a mess, but it is working. + +#import + #import #import #import +#import "sdl_codes.h" + #import "SettingsMenuController.h" #import "input/input.h" @@ -31,6 +42,7 @@ typedef NSMutableArray BindingIndexArray; @implementation SettingsMenu { __weak IBOutlet NSWindow *_window; __weak IBOutlet NSTableView *_table; + __weak IBOutlet NSBox *bindingBox; // Binding buttons __weak IBOutlet NSButton *bindingButton1; @@ -43,23 +55,53 @@ typedef NSMutableArray BindingIndexArray; BDescVec *binds; int currentButtonCode; - // NSNumber (ButtonCode) -> NSArray (of BindingDesc pointers) + // Whether currently waiting for some kind of input + bool isListening; + + // For the current binding selection when the table is + // reloaded from deleting/adding keybinds + bool keepCurrentButtonSelection; + NSMutableDictionary *nsbinds; NSMutableDictionary *bindingNames; } +(SettingsMenu*)openWindow { SettingsMenu *s = [[SettingsMenu alloc] initWithNibName:@"settingsmenu" bundle:NSBundle.mainBundle]; - [NSApplication.sharedApplication.mainWindow beginSheet:s.view.window completionHandler:^(NSModalResponse _){}]; + // Show the window as a sheet, window events will be sucked up by SDL though + //[NSApplication.sharedApplication.mainWindow beginSheet:s.view.window completionHandler:^(NSModalResponse _){}]; + + // Show the view in a new window instead, so key and controller events + // can be captured without SDL's interference + NSWindow *win = [NSWindow windowWithContentViewController:s]; + win.styleMask &= ~NSWindowStyleMaskResizable; + win.styleMask &= ~NSWindowStyleMaskFullScreen; + win.styleMask &= NSWindowStyleMaskTitled; + win.title = @"Keybindings"; + [s setWindow:win]; + [win orderFront:self]; + + return s; +} + +-(void)raise { + if (_window) + [_window orderFront:self]; } -(void)closeWindow { + [self setNotListening:true]; [_window close]; } +-(SettingsMenu*)setWindow:(NSWindow*)window { + _window = window; +} + - (IBAction)acceptButton:(NSButton *)sender { shState->rtData().bindingUpdateMsg.post(*binds); storeBindings(*binds, shState->config()); + [self closeWindow]; } - (IBAction)cancelButton:(NSButton *)sender { [self closeWindow]; @@ -69,22 +111,107 @@ typedef NSMutableArray BindingIndexArray; BDescVec tmp = genDefaultBindings(shState->config()); binds->assign(tmp.begin(), tmp.end()); - [self loadBinds]; - [_table reloadData]; - if (currentButtonCode) [self setButtonNames:currentButtonCode]; + [self setNotListening:false]; } - (void)viewDidLoad { [super viewDidLoad]; + isListening = false; + keepCurrentButtonSelection = false; + [self initDelegateWithTable:_table]; _table.delegate = self; _table.dataSource = self; - [_table reloadData]; + [self setNotListening:true]; + _table.enabled = true; + + bindingBox.title = @""; + [self setButtonNames:0]; } - (void)keyDown:(NSEvent *)event { - NSLog([NSString stringWithFormat:@"%d", event.keyCode]); + [super keyDown:event]; + if (!isListening) return; + + BindingDesc d; + d.target = (Input::ButtonCode)currentButtonCode; + SourceDesc s; + s.type = Key; + s.d.scan = darwin_scancode_table[event.keyCode]; + d.src = s; + binds->push_back(d); + [self setNotListening:true]; +} + +#define checkButtonStart if (0) {} +#define checkButtonEnd else { return; } +#define checkButtonElement(e, b, n) \ +else if (element == gamepad.e && gamepad.b.isPressed) { \ +s.type = JButton; \ +s.d.jb = n; \ +} + +#define checkButtonAlt(b, n) checkButtonElement(b, b, n) + +#define checkButton(b, n) checkButtonAlt(button##b, n) + +#define setAxisData(a, n) \ +GCControllerAxisInput *axis = gamepad.a; \ +s.type = JAxis; \ +s.d.ja.axis = n; \ +s.d.ja.dir = (axis.value >= 0) ? AxisDir::Positive : AxisDir::Negative; + +#define checkAxis(el, a, n) else if (element == gamepad.el && (gamepad.el.a.value >= 0.5 || gamepad.el.a.value <= -0.5)) { setAxisData(el.a, n); } + +- (void)registerJoystickAction:(GCExtendedGamepad*)gamepad element:(GCControllerElement*)element { + if (!isListening) return; + + BindingDesc d; + d.target = (Input::ButtonCode)currentButtonCode; + SourceDesc s; + + checkButtonStart + checkButton(A, 0) + checkButton(B, 1) + checkButton(X, 2) + checkButton(Y, 3) + checkButtonElement(dpad, dpad.up, 11) + checkButtonElement(dpad, dpad.down, 12) + checkButtonElement(dpad, dpad.left, 13) + checkButtonElement(dpad, dpad.right, 14) + checkButtonAlt(leftShoulder, 9) + checkButtonAlt(rightShoulder, 10) + checkButtonAlt(leftThumbstickButton, 7) + checkButtonAlt(rightThumbstickButton, 8) + checkButton(Home, 5) + checkButton(Menu, 6) + checkButton(Options, 4) + + checkAxis(leftThumbstick, xAxis, 0) + checkAxis(leftThumbstick, yAxis, 1) + checkAxis(rightThumbstick, xAxis, 2) + checkAxis(rightThumbstick, yAxis, 3) + + else if (element == gamepad.leftTrigger && (gamepad.leftTrigger.value >= 0.5 || gamepad.leftTrigger.value <= -0.5)) { + GCControllerButtonInput *trigger = gamepad.leftTrigger; + s.type = JAxis; + s.d.ja.axis = 4; + s.d.ja.dir = AxisDir::Positive; + } + + else if (element == gamepad.rightTrigger && (gamepad.rightTrigger.value >= 0.5 || gamepad.rightTrigger.value <= -0.5)) { + GCControllerButtonInput *trigger = gamepad.rightTrigger; + s.type = JAxis; + s.d.ja.axis = 5; + s.d.ja.dir = AxisDir::Positive; + } + + checkButtonEnd; + + d.src = s; + binds->push_back(d); + [self setNotListening:true]; } +(NSString*)nameForBinding:(SourceDesc&)desc { @@ -233,18 +360,43 @@ if (!data.config.kbActionNames.value.empty()) bindingNames[@(Input::code)] = \ } - (void)tableViewSelectionDidChange:(NSNotification *)notification { - int buttonCode = inputMapRowToCode[_table.selectedRow]; - currentButtonCode = buttonCode; + if (isListening) + isListening = false; - [self setButtonNames:buttonCode]; + if (keepCurrentButtonSelection) { + if (keepCurrentButtonSelection) keepCurrentButtonSelection = false; + [_table deselectRow:_table.selectedRow]; + [self setButtonNames:currentButtonCode]; + bindingBox.title = bindingNames[@(currentButtonCode)]; + return; + } + + if (_table.selectedRow > -1) { + int buttonCode = inputMapRowToCode[_table.selectedRow]; + currentButtonCode = buttonCode; + [self setButtonNames:buttonCode]; + bindingBox.title = bindingNames[@(currentButtonCode)]; + } + else { + [self setButtonNames:0]; + bindingBox.title = @""; + } } - (int)setButtonNames:(int)input { + if (!input) { + bindingButton1.title = @""; + bindingButton2.title = bindingButton1.title; + bindingButton3.title = bindingButton1.title; + bindingButton4.title = bindingButton1.title; + [self enableButtons:false]; + return 0; + } BindingIndexArray *nsbind = nsbinds[@(input)]; NSMutableArray *pnames = [NSMutableArray new]; for (int i = 0; i < 4; i++) { if (i > nsbind.count - 1) { - [pnames addObject:@"N/A"]; + [pnames addObject:@"(Empty)"]; } else { BindingDesc &b = binds->at(nsbind[i].intValue); @@ -272,16 +424,33 @@ if (!data.config.kbActionNames.value.empty()) bindingNames[@(Input::code)] = \ } - (IBAction)binding1Clicked:(NSButton *)sender { - [self removeBinding:0 forInput:currentButtonCode]; + // Need at least one binding, for now + if (nsbinds[@(currentButtonCode)].count > 1) { + [self removeBinding:0 forInput:currentButtonCode]; + return; + } + [self setListening:sender]; } - (IBAction)binding2Clicked:(NSButton *)sender { - [self removeBinding:1 forInput:currentButtonCode]; + if (nsbinds[@(currentButtonCode)].count > 1) { + [self removeBinding:1 forInput:currentButtonCode]; + return; + } + [self setListening:sender]; } - (IBAction)binding3Clicked:(NSButton *)sender { - [self removeBinding:2 forInput:currentButtonCode]; + if (nsbinds[@(currentButtonCode)].count > 2) { + [self removeBinding:2 forInput:currentButtonCode]; + return; + } + [self setListening:sender]; } - (IBAction)binding4Clicked:(NSButton *)sender { - [self removeBinding:3 forInput:currentButtonCode]; + if (nsbinds[@(currentButtonCode)].count > 3) { + [self removeBinding:3 forInput:currentButtonCode]; + return; + } + [self setListening:sender]; } - (void)removeBinding:(int)bindIndex forInput:(int)input { @@ -289,9 +458,42 @@ if (!data.config.kbActionNames.value.empty()) bindingNames[@(Input::code)] = \ int bi = bind[bindIndex].intValue; binds->erase(binds->begin() + bi); + [self setNotListening:true]; +} + +- (void)setListening:(NSButton*)src { + if (isListening) { + [self setNotListening:true]; + return; + } + + // Stops receiving keyDown events if it's disabled, apparently + //_table.enabled = false; + + [self enableButtons:false]; + + if (src == nil) return; + + src.title = @"Click to Cancel..."; + src.enabled = true; + isListening = true; + + NSArray* controllers = [GCController controllers]; + if (controllers.count <= 0) return; + GCController *gamepad = controllers[0]; + if (gamepad.extendedGamepad == nil || gamepad.extendedGamepad.valueChangedHandler != nil) return; + gamepad.extendedGamepad.valueChangedHandler = ^(GCExtendedGamepad *gamepad, GCControllerElement *element) + {[self registerJoystickAction:gamepad element:element];}; +} + +- (void)setNotListening:(bool)keepCurrentSelection { [self loadBinds]; + + keepCurrentButtonSelection = keepCurrentSelection; + isListening = false; [_table reloadData]; - [self setButtonNames: input]; + [self setButtonNames:currentButtonCode]; + } -(void)dealloc { diff --git a/macos/views/sdl_codes.h b/macos/views/sdl_codes.h new file mode 100644 index 00000000..d5b115f6 --- /dev/null +++ b/macos/views/sdl_codes.h @@ -0,0 +1,146 @@ +// +// sdl_codes.h +// mkxp-z +// +// Created by ゾロアーク on 2/16/21. +// + +#ifndef sdl_codes_h +#define sdl_codes_h + +#include + +// Stuff straight from SDL to make my life easier. + +static const SDL_Scancode darwin_scancode_table[] = { + /* 0 */ SDL_SCANCODE_A, + /* 1 */ SDL_SCANCODE_S, + /* 2 */ SDL_SCANCODE_D, + /* 3 */ SDL_SCANCODE_F, + /* 4 */ SDL_SCANCODE_H, + /* 5 */ SDL_SCANCODE_G, + /* 6 */ SDL_SCANCODE_Z, + /* 7 */ SDL_SCANCODE_X, + /* 8 */ SDL_SCANCODE_C, + /* 9 */ SDL_SCANCODE_V, + /* 10 */ SDL_SCANCODE_NONUSBACKSLASH, /* SDL_SCANCODE_NONUSBACKSLASH on ANSI and JIS keyboards (if this key would exist there), SDL_SCANCODE_GRAVE on ISO. (The USB keyboard driver actually translates these usage codes to different virtual key codes depending on whether the keyboard is ISO/ANSI/JIS. That's why you have to help it identify the keyboard type when you plug in a PC USB keyboard. It's a historical thing - ADB keyboards are wired this way.) */ + /* 11 */ SDL_SCANCODE_B, + /* 12 */ SDL_SCANCODE_Q, + /* 13 */ SDL_SCANCODE_W, + /* 14 */ SDL_SCANCODE_E, + /* 15 */ SDL_SCANCODE_R, + /* 16 */ SDL_SCANCODE_Y, + /* 17 */ SDL_SCANCODE_T, + /* 18 */ SDL_SCANCODE_1, + /* 19 */ SDL_SCANCODE_2, + /* 20 */ SDL_SCANCODE_3, + /* 21 */ SDL_SCANCODE_4, + /* 22 */ SDL_SCANCODE_6, + /* 23 */ SDL_SCANCODE_5, + /* 24 */ SDL_SCANCODE_EQUALS, + /* 25 */ SDL_SCANCODE_9, + /* 26 */ SDL_SCANCODE_7, + /* 27 */ SDL_SCANCODE_MINUS, + /* 28 */ SDL_SCANCODE_8, + /* 29 */ SDL_SCANCODE_0, + /* 30 */ SDL_SCANCODE_RIGHTBRACKET, + /* 31 */ SDL_SCANCODE_O, + /* 32 */ SDL_SCANCODE_U, + /* 33 */ SDL_SCANCODE_LEFTBRACKET, + /* 34 */ SDL_SCANCODE_I, + /* 35 */ SDL_SCANCODE_P, + /* 36 */ SDL_SCANCODE_RETURN, + /* 37 */ SDL_SCANCODE_L, + /* 38 */ SDL_SCANCODE_J, + /* 39 */ SDL_SCANCODE_APOSTROPHE, + /* 40 */ SDL_SCANCODE_K, + /* 41 */ SDL_SCANCODE_SEMICOLON, + /* 42 */ SDL_SCANCODE_BACKSLASH, + /* 43 */ SDL_SCANCODE_COMMA, + /* 44 */ SDL_SCANCODE_SLASH, + /* 45 */ SDL_SCANCODE_N, + /* 46 */ SDL_SCANCODE_M, + /* 47 */ SDL_SCANCODE_PERIOD, + /* 48 */ SDL_SCANCODE_TAB, + /* 49 */ SDL_SCANCODE_SPACE, + /* 50 */ SDL_SCANCODE_GRAVE, /* SDL_SCANCODE_GRAVE on ANSI and JIS keyboards, SDL_SCANCODE_NONUSBACKSLASH on ISO (see comment about virtual key code 10 above) */ + /* 51 */ SDL_SCANCODE_BACKSPACE, + /* 52 */ SDL_SCANCODE_KP_ENTER, /* keyboard enter on portables */ + /* 53 */ SDL_SCANCODE_ESCAPE, + /* 54 */ SDL_SCANCODE_RGUI, + /* 55 */ SDL_SCANCODE_LGUI, + /* 56 */ SDL_SCANCODE_LSHIFT, + /* 57 */ SDL_SCANCODE_CAPSLOCK, + /* 58 */ SDL_SCANCODE_LALT, + /* 59 */ SDL_SCANCODE_LCTRL, + /* 60 */ SDL_SCANCODE_RSHIFT, + /* 61 */ SDL_SCANCODE_RALT, + /* 62 */ SDL_SCANCODE_RCTRL, + /* 63 */ SDL_SCANCODE_RGUI, /* fn on portables, acts as a hardware-level modifier already, so we don't generate events for it, also XK_Meta_R */ + /* 64 */ SDL_SCANCODE_F17, + /* 65 */ SDL_SCANCODE_KP_PERIOD, + /* 66 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 67 */ SDL_SCANCODE_KP_MULTIPLY, + /* 68 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 69 */ SDL_SCANCODE_KP_PLUS, + /* 70 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 71 */ SDL_SCANCODE_NUMLOCKCLEAR, + /* 72 */ SDL_SCANCODE_VOLUMEUP, + /* 73 */ SDL_SCANCODE_VOLUMEDOWN, + /* 74 */ SDL_SCANCODE_MUTE, + /* 75 */ SDL_SCANCODE_KP_DIVIDE, + /* 76 */ SDL_SCANCODE_KP_ENTER, /* keypad enter on external keyboards, fn-return on portables */ + /* 77 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 78 */ SDL_SCANCODE_KP_MINUS, + /* 79 */ SDL_SCANCODE_F18, + /* 80 */ SDL_SCANCODE_F19, + /* 81 */ SDL_SCANCODE_KP_EQUALS, + /* 82 */ SDL_SCANCODE_KP_0, + /* 83 */ SDL_SCANCODE_KP_1, + /* 84 */ SDL_SCANCODE_KP_2, + /* 85 */ SDL_SCANCODE_KP_3, + /* 86 */ SDL_SCANCODE_KP_4, + /* 87 */ SDL_SCANCODE_KP_5, + /* 88 */ SDL_SCANCODE_KP_6, + /* 89 */ SDL_SCANCODE_KP_7, + /* 90 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 91 */ SDL_SCANCODE_KP_8, + /* 92 */ SDL_SCANCODE_KP_9, + /* 93 */ SDL_SCANCODE_INTERNATIONAL3, /* Cosmo_USB2ADB.c says "Yen (JIS)" */ + /* 94 */ SDL_SCANCODE_INTERNATIONAL1, /* Cosmo_USB2ADB.c says "Ro (JIS)" */ + /* 95 */ SDL_SCANCODE_KP_COMMA, /* Cosmo_USB2ADB.c says ", JIS only" */ + /* 96 */ SDL_SCANCODE_F5, + /* 97 */ SDL_SCANCODE_F6, + /* 98 */ SDL_SCANCODE_F7, + /* 99 */ SDL_SCANCODE_F3, + /* 100 */ SDL_SCANCODE_F8, + /* 101 */ SDL_SCANCODE_F9, + /* 102 */ SDL_SCANCODE_LANG2, /* Cosmo_USB2ADB.c says "Eisu" */ + /* 103 */ SDL_SCANCODE_F11, + /* 104 */ SDL_SCANCODE_LANG1, /* Cosmo_USB2ADB.c says "Kana" */ + /* 105 */ SDL_SCANCODE_PRINTSCREEN, /* On ADB keyboards, this key is labeled "F13/print screen". Problem: USB has different usage codes for these two functions. On Apple USB keyboards, the key is labeled "F13" and sends the F13 usage code (SDL_SCANCODE_F13). I decided to use SDL_SCANCODE_PRINTSCREEN here nevertheless since SDL applications are more likely to assume the presence of a print screen key than an F13 key. */ + /* 106 */ SDL_SCANCODE_F16, + /* 107 */ SDL_SCANCODE_SCROLLLOCK, /* F14/scroll lock, see comment about F13/print screen above */ + /* 108 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 109 */ SDL_SCANCODE_F10, + /* 110 */ SDL_SCANCODE_APPLICATION, /* windows contextual menu key, fn-enter on portables */ + /* 111 */ SDL_SCANCODE_F12, + /* 112 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 113 */ SDL_SCANCODE_PAUSE, /* F15/pause, see comment about F13/print screen above */ + /* 114 */ SDL_SCANCODE_INSERT, /* the key is actually labeled "help" on Apple keyboards, and works as such in Mac OS, but it sends the "insert" usage code even on Apple USB keyboards */ + /* 115 */ SDL_SCANCODE_HOME, + /* 116 */ SDL_SCANCODE_PAGEUP, + /* 117 */ SDL_SCANCODE_DELETE, + /* 118 */ SDL_SCANCODE_F4, + /* 119 */ SDL_SCANCODE_END, + /* 120 */ SDL_SCANCODE_F2, + /* 121 */ SDL_SCANCODE_PAGEDOWN, + /* 122 */ SDL_SCANCODE_F1, + /* 123 */ SDL_SCANCODE_LEFT, + /* 124 */ SDL_SCANCODE_RIGHT, + /* 125 */ SDL_SCANCODE_DOWN, + /* 126 */ SDL_SCANCODE_UP, + /* 127 */ SDL_SCANCODE_POWER +}; + +#endif /* sdl_codes_h */ diff --git a/macos/views/settingsmenu.xib b/macos/views/settingsmenu.xib index 60902529..e402c4af 100644 --- a/macos/views/settingsmenu.xib +++ b/macos/views/settingsmenu.xib @@ -9,23 +9,20 @@ + + - + - - - - - - + - + @@ -34,9 +31,9 @@ - + - + @@ -49,7 +46,7 @@ - + @@ -57,11 +54,11 @@ - + - + @@ -69,7 +66,7 @@ - + @@ -89,11 +86,11 @@ - + - + @@ -101,7 +98,7 @@ - + @@ -121,11 +118,11 @@ - + - + @@ -133,7 +130,7 @@ - + @@ -153,11 +150,11 @@ - + - + @@ -165,7 +162,7 @@ - + @@ -185,11 +182,11 @@ - + - + @@ -197,7 +194,7 @@ - + @@ -221,7 +218,7 @@ diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 4242957d..3de44033 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -29,15 +29,19 @@ #include #include - - #include #include #include #include "sharedstate.h" #include "graphics.h" + +#ifndef MKXPZ_BUILD_XCODE #include "settingsmenu.h" +#else +#include "system/system.h" +#endif + #include "al-util.h" #include "debugwriter.h" @@ -176,8 +180,12 @@ void EventThread::process(RGSSThreadData &rtData) SDL_Haptic *hap; memset(&hapticEffect, 0, sizeof(SDL_HapticEffect)); textInputBuffer.clear(); - +#ifndef MKXPZ_BUILD_XCODE SettingsMenu *sMenu = 0; +#else + // Will always be 0 + void *sMenu = 0; +#endif while (true) { @@ -186,7 +194,7 @@ void EventThread::process(RGSSThreadData &rtData) Debug() << "EventThread: Event error"; break; } - +#ifndef MKXPZ_BUILD_XCODE if (sMenu && sMenu->onEvent(event)) { if (sMenu->destroyReq()) @@ -199,6 +207,7 @@ void EventThread::process(RGSSThreadData &rtData) continue; } +#endif /* Preselect and discard unwanted events here */ switch (event.type) @@ -294,6 +303,7 @@ void EventThread::process(RGSSThreadData &rtData) if (event.key.keysym.scancode == SDL_SCANCODE_F1) { +#ifndef MKXPZ_BUILD_XCODE if (!sMenu) { sMenu = new SettingsMenu(rtData); @@ -301,6 +311,9 @@ void EventThread::process(RGSSThreadData &rtData) } sMenu->raise(); +#else + openSettingsWindow(); +#endif } if (event.key.keysym.scancode == SDL_SCANCODE_F2) @@ -493,6 +506,7 @@ void EventThread::process(RGSSThreadData &rtData) break; case REQUEST_SETTINGS : +#ifndef MKXPZ_BUILD_XCODE if (!sMenu) { sMenu = new SettingsMenu(rtData); @@ -500,6 +514,9 @@ void EventThread::process(RGSSThreadData &rtData) } sMenu->raise(); +#else + openSettingsWindow(); +#endif break; case REQUEST_RUMBLE : diff --git a/src/settingsmenu.cpp b/src/settingsmenu.cpp index f4df9aa9..8ae67001 100644 --- a/src/settingsmenu.cpp +++ b/src/settingsmenu.cpp @@ -1167,7 +1167,8 @@ bool SettingsMenu::onEvent(const SDL_Event &event) void SettingsMenu::raise() { - SDL_RaiseWindow(p->window); + openSettingsWindow(); + //SDL_RaiseWindow(p->window); } bool SettingsMenu::destroyReq() const diff --git a/src/system/systemImplApple.mm b/src/system/systemImplApple.mm index 129f84a0..d64f4c78 100644 --- a/src/system/systemImplApple.mm +++ b/src/system/systemImplApple.mm @@ -20,6 +20,12 @@ std::string systemImpl::getUserName() { } +// constant, if it's not nil then just raise the menu instead +SettingsMenu *smenu = nil; void openSettingsWindow() { - [SettingsMenu openWindow]; + if (smenu == nil) { + smenu = [SettingsMenu openWindow]; + return; + } + [smenu raise]; }