mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
Wires joystick support all the way through to machines.
Ensures there's only one joystick manager, which is shared by all machines, with input going only to the key window.
This commit is contained in:
parent
8f4042c4bb
commit
1362906f94
@ -12,6 +12,8 @@
|
||||
|
||||
#import "CSOpenGLView.h"
|
||||
#import "CSAudioQueue.h"
|
||||
|
||||
#import "CSBestEffortUpdater.h"
|
||||
#import "CSJoystickManager.h"
|
||||
|
||||
#include "KeyCodes.h"
|
||||
|
@ -9,4 +9,5 @@
|
||||
import Cocoa
|
||||
|
||||
class DocumentController: NSDocumentController {
|
||||
let joystickManager = CSJoystickManager()
|
||||
}
|
||||
|
@ -229,6 +229,13 @@ class MachineDocument:
|
||||
func windowDidResignKey(_ notification: Notification) {
|
||||
if let machine = self.machine {
|
||||
machine.clearAllKeys()
|
||||
machine.joystickManager = nil
|
||||
}
|
||||
}
|
||||
|
||||
func windowDidBecomeKey(_ notification: Notification) {
|
||||
if let machine = self.machine {
|
||||
machine.joystickManager = (DocumentController.shared as! DocumentController).joystickManager
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
Buttons have an index and are either currently pressed, or not.
|
||||
*/
|
||||
@interface CSJoystickButton: NSObject
|
||||
/// The button index. By convention the USB spec defines the first button as number 1.
|
||||
@property(nonatomic, readonly) NSInteger index;
|
||||
@property(nonatomic, readonly) bool isPressed;
|
||||
@end
|
||||
|
@ -12,6 +12,7 @@
|
||||
#import "CSFastLoading.h"
|
||||
#import "CSOpenGLView.h"
|
||||
#import "CSStaticAnalyser.h"
|
||||
#import "CSJoystickManager.h"
|
||||
|
||||
@class CSMachine;
|
||||
@protocol CSMachineDelegate
|
||||
@ -74,6 +75,7 @@ typedef NS_ENUM(NSInteger, CSMachineKeyboardInputMode) {
|
||||
@property (nonatomic, readonly) BOOL hasKeyboard;
|
||||
@property (nonatomic, readonly) BOOL hasJoystick;
|
||||
@property (nonatomic, assign) CSMachineKeyboardInputMode inputMode;
|
||||
@property (nonatomic, nullable) CSJoystickManager *joystickManager;
|
||||
|
||||
// LED list.
|
||||
@property (nonatomic, readonly, nonnull) NSArray<NSString *> *leds;
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "Typer.hpp"
|
||||
#include "../../../../Activity/Observer.hpp"
|
||||
|
||||
#import "CSJoystickManager.h"
|
||||
#import "CSStaticAnalyser+TargetVector.h"
|
||||
#import "NSBundle+DataResource.h"
|
||||
#import "NSData+StdVector.h"
|
||||
@ -76,6 +75,7 @@ struct ActivityObserver: public Activity::Observer {
|
||||
|
||||
CSStaticAnalyser *_analyser;
|
||||
std::unique_ptr<Machine::DynamicMachine> _machine;
|
||||
JoystickMachine::Machine *_joystickMachine;
|
||||
|
||||
CSJoystickManager *_joystickManager;
|
||||
std::bitset<65536> _depressedKeys;
|
||||
@ -93,8 +93,6 @@ struct ActivityObserver: public Activity::Observer {
|
||||
|
||||
_inputMode = _machine->keyboard_machine() ? CSMachineKeyboardInputModeKeyboard : CSMachineKeyboardInputModeJoystick;
|
||||
|
||||
_joystickManager = [[CSJoystickManager alloc] init];
|
||||
|
||||
_leds = [[NSMutableArray alloc] init];
|
||||
Activity::Source *const activity_source = _machine->activity_source();
|
||||
if(activity_source) {
|
||||
@ -106,6 +104,8 @@ struct ActivityObserver: public Activity::Observer {
|
||||
|
||||
_speakerDelegate.machine = self;
|
||||
_speakerDelegate.machineAccessLock = _delegateMachineAccessLock;
|
||||
|
||||
_joystickMachine = _machine->joystick_machine();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -166,6 +166,54 @@ struct ActivityObserver: public Activity::Observer {
|
||||
|
||||
- (void)runForInterval:(NSTimeInterval)interval {
|
||||
@synchronized(self) {
|
||||
if(_joystickMachine && _joystickManager) {
|
||||
[_joystickManager update];
|
||||
|
||||
// TODO: configurable mapping from physical joypad inputs to machine inputs.
|
||||
// Until then, apply a default mapping.
|
||||
|
||||
size_t c = 0;
|
||||
std::vector<std::unique_ptr<Inputs::Joystick>> &machine_joysticks = _joystickMachine->get_joysticks();
|
||||
for(CSJoystick *joystick in _joystickManager.joysticks) {
|
||||
size_t target = c % machine_joysticks.size();
|
||||
++++c;
|
||||
|
||||
// Post the first two analogue axes presented by the controller as horizontal and vertical inputs,
|
||||
// unless the user seems to be using a hat.
|
||||
// SDL will return a value in the range [-32768, 32767], so map from that to [0, 1.0]
|
||||
if(!joystick.hats.count || !joystick.hats[0].direction) {
|
||||
if(joystick.axes.count > 0) {
|
||||
const float x_axis = joystick.axes[0].position;
|
||||
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Horizontal), x_axis);
|
||||
}
|
||||
if(joystick.axes.count > 1) {
|
||||
const float y_axis = joystick.axes[1].position;
|
||||
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Vertical), y_axis);
|
||||
}
|
||||
}
|
||||
|
||||
// Forward hats as directions; hats always override analogue inputs.
|
||||
for(CSJoystickHat *hat in joystick.hats) {
|
||||
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Up), !!(hat.direction & CSJoystickHatDirectionUp));
|
||||
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Down), !!(hat.direction & CSJoystickHatDirectionDown));
|
||||
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Left), !!(hat.direction & CSJoystickHatDirectionLeft));
|
||||
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Right), !!(hat.direction & CSJoystickHatDirectionRight));
|
||||
}
|
||||
|
||||
// Forward all fire buttons, mapping as a function of index.
|
||||
if(machine_joysticks[target]->get_number_of_fire_buttons()) {
|
||||
std::vector<bool> button_states((size_t)machine_joysticks[target]->get_number_of_fire_buttons());
|
||||
for(CSJoystickButton *button in joystick.buttons) {
|
||||
if(button.isPressed) button_states[(size_t)(((int)button.index - 1) % machine_joysticks[target]->get_number_of_fire_buttons())] = true;
|
||||
}
|
||||
for(size_t index = 0; index < button_states.size(); ++index) {
|
||||
machine_joysticks[target]->set_input(
|
||||
Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Fire, index),
|
||||
button_states[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_machine->crt_machine()->run_for(interval);
|
||||
}
|
||||
}
|
||||
@ -202,6 +250,18 @@ struct ActivityObserver: public Activity::Observer {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setJoystickManager:(CSJoystickManager *)joystickManager {
|
||||
@synchronized(self) {
|
||||
_joystickManager = joystickManager;
|
||||
if(_joystickMachine) {
|
||||
std::vector<std::unique_ptr<Inputs::Joystick>> &machine_joysticks = _joystickMachine->get_joysticks();
|
||||
for(const auto &joystick: machine_joysticks) {
|
||||
joystick->reset_all_inputs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setKey:(uint16_t)key characters:(NSString *)characters isPressed:(BOOL)isPressed {
|
||||
auto keyboard_machine = _machine->keyboard_machine();
|
||||
if(self.inputMode == CSMachineKeyboardInputModeKeyboard && keyboard_machine) {
|
||||
|
Loading…
Reference in New Issue
Block a user