game-input vocab w/ iokit backend
parent
ec593ad4c2
commit
f30042cc8c
|
@ -0,0 +1,273 @@
|
|||
USING: cocoa cocoa.plists core-foundation iokit iokit.hid
|
||||
kernel cocoa.enumeration destructors math.parser cocoa.application
|
||||
sequences locals combinators.short-circuit game-input threads
|
||||
symbols namespaces assocs hashtables arrays combinators
|
||||
core-foundation.run-loop accessors sequences.private
|
||||
alien.c-types math ;
|
||||
IN: game-input.backend.iokit
|
||||
|
||||
SINGLETON: iokit-game-input-backend
|
||||
|
||||
: hid-manager-matching ( matching-seq -- alien )
|
||||
f 0 IOHIDManagerCreate
|
||||
[ swap >plist IOHIDManagerSetDeviceMatchingMultiple ]
|
||||
keep ;
|
||||
|
||||
: devices-from-hid-manager ( manager -- vector )
|
||||
[
|
||||
IOHIDManagerCopyDevices
|
||||
[ &CFRelease NSFastEnumeration>vector ] [ f ] if*
|
||||
] with-destructors ;
|
||||
|
||||
: game-devices-matching-seq
|
||||
{
|
||||
H{ { "DeviceUsage" 4 } { "DeviceUsagePage" 1 } } ! joysticks
|
||||
H{ { "DeviceUsage" 5 } { "DeviceUsagePage" 1 } } ! gamepads
|
||||
H{ { "DeviceUsage" 6 } { "DeviceUsagePage" 1 } } ! keyboards
|
||||
} ; inline
|
||||
|
||||
: buttons-matching-hash
|
||||
H{ { "UsagePage" 9 } { "Type" 2 } } ; inline
|
||||
: keys-matching-hash
|
||||
H{ { "UsagePage" 7 } { "Type" 2 } } ; inline
|
||||
: x-axis-matching-hash
|
||||
H{ { "UsagePage" 1 } { "Usage" HEX: 30 } { "Type" 1 } } ; inline
|
||||
: y-axis-matching-hash
|
||||
H{ { "UsagePage" 1 } { "Usage" HEX: 31 } { "Type" 1 } } ; inline
|
||||
: z-axis-matching-hash
|
||||
H{ { "UsagePage" 1 } { "Usage" HEX: 32 } { "Type" 1 } } ; inline
|
||||
: rx-axis-matching-hash
|
||||
H{ { "UsagePage" 1 } { "Usage" HEX: 33 } { "Type" 1 } } ; inline
|
||||
: ry-axis-matching-hash
|
||||
H{ { "UsagePage" 1 } { "Usage" HEX: 34 } { "Type" 1 } } ; inline
|
||||
: rz-axis-matching-hash
|
||||
H{ { "UsagePage" 1 } { "Usage" HEX: 35 } { "Type" 1 } } ; inline
|
||||
: slider-matching-hash
|
||||
H{ { "UsagePage" 1 } { "Usage" HEX: 36 } { "Type" 1 } } ; inline
|
||||
: hat-switch-matching-hash
|
||||
H{ { "UsagePage" 1 } { "Usage" HEX: 39 } { "Type" 1 } } ; inline
|
||||
|
||||
: device-elements-matching ( device matching-hash -- vector )
|
||||
[
|
||||
>plist 0 IOHIDDeviceCopyMatchingElements
|
||||
[ &CFRelease NSFastEnumeration>vector ] [ f ] if*
|
||||
] with-destructors ;
|
||||
|
||||
: button-count ( device -- button-count )
|
||||
buttons-matching-hash device-elements-matching length ;
|
||||
|
||||
: ?axis ( device hash -- axis/f )
|
||||
device-elements-matching dup empty? [ drop f ] [ first ] if ;
|
||||
|
||||
: ?x-axis ( device -- ? )
|
||||
x-axis-matching-hash ?axis ;
|
||||
: ?y-axis ( device -- ? )
|
||||
y-axis-matching-hash ?axis ;
|
||||
: ?z-axis ( device -- ? )
|
||||
z-axis-matching-hash ?axis ;
|
||||
: ?rx-axis ( device -- ? )
|
||||
rx-axis-matching-hash ?axis ;
|
||||
: ?ry-axis ( device -- ? )
|
||||
ry-axis-matching-hash ?axis ;
|
||||
: ?rz-axis ( device -- ? )
|
||||
rz-axis-matching-hash ?axis ;
|
||||
: ?slider ( device -- ? )
|
||||
slider-matching-hash ?axis ;
|
||||
: ?hat-switch ( device -- ? )
|
||||
hat-switch-matching-hash ?axis ;
|
||||
|
||||
: hid-manager-matching-game-devices ( -- alien )
|
||||
game-devices-matching-seq hid-manager-matching ;
|
||||
|
||||
: device-property ( device key -- value )
|
||||
[
|
||||
<NSString> IOHIDDeviceGetProperty
|
||||
[ &CFRelease plist> ] [ f ] if*
|
||||
] with-destructors ;
|
||||
: element-property ( element key -- value )
|
||||
[
|
||||
<NSString> IOHIDElementGetProperty
|
||||
[ &CFRelease plist> ] [ f ] if*
|
||||
] with-destructors ;
|
||||
: set-element-property ( element key value -- )
|
||||
[ <NSString> ] [ >plist ] bi* IOHIDElementSetProperty drop ;
|
||||
: transfer-element-property ( element from-key to-key -- )
|
||||
[ dupd element-property ] dip swap set-element-property ;
|
||||
|
||||
: controller-device? ( device -- ? )
|
||||
{
|
||||
[ 1 4 IOHIDDeviceConformsTo ]
|
||||
[ 1 5 IOHIDDeviceConformsTo ]
|
||||
} 1|| ;
|
||||
|
||||
: element-usage ( element -- {usage-page,usage} )
|
||||
[ IOHIDElementGetUsagePage ] [ IOHIDElementGetUsage ] bi
|
||||
2array ;
|
||||
|
||||
: button? ( {usage-page,usage} -- ? )
|
||||
first 9 = ;
|
||||
: keyboard-key? ( {usage-page,usage} -- ? )
|
||||
first 7 = ;
|
||||
: x-axis? ( {usage-page,usage} -- ? )
|
||||
{ 1 HEX: 30 } = ;
|
||||
: y-axis? ( {usage-page,usage} -- ? )
|
||||
{ 1 HEX: 31 } = ;
|
||||
: z-axis? ( {usage-page,usage} -- ? )
|
||||
{ 1 HEX: 32 } = ;
|
||||
: rx-axis? ( {usage-page,usage} -- ? )
|
||||
{ 1 HEX: 33 } = ;
|
||||
: ry-axis? ( {usage-page,usage} -- ? )
|
||||
{ 1 HEX: 34 } = ;
|
||||
: rz-axis? ( {usage-page,usage} -- ? )
|
||||
{ 1 HEX: 35 } = ;
|
||||
: slider? ( {usage-page,usage} -- ? )
|
||||
{ 1 HEX: 36 } = ;
|
||||
: hat-switch? ( {usage-page,usage} -- ? )
|
||||
{ 1 HEX: 39 } = ;
|
||||
|
||||
: button-value ( value -- f/(0,1] )
|
||||
IOHIDValueGetIntegerValue dup zero? [ drop f ] when ;
|
||||
! XXX calibration
|
||||
: axis-value ( value -- [-1,1] )
|
||||
kIOHIDValueScaleTypeCalibrated IOHIDValueGetScaledValue ;
|
||||
: slider-value ( value -- [0,1] )
|
||||
kIOHIDValueScaleTypeCalibrated IOHIDValueGetScaledValue
|
||||
1.0 + 0.5 * ;
|
||||
: pov-value ( value -- pov-direction )
|
||||
! XXX
|
||||
IOHIDValueGetIntegerValue ;
|
||||
|
||||
: record-controller ( controller-state value -- )
|
||||
dup IOHIDValueGetElement element-usage {
|
||||
{ [ dup button? ] [ [ button-value ] [ second 1- ] bi* rot buttons>> set-nth ] }
|
||||
{ [ dup x-axis? ] [ drop axis-value >>x drop ] }
|
||||
{ [ dup y-axis? ] [ drop axis-value >>y drop ] }
|
||||
{ [ dup z-axis? ] [ drop axis-value >>z drop ] }
|
||||
{ [ dup rx-axis? ] [ drop axis-value >>rx drop ] }
|
||||
{ [ dup ry-axis? ] [ drop axis-value >>ry drop ] }
|
||||
{ [ dup rz-axis? ] [ drop axis-value >>rz drop ] }
|
||||
{ [ dup slider? ] [ drop slider-value >>slider drop ] }
|
||||
{ [ dup hat-switch? ] [ drop pov-value >>pov drop ] }
|
||||
[ 3drop ]
|
||||
} cond ;
|
||||
|
||||
SYMBOLS: +hid-manager+ +keyboard-state+ +controller-states+ ;
|
||||
|
||||
: ?set-nth ( value nth seq -- )
|
||||
2dup bounds-check? [ set-nth-unsafe ] [ 3drop ] if ;
|
||||
|
||||
: record-keyboard ( value -- )
|
||||
dup IOHIDValueGetElement element-usage keyboard-key? [
|
||||
[ IOHIDValueGetIntegerValue c-bool> ]
|
||||
[ IOHIDValueGetElement IOHIDElementGetUsage ] bi
|
||||
+keyboard-state+ get ?set-nth
|
||||
] [ drop ] if ;
|
||||
|
||||
: default-calibrate-saturation ( element -- )
|
||||
[ kIOHIDElementMinKey kIOHIDElementCalibrationSaturationMinKey transfer-element-property ]
|
||||
[ kIOHIDElementMaxKey kIOHIDElementCalibrationSaturationMaxKey transfer-element-property ]
|
||||
bi ;
|
||||
|
||||
: default-calibrate-axis ( element -- )
|
||||
[ kIOHIDElementCalibrationMinKey -1.0 set-element-property ]
|
||||
[ kIOHIDElementCalibrationMaxKey 1.0 set-element-property ]
|
||||
[ default-calibrate-saturation ]
|
||||
tri ;
|
||||
|
||||
: default-calibrate-slider ( element -- )
|
||||
[ kIOHIDElementCalibrationMinKey 0.0 set-element-property ]
|
||||
[ kIOHIDElementCalibrationMaxKey 1.0 set-element-property ]
|
||||
[ default-calibrate-saturation ]
|
||||
tri ;
|
||||
|
||||
: (default) ( ? quot -- )
|
||||
[ f ] if* ; inline
|
||||
|
||||
: <device-controller-state> ( device -- controller-state )
|
||||
{
|
||||
[ ?x-axis [ default-calibrate-axis 0.0 ] (default) ]
|
||||
[ ?y-axis [ default-calibrate-axis 0.0 ] (default) ]
|
||||
[ ?z-axis [ default-calibrate-axis 0.0 ] (default) ]
|
||||
[ ?rx-axis [ default-calibrate-axis 0.0 ] (default) ]
|
||||
[ ?ry-axis [ default-calibrate-axis 0.0 ] (default) ]
|
||||
[ ?rz-axis [ default-calibrate-axis 0.0 ] (default) ]
|
||||
[ ?slider [ default-calibrate-slider 0.0 ] (default) ]
|
||||
[ ?hat-switch pov-neutral and ]
|
||||
[ button-count f <array> ]
|
||||
} cleave controller-state boa ;
|
||||
|
||||
: device-matched-callback ( -- alien )
|
||||
[| context result sender device |
|
||||
device controller-device? [
|
||||
device <device-controller-state>
|
||||
device +controller-states+ get set-at
|
||||
] when
|
||||
] IOHIDDeviceCallback ;
|
||||
|
||||
: device-removed-callback ( -- alien )
|
||||
[| context result sender device |
|
||||
device +controller-states+ get delete-at
|
||||
] IOHIDDeviceCallback ;
|
||||
|
||||
: device-input-callback ( -- alien )
|
||||
[| context result sender value |
|
||||
sender controller-device?
|
||||
[ sender +controller-states+ get at value record-controller ]
|
||||
[ value record-keyboard ]
|
||||
if
|
||||
] IOHIDValueCallback ;
|
||||
|
||||
: initialize-variables ( manager -- )
|
||||
+hid-manager+ set-global
|
||||
4 <hashtable> +controller-states+ set-global
|
||||
256 f <array> +keyboard-state+ set-global ;
|
||||
|
||||
M: iokit-game-input-backend open-game-input
|
||||
hid-manager-matching-game-devices {
|
||||
[ initialize-variables ]
|
||||
[ device-matched-callback f IOHIDManagerRegisterDeviceMatchingCallback ]
|
||||
[ device-removed-callback f IOHIDManagerRegisterDeviceRemovalCallback ]
|
||||
[ device-input-callback f IOHIDManagerRegisterInputValueCallback ]
|
||||
[ 0 IOHIDManagerOpen mach-error ]
|
||||
[
|
||||
CFRunLoopGetMain CFRunLoopDefaultMode
|
||||
IOHIDManagerScheduleWithRunLoop
|
||||
]
|
||||
} cleave ;
|
||||
|
||||
! XXX while game-input is open, we need to reset-game-input and open-game-input as a
|
||||
! boot image hook
|
||||
M: iokit-game-input-backend close-game-input
|
||||
+hid-manager+ global [
|
||||
[ 0 IOHIDManagerClose drop ]
|
||||
[ CFRelease ] bi
|
||||
f
|
||||
] change-at
|
||||
f +keyboard-state+ set-global
|
||||
f +controller-states+ set-global ;
|
||||
|
||||
M: iokit-game-input-backend get-controllers ( -- sequence )
|
||||
+controller-states+ get keys [ controller boa ] map ;
|
||||
|
||||
M: iokit-game-input-backend manufacturer ( controller -- string )
|
||||
handle>> kIOHIDManufacturerKey device-property ;
|
||||
M: iokit-game-input-backend product ( controller -- string )
|
||||
handle>> kIOHIDProductKey device-property ;
|
||||
M: iokit-game-input-backend vendor-id ( controller -- integer )
|
||||
handle>> kIOHIDVendorIDKey device-property ;
|
||||
M: iokit-game-input-backend product-id ( controller -- integer )
|
||||
handle>> kIOHIDProductIDKey device-property ;
|
||||
M: iokit-game-input-backend location-id ( controller -- integer )
|
||||
handle>> kIOHIDLocationIDKey device-property ;
|
||||
|
||||
M: iokit-game-input-backend read-controller ( controller -- controller-state )
|
||||
handle>> +controller-states+ get at clone ;
|
||||
|
||||
M: iokit-game-input-backend read-keyboard ( -- keyboard-state )
|
||||
+keyboard-state+ get clone keyboard-state boa ;
|
||||
|
||||
M: iokit-game-input-backend calibrate-controller ( controller -- )
|
||||
! XXX
|
||||
drop ;
|
||||
|
||||
iokit-game-input-backend game-input-backend set-global
|
|
@ -0,0 +1,39 @@
|
|||
USING: arrays accessors continuations kernel symbols ;
|
||||
IN: game-input
|
||||
|
||||
SYMBOL: game-input-backend
|
||||
|
||||
HOOK: open-game-input game-input-backend ( -- )
|
||||
HOOK: close-game-input game-input-backend ( -- )
|
||||
|
||||
: with-game-input ( quot -- )
|
||||
open-game-input [ close-game-input ] [ ] cleanup ;
|
||||
|
||||
TUPLE: controller handle ;
|
||||
TUPLE: controller-state x y z rx ry rz slider pov buttons ;
|
||||
|
||||
M: controller-state clone
|
||||
call-next-method dup buttons>> clone >>buttons ;
|
||||
|
||||
SYMBOLS:
|
||||
pov-neutral
|
||||
pov-up pov-up-left pov-left pov-down-left
|
||||
pov-down pov-down-right pov-right pov-up-right ;
|
||||
|
||||
HOOK: get-controllers game-input-backend ( -- sequence )
|
||||
|
||||
HOOK: manufacturer game-input-backend ( controller -- string )
|
||||
HOOK: product game-input-backend ( controller -- string )
|
||||
HOOK: vendor-id game-input-backend ( controller -- integer )
|
||||
HOOK: product-id game-input-backend ( controller -- integer )
|
||||
HOOK: location-id game-input-backend ( controller -- integer )
|
||||
|
||||
HOOK: read-controller game-input-backend ( controller -- controller-state )
|
||||
HOOK: calibrate-controller game-input-backend ( controller -- )
|
||||
|
||||
TUPLE: keyboard-state keys ;
|
||||
|
||||
M: keyboard-state clone
|
||||
call-next-method dup keys>> clone >>keys ;
|
||||
|
||||
HOOK: read-keyboard game-input-backend ( -- keyboard-state )
|
|
@ -20,8 +20,8 @@ IN: iokit.hid
|
|||
: kIOHIDPrimaryUsageKey "PrimaryUsage" ; inline
|
||||
: kIOHIDPrimaryUsagePageKey "PrimaryUsagePage" ; inline
|
||||
: kIOHIDMaxInputReportSizeKey "MaxInputReportSize" ; inline
|
||||
: kIOHIDMaxOutputReportSizeKey "MaxOutputReportSize" ; inline
|
||||
: kIOHIDMaxFeatureReportSizeKey "MaxFeatureReportSize" ; inline
|
||||
: kIOHIDMaxOutputReportSizeKey "MaxOutputReportSize" ; inline
|
||||
: kIOHIDMaxFeatureReportSizeKey "MaxFeatureReportSize" ; inline
|
||||
: kIOHIDReportIntervalKey "ReportInterval" ; inline
|
||||
|
||||
: kIOHIDElementKey "Elements" ; inline
|
||||
|
@ -77,7 +77,7 @@ IN: iokit.hid
|
|||
: kIOHIDElementTypeFeature 257 ; inline
|
||||
: kIOHIDElementTypeCollection 513 ; inline
|
||||
|
||||
: kIOHIDElementCollectionTypePhysical HEX: 00 ; inline
|
||||
: kIOHIDElementCollectionTypePhysical HEX: 00 ; inline
|
||||
: kIOHIDElementCollectionTypeApplication HEX: 01 ; inline
|
||||
: kIOHIDElementCollectionTypeLogical HEX: 02 ; inline
|
||||
: kIOHIDElementCollectionTypeReport HEX: 03 ; inline
|
||||
|
@ -90,10 +90,10 @@ IN: iokit.hid
|
|||
: kIOHIDReportTypeFeature 2 ; inline
|
||||
: kIOHIDReportTypeCount 3 ; inline
|
||||
|
||||
: kIOHIDOptionsTypeNone HEX: 00 ; inline
|
||||
: kIOHIDOptionsTypeNone HEX: 00 ; inline
|
||||
: kIOHIDOptionsTypeSeizeDevice HEX: 01 ; inline
|
||||
|
||||
: kIOHIDQueueOptionsTypeNone HEX: 00 ; inline
|
||||
: kIOHIDQueueOptionsTypeNone HEX: 00 ; inline
|
||||
: kIOHIDQueueOptionsTypeEnqueueAll HEX: 01 ; inline
|
||||
|
||||
: kIOHIDElementFlagsConstantMask HEX: 0001 ; inline
|
||||
|
@ -269,3 +269,4 @@ FUNCTION: IOHIDValueRef IOHIDTransactionGetValue ( IOHIDTransactionRef transacti
|
|||
FUNCTION: IOReturn IOHIDTransactionCommit ( IOHIDTransactionRef transaction ) ;
|
||||
FUNCTION: IOReturn IOHIDTransactionCommitWithCallback ( IOHIDTransactionRef transaction, CFTimeInterval timeout, IOHIDCallback callback, void* context ) ;
|
||||
FUNCTION: void IOHIDTransactionClear ( IOHIDTransactionRef transaction ) ;
|
||||
|
||||
|
|
Loading…
Reference in New Issue