2024-10-08 18:33:13 +11:00

124 lines
4.4 KiB
Objective-C

//
// GCDevicePhysicalInput.h
// GameController
//
// Copyright © 2021 Apple Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <GameController/GCDevicePhysicalInputState.h>
#import <GameController/GCDevicePhysicalInputStateDiff.h>
@protocol GCDevice;
NS_ASSUME_NONNULL_BEGIN
/**
An objecting conforming to \c GCDevicePhysicalInput provides properties and
methods for accessing common physical elements - buttons, thumbsticks, dpads,
etc - of a device.
*/
API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0))
@protocol GCDevicePhysicalInput <GCDevicePhysicalInputState>
/**
The device that this profile is mapping input from.
*/
@property (weak, readonly) id<GCDevice> device;
/**
The dispatch queue that element value change handlers and other callbacks are
submitted on.
The default queue is the \c handlerQueue of the associated \c device. Set
this property if your application wants to receive input callbacks on a
different queue. You should set this property before configuring other
callbacks.
*/
@property (atomic, strong, nullable) dispatch_queue_t queue API_AVAILABLE(macos(14.0), ios(17.0), tvos(17.0));
#pragma mark Immediate Input
/**
Set this block to be notified when a value on a element changed. If multiple
elements change this block will be called for each element that changed.
The block is called on the \c queue configured for the physical input.
@param element
The element that has been modified.
*/
@property (atomic, copy, nullable) void (^elementValueDidChangeHandler)(__kindof id<GCDevicePhysicalInput> physicalInput, __kindof id<GCPhysicalInputElement> element);
/**
Polls the current state vector of the physical input and saves it to a new
instance.
If your application is heavily multithreaded this may also be useful to
guarantee atomicity of input handling as a snapshot will not change based on
further device input once it is taken.
@return An input state with the duplicated state vector of the current input.
*/
- (__kindof id<GCDevicePhysicalInputState>)capture;
#pragma mark Buffered Input
/**
Set this block to be notified when a new input state is available. Your
handler should repeatedly call \c -nextInputState until it returns \c nil to
drain the pending input states from the queue.
physicalInput.inputStateQueueDepth = 20;
physicalInput.inputStateAvailableHandler = ^(__kindof id<GCDevicePhysicalInput> physicalInput) {
id<GCDevicePhysicalInputState, GCDevicePhysicalInputStateDiff> nextInputState;
while ((nextInputState = [physicalInput nextInputState])) {
// You can grab the individual states of all elements that your app
// is interested in.
id<GCButtonElement> buttonA = nextInputState.buttons[GCInputButtonA];
BOOL buttonAPressed = buttonA.pressedInput.pressed;
if (buttonAPressed) {
// Handle button A pressed
}
// Your code can first query whether an element's input value changed
// from the prior input state.
GCDevicePhysicalInputElementChange buttonAChange = [nextInputState changeForElement:buttonA];
if (buttonAChange == GCDevicePhysicalInputElementChanged) {
// Handle button A input changed
}
// Or, your code can request an enumerator of elements with input
// values that changed from the prior input state
for (id<GCPhysicalInputElement> changedElement in nextInputState.changedElements) {
}
}
};
*/
@property (atomic, copy, nullable) void (^inputStateAvailableHandler)(__kindof id<GCDevicePhysicalInput> physicalInput);
/**
The maximum number of input states to buffer. If your application does not
drain the pending input states in the queue before this limit is reached, older
input states will be discarded - resulting in your application "missing" input
state changes.
The default value is \c one (no buffering). Smaller values are ignored. A
value of \c 20 should be more than enough to ensure no input state changes
are missed.
*/
@property (atomic, readwrite) NSInteger inputStateQueueDepth;
/**
Pop the oldest pending input state from the queue. This method returns \c nil
when there are no more input states pending.
*/
- (nullable __kindof id<GCDevicePhysicalInputState, GCDevicePhysicalInputStateDiff>)nextInputState;
@end
NS_ASSUME_NONNULL_END