metaforce/Runtime/CGameOptionsTouchBarMac.mm

261 lines
11 KiB
Plaintext

#include "CGameOptions.hpp"
#include "CGameOptionsTouchBar.hpp"
#include "GameGlobalObjects.hpp"
#include "GuiSys/CStringTable.hpp"
#include "MP1/MP1.hpp"
#include <AppKit/AppKit.h>
#if !__has_feature(objc_arc)
#error ARC Required
#endif
static NSColor *BlueConfirm() {
return [NSColor colorWithSRGBRed:0 / 255.f green:130 / 255.f blue:215 / 255.f alpha:1.f];
}
@interface GameOptionsTouchBar : NSObject <NSTouchBarDelegate> {
@public
metaforce::CStringTable *_pauseScreenStrg;
metaforce::CGameOptionsTouchBar::EAction _action;
std::pair<int, int> _selection;
int _value, _pendingValue;
}
- (IBAction)onBack:(id)sender;
- (IBAction)onSlide:(id)sender;
- (IBAction)onSet0:(id)sender;
- (IBAction)onSet1:(id)sender;
- (IBAction)onSet2:(id)sender;
- (IBAction)onLeft:(id)sender;
- (IBAction)onRight:(id)sender;
@end
@implementation GameOptionsTouchBar
- (NSTouchBar *)makeTouchBar {
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items = @[ @"optionsGroup" ];
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
touchBar.principalItemIdentifier = @"optionsGroup";
return touchBar;
}
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
if ([identifier isEqualToString:@"optionsGroup"]) {
NSGroupTouchBarItem *item = [[NSGroupTouchBarItem alloc] initWithIdentifier:identifier];
NSTouchBar *touchBar = [NSTouchBar new];
touchBar.delegate = self;
id items;
if (_selection.first == -1) {
items = [NSMutableArray arrayWithCapacity:5];
[items addObject:@"back"];
for (int i = 0; i < 4; ++i)
[items addObject:[NSString stringWithFormat:@"left/%d", i]];
} else if (_selection.second == -1) {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
items = [NSMutableArray arrayWithCapacity:opt.first + 1];
[items addObject:@"back"];
for (int i = 0; i < opt.first; ++i)
[items addObject:[NSString stringWithFormat:@"right/%d", i]];
} else {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
const metaforce::SGameOption &subopt = opt.second[_selection.second];
if (subopt.type == metaforce::EOptionType::Float)
items = @[ @"back", @"value" ];
else if (subopt.type == metaforce::EOptionType::DoubleEnum)
items = @[ @"back", @"label", @"double0", @"double1" ];
else if (subopt.type == metaforce::EOptionType::TripleEnum)
items = @[ @"back", @"label", @"triple0", @"triple1", @"triple2" ];
}
touchBar.customizationRequiredItemIdentifiers = items;
touchBar.defaultItemIdentifiers = items;
item.groupTouchBar = touchBar;
return item;
} else if ([identifier isEqualToString:@"back"]) {
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarGoBackTemplate]
target:self
action:@selector(onBack:)];
item.view = button;
return item;
} else if ([identifier isEqualToString:@"label"]) {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
const metaforce::SGameOption &subopt = opt.second[_selection.second];
const char16_t *cStr = _pauseScreenStrg->GetString(subopt.stringId);
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSTextField *label = [NSTextField labelWithString:[str stringByAppendingString:@":"]];
item.view = label;
return item;
} else if ([identifier isEqualToString:@"value"]) {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
const metaforce::SGameOption &subopt = opt.second[_selection.second];
const char16_t *cStr = _pauseScreenStrg->GetString(subopt.stringId);
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSSliderTouchBarItem *item = [[NSSliderTouchBarItem alloc] initWithIdentifier:identifier];
NSSlider *slider = [NSSlider sliderWithValue:_value
minValue:subopt.minVal
maxValue:subopt.maxVal
target:nil
action:nil];
item.target = self;
item.action = @selector(onSlide:);
item.slider = slider;
item.label = str;
return item;
} else if ([identifier isEqualToString:@"double0"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(95); // Off
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet0:)];
if (_value == 0)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"double1"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(94); // On
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet1:)];
if (_value == 1)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"triple0"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(96); // Mono
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet0:)];
if (_value == 0)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"triple1"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(97); // Stereo
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet1:)];
if (_value == 1)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else if ([identifier isEqualToString:@"triple2"]) {
const char16_t *cStr = _pauseScreenStrg->GetString(98); // Dolby
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onSet2:)];
if (_value == 2)
button.bezelColor = BlueConfirm();
item.view = button;
return item;
} else {
NSArray<NSString *> *pc = [identifier pathComponents];
if ([pc count] == 2) {
NSString *first = [pc objectAtIndex:0];
if ([first isEqualToString:@"left"]) {
auto idx = strtoul([[pc objectAtIndex:1] UTF8String], nullptr, 10);
const char16_t *cStr = _pauseScreenStrg->GetString(16 + idx);
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onLeft:)];
button.tag = idx;
item.view = button;
return item;
} else if ([first isEqualToString:@"right"]) {
const std::pair<int, const metaforce::SGameOption *> &opt = metaforce::GameOptionsRegistry[_selection.first];
auto idx = strtoul([[pc objectAtIndex:1] UTF8String], nullptr, 10);
const metaforce::SGameOption &subopt = opt.second[idx];
const char16_t *cStr = _pauseScreenStrg->GetString(subopt.stringId);
NSString *str = [NSString stringWithUTF8String:hecl::Char16ToUTF8(cStr).c_str()];
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
NSButton *button = [NSButton buttonWithTitle:str target:self action:@selector(onRight:)];
button.tag = idx;
item.view = button;
return item;
}
}
}
return nil;
}
- (IBAction)onBack:(id)sender {
_action = metaforce::CGameOptionsTouchBar::EAction::Back;
}
- (IBAction)onSlide:(id)sender {
_pendingValue = [((NSSliderTouchBarItem *)sender).slider intValue];
_action = metaforce::CGameOptionsTouchBar::EAction::ValueChange;
}
- (IBAction)onSet0:(id)sender {
_pendingValue = 0;
_action = metaforce::CGameOptionsTouchBar::EAction::ValueChange;
}
- (IBAction)onSet1:(id)sender {
_pendingValue = 1;
_action = metaforce::CGameOptionsTouchBar::EAction::ValueChange;
}
- (IBAction)onSet2:(id)sender {
_pendingValue = 2;
_action = metaforce::CGameOptionsTouchBar::EAction::ValueChange;
}
- (IBAction)onLeft:(id)sender {
_selection.first = ((NSButton *)sender).tag;
_action = metaforce::CGameOptionsTouchBar::EAction::Advance;
}
- (IBAction)onRight:(id)sender {
_selection.second = ((NSButton *)sender).tag;
_action = metaforce::CGameOptionsTouchBar::EAction::Advance;
}
@end
namespace metaforce {
class CGameOptionsTouchBarMac : public CGameOptionsTouchBar {
TLockedToken<CStringTable> m_pauseScreen;
GameOptionsTouchBar *m_touchBar;
bool m_initialized = false;
public:
CGameOptionsTouchBarMac() {
m_pauseScreen = g_SimplePool->GetObj("STRG_PauseScreen");
m_touchBar = [GameOptionsTouchBar new];
m_touchBar->_pauseScreenStrg = m_pauseScreen.GetObj();
m_touchBar->_selection = std::make_pair(-1, -1);
m_touchBar->_value = -1;
}
EAction PopAction() {
if (m_touchBar->_action != EAction::None) {
EAction action = m_touchBar->_action;
m_touchBar->_action = EAction::None;
return action;
}
return EAction::None;
}
void GetSelection(int &left, int &right, int &value) {
left = m_touchBar->_selection.first;
right = m_touchBar->_selection.second;
value = m_touchBar->_pendingValue;
}
void SetSelection(int left, int right, int value) {
if (m_initialized && left == m_touchBar->_selection.first && right == m_touchBar->_selection.second &&
value == m_touchBar->_value)
return;
m_initialized = true;
m_touchBar->_selection = std::make_pair(left, right);
m_touchBar->_value = value;
g_Main->GetMainWindow()->setTouchBarProvider((__bridge_retained void *)m_touchBar);
}
};
std::unique_ptr<CGameOptionsTouchBar> NewGameOptionsTouchBar() { return std::make_unique<CGameOptionsTouchBarMac>(); }
}