1+ //
2+ // GameController.swift
3+ // SwiftAndroid
4+ //
5+ // Created by Alsey Coleman Miller on 2/27/26.
6+ //
7+
8+ #if AGDK
9+ #if os(Android)
10+ import Android
11+ import AndroidNDK
12+ #endif
13+
14+ /// Swift wrapper for the Android Game Controller (Paddleboat) C API.
15+ @MainActor
16+ public struct GameController : ~ Copyable {
17+
18+ let environment : JNIEnvironment
19+
20+ public init ( context: jobject , environment: JNIEnvironment ) throws {
21+ let result = Paddleboat_init ( environment, context)
22+ guard result == 0 else {
23+ throw GameController . Error ( rawValue: result) ?? GameController . Error. notInitialized
24+ }
25+ guard Paddleboat_isInitialized ( ) else {
26+ throw GameController . Error. notInitialized
27+ }
28+ self . environment = environment
29+ }
30+
31+ deinit {
32+ Paddleboat_destroy ( environment)
33+ }
34+
35+ public func update( ) {
36+ Paddleboat_update ( environment)
37+ }
38+
39+ // MARK: - Back button
40+ public static func setBackButtonConsumed( _ consume: Bool ) {
41+ Paddleboat_setBackButtonConsumed ( consume)
42+ }
43+
44+ public static func isBackButtonConsumed( ) -> Bool {
45+ Paddleboat_getBackButtonConsumed ( )
46+ }
47+
48+ // MARK: - Controller Info / Data
49+ public static func getControllerStatus( index: Int32 ) -> ControllerStatus {
50+ ControllerStatus ( rawValue: Paddleboat_getControllerStatus ( index) ) ?? . inactive
51+ }
52+
53+ public static func getControllerName( index: Int32 , bufferSize: Int = 128 ) -> ( ErrorCode , String ) {
54+ var buffer = [ CChar] ( repeating: 0 , count: bufferSize)
55+ let err = Paddleboat_getControllerName ( index, Int32 ( buffer. count) , & buffer)
56+ let code = ErrorCode ( rawValue: err) ?? . noError
57+ let name = buffer. withUnsafeBufferPointer { String ( cString: $0. baseAddress!) }
58+ return ( code, name)
59+ }
60+
61+ // MARK: - Lights / Vibration
62+ @discardableResult
63+ public func setControllerLight( index: Int32 , type: LightType , data: UInt32 ) -> ErrorCode {
64+ let err = Paddleboat_setControllerLight ( index, type. rawValue, data, environment)
65+ return ErrorCode ( rawValue: err) ?? . noError
66+ }
67+
68+ @discardableResult
69+ public func setControllerVibration( index: Int32 , vibration: VibrationData ) -> ErrorCode {
70+ var cData = Paddleboat_Vibration_Data ( duration_ms: vibration. durationMs,
71+ left_motor_intensity: vibration. intensityLeft,
72+ right_motor_intensity: vibration. intensityRight)
73+ let err = Paddleboat_setControllerVibrationData ( index, & cData, environment)
74+ return ErrorCode ( rawValue: err) ?? . noError
75+ }
76+
77+ // MARK: - Motion
78+ public static func getIntegratedMotionSensorFlags( ) -> IntegratedMotionSensorFlags {
79+ IntegratedMotionSensorFlags ( rawValue: Paddleboat_getIntegratedMotionSensorFlags ( ) )
80+ }
81+ }
82+
83+ // MARK: - Supporting Types
84+
85+ public extension GameController {
86+
87+ // MARK: - Version / Constants
88+ public static var maxControllers : Int32 { 8 }
89+
90+ // MARK: - Error
91+ public enum Error : Int32 , Swift . Error {
92+ case noError = 0
93+ case alreadyInitialized = - 2000
94+ case notInitialized = - 2001
95+ case invalidParameter = - 2002
96+ case invalidControllerIndex = - 2003
97+ case noController = - 2004
98+ case featureNotSupported = - 2005
99+ case fileIO = - 2006
100+ case incompatibleMappingData = - 2007
101+ case invalidMappingData = - 2008
102+ case noMouse = - 2009
103+ case initGCMFailure = - 2010
104+ }
105+
106+ typealias ErrorCode = Error
107+
108+ public enum ControllerStatus : Int32 {
109+ case inactive = 0
110+ case active = 1
111+ case justConnected = 2
112+ case justDisconnected = 3
113+ }
114+
115+ public struct Buttons : OptionSet , Sendable {
116+ public let rawValue : UInt32
117+ public init ( rawValue: UInt32 ) { self . rawValue = rawValue }
118+ public static let a = Buttons ( rawValue: 1 << 0 )
119+ public static let b = Buttons ( rawValue: 1 << 1 )
120+ public static let x = Buttons ( rawValue: 1 << 2 )
121+ public static let y = Buttons ( rawValue: 1 << 3 )
122+ public static let l1 = Buttons ( rawValue: 1 << 4 )
123+ public static let r1 = Buttons ( rawValue: 1 << 5 )
124+ public static let l2 = Buttons ( rawValue: 1 << 6 )
125+ public static let r2 = Buttons ( rawValue: 1 << 7 )
126+ public static let l3 = Buttons ( rawValue: 1 << 8 )
127+ public static let r3 = Buttons ( rawValue: 1 << 9 )
128+ public static let dpadUp = Buttons ( rawValue: 1 << 10 )
129+ public static let dpadDown = Buttons ( rawValue: 1 << 11 )
130+ public static let dpadLeft = Buttons ( rawValue: 1 << 12 )
131+ public static let dpadRight = Buttons ( rawValue: 1 << 13 )
132+ public static let start = Buttons ( rawValue: 1 << 14 )
133+ public static let select = Buttons ( rawValue: 1 << 15 )
134+ public static let system = Buttons ( rawValue: 1 << 16 )
135+ public static let touchpad = Buttons ( rawValue: 1 << 17 )
136+ public static let aux1 = Buttons ( rawValue: 1 << 18 )
137+ public static let aux2 = Buttons ( rawValue: 1 << 19 )
138+ public static let aux3 = Buttons ( rawValue: 1 << 20 )
139+ public static let aux4 = Buttons ( rawValue: 1 << 21 )
140+ }
141+
142+ public enum LightType : Int32 {
143+ case playerNumber = 0
144+ case rgb = 1
145+ }
146+
147+ public struct IntegratedMotionSensorFlags : OptionSet , Sendable {
148+ public let rawValue : UInt32
149+ public init ( rawValue: UInt32 ) { self . rawValue = rawValue }
150+ public static let none = IntegratedMotionSensorFlags ( [ ] )
151+ public static let accelerometer = IntegratedMotionSensorFlags ( rawValue: 0x00000001 )
152+ public static let gyroscope = IntegratedMotionSensorFlags ( rawValue: 0x00000002 )
153+ public static let indexFlag = IntegratedMotionSensorFlags ( rawValue: 0x40000000 )
154+ }
155+
156+ public struct VibrationData {
157+ public var durationMs : Int32
158+ public var intensityLeft : Float
159+ public var intensityRight : Float
160+ public init ( durationMs: Int32 , intensityLeft: Float , intensityRight: Float ) {
161+ self . durationMs = durationMs
162+ self . intensityLeft = intensityLeft
163+ self . intensityRight = intensityRight
164+ }
165+ }
166+ }
167+ #endif
0 commit comments