@@ -29,7 +29,7 @@ public class SeatBeltTensioner
2929 private float _vertAccelSum = 0f ;
3030 private float _pitchSum = 0f ;
3131 private float _rollSum = 0f ;
32- private int _accelSampleCount = 0 ;
32+ private int _sampleCount = 0 ;
3333
3434 public SeatBeltTensioner ( )
3535 {
@@ -184,17 +184,17 @@ private void Update( App app )
184184 {
185185 var settings = DataContext . DataContext . Instance . Settings ;
186186
187- if ( _accelSampleCount == 0 )
187+ if ( ! IsConnected || ! settings . SeatBeltTensionerEnabled || _sampleCount == 0 )
188188 {
189189 return ;
190190 }
191191
192- var longAccelAvg = _longAccelSum / _accelSampleCount ;
193- var latAccelAvg = _latAccelSum / _accelSampleCount ;
194- var vertAccelAvg = _vertAccelSum / _accelSampleCount ;
192+ var longAccelAvg = _longAccelSum / _sampleCount ;
193+ var latAccelAvg = _latAccelSum / _sampleCount ;
194+ var vertAccelAvg = _vertAccelSum / _sampleCount ;
195195
196- var pitch = _pitchSum / _accelSampleCount ;
197- var roll = _rollSum / _accelSampleCount ;
196+ var pitch = _pitchSum / _sampleCount ;
197+ var roll = _rollSum / _sampleCount ;
198198
199199 _longAccelSum = 0f ;
200200 _latAccelSum = 0f ;
@@ -203,12 +203,7 @@ private void Update( App app )
203203 _pitchSum = 0f ;
204204 _rollSum = 0f ;
205205
206- _accelSampleCount = 0 ;
207-
208- if ( ! settings . SeatBeltTensionerEnabled || ! IsConnected )
209- {
210- return ;
211- }
206+ _sampleCount = 0 ;
212207
213208 // Get and sanitize settings
214209 var minimumTenths = Math . Clamp ( ( int ) Math . Round ( settings . SeatBeltTensionerMinimum * 10f ) , 0 , 900 ) ;
@@ -231,29 +226,15 @@ private void Update( App app )
231226 var sinRoll = MathF . Sin ( roll ) ;
232227
233228 // Gravity component along each body axis (what iRacing adds to raw acceleration)
229+ var gravLong = MathZ . OneG * - sinPitch ;
230+ var gravLat = MathZ . OneG * cosPitch * sinRoll ;
234231 var gravVert = MathZ . OneG * cosPitch * cosRoll ;
235232
236- float longAccel ;
237- float latAccel ;
238- float vertAccel ;
233+ var longAccel = settings . SeatBeltTensionerSurgeSubtractGravity ? longAccelAvg - gravLong : longAccelAvg ;
234+ var latAccel = settings . SeatBeltTensionerSwaySubtractGravity ? latAccelAvg - gravLat : latAccelAvg ;
235+ var vertAccel = settings . SeatBeltTensionerHeaveSubtractGravity ? vertAccelAvg - gravVert : vertAccelAvg ;
239236
240- if ( settings . SeatBeltTensionerSubtractFullGravity )
241- {
242- var gravLong = MathZ . OneG * - sinPitch ;
243- var gravLat = MathZ . OneG * cosPitch * sinRoll ;
244-
245- longAccel = longAccelAvg - gravLong ;
246- latAccel = latAccelAvg - gravLat ;
247- vertAccel = vertAccelAvg - gravVert ;
248- }
249- else
250- {
251- longAccel = longAccelAvg ;
252- latAccel = latAccelAvg ;
253- vertAccel = vertAccelAvg - gravVert ;
254- }
255-
256- // Surge normalized [-1..1]:
237+ // Surge normalized [-1..1]: braking tightens both belts, acceleration loosens both belts
257238 var surgeNormalized = Math . Clamp ( - longAccel / MathZ . OneG / settings . SeatBeltTensionerSurgeMaxG , - 1f , 1f ) ;
258239
259240 // Sway normalized [-1..1]: positive biases right belt tighter, left belt looser
@@ -262,6 +243,12 @@ private void Update( App app )
262243 // Heave normalized [-1..1]: bumps and crests both tighten both belts
263244 var heaveNormalized = Math . Clamp ( - vertAccel / MathZ . OneG / settings . SeatBeltTensionerHeaveMaxG , - 1f , 1f ) ;
264245
246+ // Apply inversion settings
247+ if ( settings . SeatBeltTensionerSurgeInvert ) surgeNormalized = - surgeNormalized ;
248+ if ( settings . SeatBeltTensionerSwayInvert ) swayNormalized = - swayNormalized ;
249+ if ( settings . SeatBeltTensionerHeaveInvert ) heaveNormalized = - heaveNormalized ;
250+
251+ // Update graphs if on the SBT page
265252 if ( MairaAppMenuPopup . CurrentAppPage == MainWindow . AppPage . SeatBeltTensioner )
266253 {
267254 _surgeGraph . Advance ( surgeNormalized ) ;
@@ -273,28 +260,42 @@ private void Update( App app )
273260 _heaveGraph . WritePixels ( ) ;
274261 }
275262
276- // Combine into per-arm normalized signal and offset by neutral position
277- var leftCombinedNormalized = surgeNormalized + heaveNormalized - swayNormalized + neutralPositionNormalized ;
278- var rightCombinedNormalized = surgeNormalized + heaveNormalized + swayNormalized + neutralPositionNormalized ;
263+ // Combine into per-arm normalized signal
264+ var leftCombinedNormalized = surgeNormalized + heaveNormalized - swayNormalized ;
265+ var rightCombinedNormalized = surgeNormalized + heaveNormalized + swayNormalized ;
279266
280267 // Apply soft limiter
281268 var limitedLeftNormalized = MathZ . SoftLimiter ( leftCombinedNormalized ) ;
282269 var limitedRightNormalized = MathZ . SoftLimiter ( rightCombinedNormalized ) ;
283270
284271 // Map to tenths of degrees and clamp to minimum / maximum
285- var leftTargetPositionTenths = Math . Clamp ( ( int ) MathF . Round ( limitedLeftNormalized * rangeTenths + 900 ) , minimumTenths , maximumTenths ) ;
286- var rightTargetPositionTenths = Math . Clamp ( ( int ) MathF . Round ( limitedRightNormalized * rangeTenths + 900 ) , minimumTenths , maximumTenths ) ;
272+ int leftTargetPositionTenths ;
273+ int rightTargetPositionTenths ;
287274
275+ if ( limitedLeftNormalized >= 0f )
276+ {
277+ leftTargetPositionTenths = Math . Clamp ( ( int ) MathF . Round ( limitedLeftNormalized * ( maximumTenths - neutralTenths ) + neutralTenths ) , minimumTenths , maximumTenths ) ;
278+ }
279+ else
280+ {
281+ leftTargetPositionTenths = Math . Clamp ( ( int ) MathF . Round ( limitedLeftNormalized * ( neutralTenths - minimumTenths ) + neutralTenths ) , minimumTenths , maximumTenths ) ;
282+ }
283+
284+ if ( rightCombinedNormalized >= 0f )
285+ {
286+ rightTargetPositionTenths = Math . Clamp ( ( int ) MathF . Round ( limitedRightNormalized * ( maximumTenths - neutralTenths ) + neutralTenths ) , minimumTenths , maximumTenths ) ;
287+ }
288+ else
289+ {
290+ rightTargetPositionTenths = Math . Clamp ( ( int ) MathF . Round ( limitedRightNormalized * ( neutralTenths - minimumTenths ) + neutralTenths ) , minimumTenths , maximumTenths ) ;
291+ }
292+
293+ // Update shoulder graphs if on the SBT page
288294 if ( MairaAppMenuPopup . CurrentAppPage == MainWindow . AppPage . SeatBeltTensioner )
289295 {
290296 // Remap tenths to [-1..1]: -1=minimum, 0=neutral, +1=maximum (piecewise linear)
291- var leftShoulderNormalized = leftTargetPositionTenths <= neutralTenths
292- ? ( float ) ( leftTargetPositionTenths - neutralTenths ) / ( neutralTenths - minimumTenths )
293- : ( float ) ( leftTargetPositionTenths - neutralTenths ) / ( maximumTenths - neutralTenths ) ;
294-
295- var rightShoulderNormalized = rightTargetPositionTenths <= neutralTenths
296- ? ( float ) ( rightTargetPositionTenths - neutralTenths ) / ( neutralTenths - minimumTenths )
297- : ( float ) ( rightTargetPositionTenths - neutralTenths ) / ( maximumTenths - neutralTenths ) ;
297+ var leftShoulderNormalized = leftTargetPositionTenths <= neutralTenths ? ( float ) ( leftTargetPositionTenths - neutralTenths ) / ( neutralTenths - minimumTenths ) : ( float ) ( leftTargetPositionTenths - neutralTenths ) / ( maximumTenths - neutralTenths ) ;
298+ var rightShoulderNormalized = rightTargetPositionTenths <= neutralTenths ? ( float ) ( rightTargetPositionTenths - neutralTenths ) / ( neutralTenths - minimumTenths ) : ( float ) ( rightTargetPositionTenths - neutralTenths ) / ( maximumTenths - neutralTenths ) ;
298299
299300 _leftShoulderGraph . Advance ( leftShoulderNormalized ) ;
300301 _rightShoulderGraph . Advance ( rightShoulderNormalized ) ;
@@ -314,7 +315,7 @@ private void OnPortClosed( object? sender, EventArgs e )
314315
315316 public void Tick ( App app )
316317 {
317- if ( app . Simulator . IsOnTrack )
318+ if ( app . Simulator . IsOnTrack || app . Simulator . IsReplayPlaying )
318319 {
319320 _longAccelSum += app . Simulator . LongAccel ;
320321 _latAccelSum += app . Simulator . LatAccel ;
@@ -323,7 +324,7 @@ public void Tick( App app )
323324 _pitchSum += app . Simulator . Pitch ;
324325 _rollSum += app . Simulator . Roll ;
325326
326- _accelSampleCount ++ ;
327+ _sampleCount ++ ;
327328 }
328329
329330 _updateCounter -- ;
0 commit comments