@@ -8,8 +8,15 @@ extension MotionSDK {
88 /// Skan BLE + auto-connect do jedynego urządzenia z „triki” w nazwie.
99 public func connect( ) {
1010 ensureBLEPipeline ( )
11- bleManager? . autoConnectWhenSingleLikelyMatch = true
12- bleManager? . startScan ( clearList: true )
11+ trikiController? . ble. autoConnectWhenSingleLikelyMatch = true
12+ trikiController? . connect ( )
13+ }
14+
15+ /// Ponowne połączenie z ostatnim zapamiętanym urządzeniem (bez pełnego skanu).
16+ public func connectLastDevice( ) {
17+ ensureBLEPipeline ( )
18+ trikiController? . ble. autoConnectWhenSingleLikelyMatch = false
19+ trikiController? . ble. connectCachedPeripheralIfAvailable ( )
1320 }
1421
1522 /// Zamyka połączenie BLE i czyści stan sesji.
@@ -35,21 +42,23 @@ extension MotionSDK {
3542 }
3643
3744 let now = Date ( ) . timeIntervalSince1970
38- if now - lastPacketAt > 0.35 , isReceiving { isReceiving = false }
45+ let stale = trikiBLEMode. packetStaleSeconds
46+ if now - lastPacketAt > stale, isReceiving { isReceiving = false }
47+ syncTrikiPublishedState ( )
3948
4049 if config. mode == . paddle {
4150 parser. refreshTiltSensors ( )
4251 parser. flushImpulsesOnly ( )
4352 let impulses = parser. consumeImpulses ( )
4453 let out = updateFrame ( deltaTime: deltaTime)
45- var enriched = input
46- enriched . tiltY = parser . sensors . tiltY
47- enriched . tiltX = parser . sensors . tiltX
48- enriched . lateral = out . x
49- enriched . lateralSmooth = out . x
50- enriched . shake = impulses . shake || ( trikiController ? . gameInput . isShake ?? false )
51- enriched. sensors = parser . sensors
52- applyClickToSensors ( & enriched)
54+ var enriched = makeEnrichedGameInput (
55+ output : out ,
56+ sdkInput : input ,
57+ parser : parser ,
58+ impulses : impulses
59+ )
60+ applyTrikiGamepadSignals ( & enriched)
61+ finalizeAdaptiveInput ( & enriched)
5362 latestEnrichedInput = enriched
5463 publishLiveInputIfNeeded ( now: now, input: enriched)
5564 return enriched
@@ -63,14 +72,17 @@ extension MotionSDK {
6372 )
6473 let out = updateFrame ( deltaTime: deltaTime)
6574 let impulses = parser. consumeImpulses ( )
66- latestEnrichedInput = makeEnrichedGameInput (
75+ var enriched = makeEnrichedGameInput (
6776 output: out,
6877 sdkInput: input,
6978 parser: parser,
7079 impulses: impulses
7180 )
72- publishLiveInputIfNeeded ( now: now, input: latestEnrichedInput)
73- return latestEnrichedInput
81+ applyTrikiGamepadSignals ( & enriched)
82+ finalizeAdaptiveInput ( & enriched)
83+ latestEnrichedInput = enriched
84+ publishLiveInputIfNeeded ( now: now, input: enriched)
85+ return enriched
7486 }
7587
7688 /// Pobiera ostatnią wzbogaconą ramkę wejścia bez aktualizacji stanu.
@@ -125,6 +137,17 @@ extension MotionSDK {
125137 /// Czyści bufor logów BLE.
126138 public func clearBLEDevLog( ) { bleManager? . devRawLog. removeAll ( ) }
127139
140+ /// Czy zapisano UUID ostatniego urządzenia (szybkie ponowne połączenie).
141+ public var hasCachedBLEDevice : Bool {
142+ bleManager? . cachedPeripheralUUID != nil
143+ }
144+
145+ /// Log monitora trybu BLE (Δt między pakietami).
146+ public var debugBLEMonitorLogging : Bool {
147+ get { trikiController? . debugBLEMonitorLogging ?? false }
148+ set { trikiController? . debugBLEMonitorLogging = newValue }
149+ }
150+
128151 // MARK: - Private
129152
130153 /// Handles `ensureBLEPipeline`.
@@ -145,7 +168,6 @@ extension MotionSDK {
145168 self . enqueueBLE ( bytes)
146169 self . streamParser? . enqueue ( data: bytes)
147170 self . lastPacketAt = Date ( ) . timeIntervalSince1970
148- if !self . isReceiving { self . isReceiving = true }
149171 }
150172 . store ( in: & bleCancellables)
151173
@@ -156,6 +178,32 @@ extension MotionSDK {
156178 if !connected { self ? . resetConnectionState ( ) }
157179 }
158180 . store ( in: & bleCancellables)
181+
182+ triki. $bleMode
183+ . removeDuplicates ( )
184+ . sink { [ weak self] mode in
185+ self ? . trikiBLEMode = mode
186+ }
187+ . store ( in: & bleCancellables)
188+
189+ triki. $idleStatusMessage
190+ . sink { [ weak self] message in
191+ self ? . trikiIdleStatusMessage = message
192+ }
193+ . store ( in: & bleCancellables)
194+
195+ triki. $isReceiving
196+ . removeDuplicates ( )
197+ . sink { [ weak self] receiving in
198+ self ? . isReceiving = receiving
199+ }
200+ . store ( in: & bleCancellables)
201+ }
202+
203+ func syncTrikiPublishedState( ) {
204+ guard let triki = trikiController else { return }
205+ trikiBLEMode = triki. getBLEMode ( )
206+ trikiIdleStatusMessage = triki. idleStatusMessage
159207 }
160208
161209 /// Handles `resetConnectionState`.
@@ -166,7 +214,11 @@ extension MotionSDK {
166214 liveInput = GameInput ( )
167215 latestEnrichedInput = GameInput ( )
168216 isReceiving = false
217+ trikiBLEMode = . unknown
218+ trikiIdleStatusMessage = nil
169219 lastHudPublishAt = 0
220+ lastFramePosX = nil
221+ lastFramePosY = nil
170222 }
171223
172224 /// Mapuje wyjście gamepada na silnik pozycji (bez surowych osi w API gry).
@@ -184,13 +236,16 @@ extension MotionSDK {
184236 /// Handles `refreshLiveInputFromEngine`.
185237 func refreshLiveInputFromEngine( ) {
186238 let out = output
187- latestEnrichedInput = makeEnrichedGameInput (
239+ var enriched = makeEnrichedGameInput (
188240 output: out,
189241 sdkInput: input,
190242 parser: streamParser,
191243 impulses: ( false , false )
192244 )
193- liveInput = latestEnrichedInput
245+ applyTrikiGamepadSignals ( & enriched)
246+ finalizeAdaptiveInput ( & enriched)
247+ latestEnrichedInput = enriched
248+ liveInput = enriched
194249 lastHudPublishAt = Date ( ) . timeIntervalSince1970
195250 }
196251
@@ -205,6 +260,33 @@ extension MotionSDK {
205260 liveInput = input
206261 }
207262
263+ /// Applies Triki gamepad velocity/tilt edges to `GameInput` (all tryby gier).
264+ func applyTrikiGamepadSignals( _ input: inout GameInput ) {
265+ guard let pad = trikiController? . gameInput else { return }
266+ input. tiltLeft = pad. isTiltLeft
267+ input. tiltRight = pad. isTiltRight
268+ let vel = Double ( pad. velocity)
269+ input. trikiVelocity = vel
270+ input. isMoving = pad. isMoving
271+ input. intensity = max ( input. intensity, vel)
272+ input. flick = input. flick || pad. isSwing
273+ let dir = Double ( pad. direction)
274+ if dir != 0 , vel > 0.5 {
275+ input. deltaX = dir * vel * 0.012
276+ }
277+ }
278+
279+ /// Uzupełnia `bleMode`, Δpos i strategię adaptacyjną dla gier.
280+ func finalizeAdaptiveInput( _ input: inout GameInput ) {
281+ input. bleMode = trikiBLEMode
282+ let prevX = lastFramePosX ?? input. posX
283+ let prevY = lastFramePosY ?? input. posY
284+ input. frameDeltaX = input. posX - prevX
285+ input. frameDeltaY = input. posY - prevY
286+ lastFramePosX = input. posX
287+ lastFramePosY = input. posY
288+ }
289+
208290 /// Builds a UI/game-friendly input snapshot from raw engine output and parser state.
209291 ///
210292 /// - Parameters:
@@ -239,16 +321,19 @@ extension MotionSDK {
239321 enriched. sensors = parser. sensors
240322 enriched. pointerDirection = pointerDirection ( posX: output. x, posY: output. y)
241323 }
242- applyClickToSensors ( & enriched)
324+ let buttonEdge = impulses. click || sdkInput. primaryAction
325+ if config. mode == . paddle {
326+ enriched. primaryAction = buttonEdge
327+ } else if impulses. click {
328+ enriched. primaryAction = true
329+ }
330+ applyClickToSensors ( & enriched, clickEdge: buttonEdge)
243331 return enriched
244332 }
245333
246- /// Handles `applyClickToSensors`.
247- ///
248- /// - Parameters:
249- /// - input: Input used by this operation.
250- func applyClickToSensors( _ input: inout GameInput ) {
251- guard input. primaryAction else { return }
334+ /// Sets one-shot click flag on sensors when a BLE button edge was detected.
335+ func applyClickToSensors( _ input: inout GameInput , clickEdge: Bool ) {
336+ guard clickEdge else { return }
252337 var sensors = input. sensors
253338 sensors. click = true
254339 input. sensors = sensors
0 commit comments