@babylonjs-toolkit/next 9.1.0 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,7 +40,7 @@ import { Skeleton } from '@babylonjs/core/Bones/skeleton';
40
40
  import { Control } from '@babylonjs/gui/2D/controls/control';
41
41
  import { TextBlock } from '@babylonjs/gui/2D/controls/textBlock';
42
42
  import { Image } from '@babylonjs/gui/2D/controls/image';
43
- import { PhysicsBody, PhysicsShape, PhysicsShapeCapsule, PhysicsRaycastResult, PhysicsMotionType, PhysicsShapeContainer, ShapeCastResult, PhysicsShapeSphere, PhysicsShapeMesh, PhysicsShapeConvexHull, PhysicsShapeBox, PhysicsShapeCylinder, PhysicsMaterialCombineMode, PhysicsShapeType } from '@babylonjs/core/Physics';
43
+ import { PhysicsBody, PhysicsShape, PhysicsShapeCapsule, PhysicsRaycastResult, PhysicsMotionType, PhysicsShapeContainer, ShapeCastResult, PhysicsShapeMesh, PhysicsShapeConvexHull, PhysicsShapeBox, PhysicsShapeSphere, PhysicsShapeCylinder, PhysicsMaterialCombineMode, PhysicsShapeType } from '@babylonjs/core/Physics';
44
44
  import { HavokPlugin } from '@babylonjs/core/Physics/v2/Plugins/havokPlugin';
45
45
  import { GLTFLoader, ArrayItem } from '@babylonjs/loaders/glTF/2.0/glTFLoader';
46
46
  import { Texture } from '@babylonjs/core/Materials/Textures/texture';
@@ -79,7 +79,7 @@ import { UnitySlider } from './unityslider';
79
79
  import { UnityScrollBar } from './unityscrollbar';
80
80
  import { UnityDropdownMenu } from './unitydropdownmenu';
81
81
  export class SceneManager {
82
- static get Version() { return "9.1.0 - R1"; }
82
+ static get Version() { return "9.5.0 - R1"; }
83
83
  static get Copyright() { return "All rights reserved (c) 2024 Mackey Kinard"; }
84
84
  static GetEngine(scene) {
85
85
  let result = null;
@@ -115,16 +115,17 @@ export class SceneManager {
115
115
  }
116
116
  static get PlaygroundCdn() { return "https://cdn.jsdelivr.net/gh/BabylonJS/BabylonToolkit@master/Runtime/"; }
117
117
  static get PlaygroundRepo() { return "https://www.babylontoolkit.com/playground/"; }
118
- static async InitializePlayground(engine, options = null) {
119
- return SceneManager.InitializeRuntime(engine, options);
118
+ static async InitializePlayground(engine, options = null, scene = null, inputOptions = null) {
119
+ return SceneManager.InitializeRuntime(engine, options, scene, inputOptions);
120
120
  }
121
- static async InitializeRuntime(engine, options = null) {
121
+ static async InitializeRuntime(engine, options = null, scene = null, inputOptions = null) {
122
122
  Tools.Log("Babylon.js Toolkit v" + SceneManager.Version);
123
123
  if (AudioSource.IsLegacyEngine())
124
124
  Tools.Log("Legacy audio engine detected");
125
125
  const hardwareScalingLevel = (options != null && options.hardwareScalingLevel != null) ? options.hardwareScalingLevel : WindowManager.GetHardwareScalingLevel();
126
126
  const initSceneFileLoaders = (options != null && options.initSceneFileLoaders != null) ? options.initSceneFileLoaders : true;
127
127
  const loadAsyncRuntimeLibs = (options != null && options.loadAsyncRuntimeLibs != null) ? options.loadAsyncRuntimeLibs : true;
128
+ const enableUserInput = (options != null && options.enableUserInput != null) ? options.enableUserInput : false;
128
129
  const defaultProjectScriptBundle = (SceneManager.PlaygroundCdn + "default.playground.js");
129
130
  const loadProjectScriptBundle = (options != null && options.loadProjectScriptBundle != null) ? options.loadProjectScriptBundle : false;
130
131
  const projectScriptBundleUrl = (options != null && options.projectScriptBundleUrl != null) ? options.projectScriptBundleUrl : defaultProjectScriptBundle;
@@ -135,6 +136,8 @@ export class SceneManager {
135
136
  SceneManager.ShowLoadingScreen(engine, hideLoadingUIWithEngine, defaultLoadingUIMarginTop);
136
137
  if (hardwareScalingLevel != null && hardwareScalingLevel > 0)
137
138
  engine.setHardwareScalingLevel(hardwareScalingLevel);
139
+ if (enableUserInput === true)
140
+ InputController.EnableUserInput(engine, scene, inputOptions);
138
141
  SceneManager.UniversalModuleDefinition = false;
139
142
  try {
140
143
  SceneManager.InitializeSceneLoaderPlugin();
@@ -367,38 +370,6 @@ export class SceneManager {
367
370
  }
368
371
  });
369
372
  }
370
- static NavigateTo(scene, route, options = null, useWindowLocation = false) {
371
- if (useWindowLocation === true) {
372
- if (options?.replace === true) {
373
- window.location.replace(route);
374
- }
375
- else {
376
- window.location.assign(route);
377
- }
378
- return;
379
- }
380
- if (scene.reactNavigationFunction != null) {
381
- const navOptions = { ...options, state: { ...(options?.state || {}), fromApp: true } };
382
- scene.reactNavigationFunction(route, navOptions);
383
- }
384
- else {
385
- console.warn("React navigation hook is not set on the scene.");
386
- }
387
- }
388
- static SetReactNavigationHook(scene, navigateToFunction) {
389
- scene.reactNavigationFunction = navigateToFunction;
390
- }
391
- static DeleteReactNavigationHook(scene) {
392
- if (scene.reactNavigationFunction != null) {
393
- scene.reactNavigationFunction = null;
394
- try {
395
- delete scene.reactNavigationFunction;
396
- }
397
- catch (e) {
398
- console.warn(e);
399
- }
400
- }
401
- }
402
373
  static EnableSceneParsing(enabled) {
403
374
  SceneManager.SceneParsingEnabled = enabled;
404
375
  }
@@ -3211,6 +3182,11 @@ export class ScriptComponent {
3211
3182
  return result;
3212
3183
  }
3213
3184
  }
3185
+ export class GameModeController extends ScriptComponent {
3186
+ constructor(transform, scene, properties = {}, alias = null) {
3187
+ super(transform, scene, properties, alias);
3188
+ }
3189
+ }
3214
3190
  export var System;
3215
3191
  (function (System) {
3216
3192
  System[System["Deg2Rad"] = (Math.PI * 2 / 360)] = "Deg2Rad";
@@ -16071,7 +16047,7 @@ export class WindowManager {
16071
16047
  printer.style.left = "6px";
16072
16048
  printer.style.bottom = "3px";
16073
16049
  printer.style.fontSize = "12px";
16074
- printer.style.zIndex = "10000";
16050
+ printer.style.zIndex = "9001";
16075
16051
  printer.style.color = "#0c0";
16076
16052
  printer.style.pointerEvents = "none";
16077
16053
  document.body.appendChild(printer);
@@ -16846,9 +16822,6 @@ export class AnimationState extends ScriptComponent {
16846
16822
  if (this.onAnimationAwakeObservable && this.onAnimationAwakeObservable.hasObservers()) {
16847
16823
  this.onAnimationAwakeObservable.notifyObservers(this.transform);
16848
16824
  }
16849
- console.warn("Animation State Mahine: " + this.transform.name);
16850
- console.log(this);
16851
- SceneManager.SetWindowState(this.transform.name, this);
16852
16825
  }
16853
16826
  updateStateMachine(deltaTime = null) {
16854
16827
  if (this.delayUpdateUntilReady === false || (this.delayUpdateUntilReady === true && this.isReady())) {
@@ -19798,44 +19771,6 @@ export class btRaycastVehicle {
19798
19771
  this.isArcadeHandBrakeActive = false;
19799
19772
  this.isArcadeWheelSkidActive = false;
19800
19773
  this.isArcadeYawAssistActive = false;
19801
- this.arcadeYawAssistDebugLogEnabled = false;
19802
- this.arcadeYawAssistDebugLogIntervalFrames = 30;
19803
- this.arcadeYawAssistDebugLogEdgeEvents = true;
19804
- this.arcadeHandbrakeKickStrengthDegPerSec = 120.0;
19805
- this.arcadeHandbrakeKickFrames = 6;
19806
- this.arcadeHandbrakeYawAuthority = 1.8;
19807
- this.arcadeHandbrakeMaxYawRateDegPerSec = 180.0;
19808
- this.arcadeHandbrakeReferenceSpeedKmh = 90.0;
19809
- this.arcadeHandbrakeSpeedGateEnabled = true;
19810
- this.arcadeHandbrakeLowSpeedShape = 2.0;
19811
- this.arcadeHandbrakeDirectYawEnabled = true;
19812
- this.arcadeHandbrakeDirectYawDegPerSec = 60.0;
19813
- this.arcadeHandbrakeDirectYawDurationMs = 0;
19814
- this.arcadeHandbrakeDirectYawFadeMs = 200;
19815
- this.arcadeDonutDirectYawEnabled = true;
19816
- this.arcadeDonutDirectYawDegPerSec = 5.0;
19817
- this.arcadeDonutDirectYawDurationMs = 0;
19818
- this.arcadeDonutDirectYawFadeMs = 200;
19819
- this.arcadeHandbrakeMaxSlideAngleDeg = 220.0;
19820
- this.arcadeHandbrakeCounterSteerClampEnabled = true;
19821
- this.arcadeHandbrakeCounterSteerYawThresholdDegPerSec = 10.0;
19822
- this.arcadeHandbrakeClampReleaseFadeMs = 250;
19823
- this.arcadeHandbrakeSteerSlewLimitEnabled = false;
19824
- this.arcadeHandbrakeSteerSlewLimitDegPerSec = 360.0;
19825
- this._wasArcadeHandBrakeActive = false;
19826
- this._wasArcadeYawAssistApplyingForce = false;
19827
- this._handbrakeKickJzRemaining = 0;
19828
- this._handbrakeKickFramesRemaining = 0;
19829
- this._arcadeHandbrakeLatchedDriveSign = 0;
19830
- this._arcadeHandbrakeHoldElapsedSec = 0;
19831
- this._arcadeHandbrakeSlewedSteerRad = 0;
19832
- this._arcadeHandbrakeClampReleaseFadeSec = 999;
19833
- this._arcadeDonutHoldElapsedSec = 0;
19834
- this._arcadeYawAssistDebugFrameCounter = 0;
19835
- this._arcadeYawAssistLastKickRad = 0;
19836
- this._arcadeYawAssistLastIaddPerWheel = 0;
19837
- this._arcadeYawAssistLastClampScalar = 1.0;
19838
- this._arcadeYawAssistLastLeverSum = 0;
19839
19774
  this.burnoutFrictionFloor = 1.0;
19840
19775
  this.frictionRestoreSpeed = 8.0;
19841
19776
  this.arcadeBurnoutWheelSpinGain = 1.0;
@@ -19848,16 +19783,20 @@ export class btRaycastVehicle {
19848
19783
  this.arcadeWheelSpinMaxAngularVelocity = 160.0;
19849
19784
  this.arcadeStationaryBurnoutWheelSpinGain = 3.25;
19850
19785
  this.arcadeStationaryBurnoutMinAngularVelocity = 65.0;
19786
+ this.arcadeHandbrakeYawCapMultiplier = 1.85;
19787
+ this.arcadeBurnoutYawCapMultiplier = 1.25;
19788
+ this.arcadeDonutYawCapMultiplier = 1.15;
19851
19789
  this.arcadeSkidFadeInSpeed = 18.0;
19852
19790
  this.arcadeSkidFadeOutSpeed = 6.0;
19853
- this.arcadeYawCapMultiplier = 1.5;
19854
19791
  this.wheelAtRestSpeedThresholdKmh = 1.0;
19855
- this.wheelSpinDebugLogEnabled = false;
19856
- this.wheelSpinDebugLogIntervalFrames = 6;
19857
- this._wheelSpinDebugLogCounter = 0;
19858
- this._postHandbrakeLogFrames = 0;
19859
- this._postHandbrakeLogCounter = 0;
19860
- this._wasAnyArcadeModeActive = false;
19792
+ this.arcadeHandbrakeAssistEnabled = true;
19793
+ this.currentSteeringInput = 0;
19794
+ this.arcadeDonutDirectYawEnabled = true;
19795
+ this.arcadeDonutDirectYawDegPerSec = 60.0;
19796
+ this.arcadeDonutDirectYawDurationMs = 0;
19797
+ this.arcadeDonutDirectYawFadeMs = 120;
19798
+ this._arcadeDonutHoldElapsedSec = 0;
19799
+ this._arcadeDonutDirectionSign = 0;
19861
19800
  this._forwardWS = [];
19862
19801
  this._axle = [];
19863
19802
  this._forwardImpulse = [];
@@ -19865,6 +19804,11 @@ export class btRaycastVehicle {
19865
19804
  this._arcadeSkidInfo = [];
19866
19805
  this._arcadePreviousWheelSpin = [];
19867
19806
  this.sideFrictionStiffness = 1.0;
19807
+ this.arcadeSideSlipSaturationEnabled = true;
19808
+ this.arcadeSideSlipPeakDeg = 8.0;
19809
+ this.arcadeSideSlipFalloffDeg = 45.0;
19810
+ this.arcadeSideSlipFalloffFactor = 0.4;
19811
+ this.arcadeSideSlipMinSpeedMps = 1.5;
19868
19812
  this._chassisMass = 0;
19869
19813
  this._chassisInvMass = 0;
19870
19814
  this._chassisTransform = Matrix.Identity();
@@ -19989,6 +19933,9 @@ export class btRaycastVehicle {
19989
19933
  return this.isArcadeBurnoutModeActive;
19990
19934
  }
19991
19935
  setIsArcadeDonutActive(active) {
19936
+ if (active !== true) {
19937
+ this._arcadeDonutDirectionSign = 0;
19938
+ }
19992
19939
  this.isArcadeDonutModeActive = active;
19993
19940
  }
19994
19941
  getIsArcadeDonutActive() {
@@ -20609,29 +20556,6 @@ export class btRaycastVehicle {
20609
20556
  const chassisAtRest = (this.wheelAtRestSpeedThresholdKmh > 0
20610
20557
  && Math.abs(this._currentVehicleSpeedKmHour) < this.wheelAtRestSpeedThresholdKmh
20611
20558
  && (!arcadeModeActiveAny || !anyWheelEngineForceActive));
20612
- let wheelSpinLogThisTick = false;
20613
- if (this.wheelSpinDebugLogEnabled === true) {
20614
- this._wheelSpinDebugLogCounter++;
20615
- const intv = (this.wheelSpinDebugLogIntervalFrames > 0)
20616
- ? this.wheelSpinDebugLogIntervalFrames : 1;
20617
- if ((this._wheelSpinDebugLogCounter % intv) === 0) {
20618
- wheelSpinLogThisTick = true;
20619
- }
20620
- }
20621
- let chassisAngVelY = 0;
20622
- if (wheelSpinLogThisTick === true) {
20623
- this._chassisBody.getAngularVelocityToRef(this._sv8);
20624
- chassisAngVelY = this._sv8.y;
20625
- console.log("[HavokVehicle.wheelSpin] tick=" + this._wheelSpinDebugLogCounter
20626
- + " speedKmh=" + this._currentVehicleSpeedKmHour.toFixed(3)
20627
- + " yawRadPerSec=" + chassisAngVelY.toFixed(4)
20628
- + " atRest=" + chassisAtRest
20629
- + " arcadeAny=" + arcadeModeActiveAny
20630
- + " burn=" + this.isArcadeBurnoutModeActive
20631
- + " donut=" + this.isArcadeDonutModeActive
20632
- + " hand=" + this.isArcadeHandBrakeActive
20633
- + " skid=" + this.isArcadeWheelSkidActive);
20634
- }
20635
20559
  for (var i = 0; i < numWheels; i++) {
20636
20560
  var wheel = this._wheelInfo[i];
20637
20561
  var groundAngularVelocity = 0.0;
@@ -20647,29 +20571,12 @@ export class btRaycastVehicle {
20647
20571
  if (chassisAtRest === true) {
20648
20572
  wheel.rotationBoost = 0;
20649
20573
  wheel.deltaRotation = 0;
20650
- if (wheelSpinLogThisTick === true) {
20651
- console.log(" wheel[" + i + "] SUPPRESSED"
20652
- + " contact=" + wheel.raycastInfo.isInContact
20653
- + " groundAngVel=" + groundAngularVelocity.toFixed(4)
20654
- + " rotation=" + wheel.rotation.toFixed(4));
20655
- }
20656
20574
  continue;
20657
20575
  }
20658
20576
  var wheelAngularVelocity = this.getWheelAngularVelocity(i, groundAngularVelocity, step, wheel.raycastInfo.isInContact);
20659
20577
  wheel.deltaRotation = wheelAngularVelocity * step;
20660
20578
  wheel.rotation += wheel.deltaRotation;
20661
20579
  wheel.deltaRotation *= 0.99;
20662
- if (wheelSpinLogThisTick === true) {
20663
- console.log(" wheel[" + i + "]"
20664
- + " contact=" + wheel.raycastInfo.isInContact
20665
- + " groundAngVel=" + groundAngularVelocity.toFixed(4)
20666
- + " rotBoost=" + wheel.rotationBoost.toFixed(4)
20667
- + " wheelAngVel=" + wheelAngularVelocity.toFixed(4)
20668
- + " deltaRot=" + wheel.deltaRotation.toFixed(5)
20669
- + " rotation=" + wheel.rotation.toFixed(4)
20670
- + " engineForce=" + wheel.engineForce.toFixed(2)
20671
- + " brake=" + wheel.brake.toFixed(2));
20672
- }
20673
20580
  }
20674
20581
  this.clampChassisYawRate(step);
20675
20582
  }
@@ -20720,9 +20627,20 @@ export class btRaycastVehicle {
20720
20627
  }
20721
20628
  }
20722
20629
  }
20630
+ getSteeringAuthorityInput() {
20631
+ var steeringInput = Scalar.Clamp(this.currentSteeringInput, -1.0, 1.0);
20632
+ if (Math.abs(steeringInput) > 0.001)
20633
+ return steeringInput;
20634
+ var signedFrontSteer = this.getSignedFrontSteeringAngleRad();
20635
+ return Scalar.Clamp(signedFrontSteer / 0.6, -1.0, 1.0);
20636
+ }
20637
+ getSteeringMagnitude() {
20638
+ return Math.abs(this.getSteeringAuthorityInput());
20639
+ }
20723
20640
  applyEasyDonutYawAssist(timeStep, absSpeedKmh, signedSpeedKmh) {
20724
20641
  if (this.isArcadeDonutModeActive !== true) {
20725
20642
  this._arcadeDonutHoldElapsedSec = 0;
20643
+ this._arcadeDonutDirectionSign = 0;
20726
20644
  return;
20727
20645
  }
20728
20646
  if (this.arcadeDonutDirectYawEnabled !== true) {
@@ -20735,14 +20653,6 @@ export class btRaycastVehicle {
20735
20653
  this._arcadeDonutHoldElapsedSec += timeStep;
20736
20654
  return;
20737
20655
  }
20738
- var L = this.getApproxWheelbaseMeters();
20739
- if (L < 0.5)
20740
- L = 2.5;
20741
- var Iz = 0.22 * this._chassisMass * L * L;
20742
- if (Iz <= 0 || this._chassisMass <= 0) {
20743
- this._arcadeDonutHoldElapsedSec += timeStep;
20744
- return;
20745
- }
20746
20656
  var durSec = this.arcadeDonutDirectYawDurationMs > 0 ? this.arcadeDonutDirectYawDurationMs / 1000.0 : 0;
20747
20657
  var fadeSec = this.arcadeDonutDirectYawFadeMs > 0 ? this.arcadeDonutDirectYawFadeMs / 1000.0 : 0;
20748
20658
  var elapsed = this._arcadeDonutHoldElapsedSec;
@@ -20771,337 +20681,76 @@ export class btRaycastVehicle {
20771
20681
  chassisUp.set(cm[ui * 4], cm[ui * 4 + 1], cm[ui * 4 + 2]);
20772
20682
  this._chassisBody.getLinearVelocityToRef(this._sv8);
20773
20683
  var signedVxMps = Vector3.Dot(this._sv8, chassisForward);
20774
- var driveSign = Math.abs(signedVxMps) > 0.25 ? (signedVxMps >= 0 ? 1 : -1) : 1;
20775
20684
  var steerSign = signedFrontSteerRad >= 0 ? 1 : -1;
20776
- var extraRad = Tools.ToRadians(this.arcadeDonutDirectYawDegPerSec)
20777
- * driveSign * steerSign
20778
- * fade * this.arcadeSteeringAssist;
20779
- var donutYawJz = Iz * extraRad * timeStep;
20780
- if (Math.abs(donutYawJz) <= 1e-6) {
20781
- this._arcadeDonutHoldElapsedSec += timeStep;
20782
- return;
20685
+ if (this._arcadeDonutDirectionSign === 0) {
20686
+ this._arcadeDonutDirectionSign = Math.abs(signedVxMps) > 0.25 ? (signedVxMps >= 0 ? 1 : -1) : steerSign;
20783
20687
  }
20784
- this._chassisBody.getObjectCenterWorldToRef(this._sv1);
20785
- var leverSum = 0;
20786
- var rearIdxList = [];
20787
- var rearLeverList = [];
20788
- for (var w = 0; w < this._wheelInfo.length; w++) {
20789
- var wi = this._wheelInfo[w];
20790
- if (!wi.isFrontWheel && wi.raycastInfo.groundObject) {
20791
- wi.raycastInfo.contactPointWS.subtractToRef(this._sv1, this._sv2);
20792
- Vector3.CrossToRef(this._sv2, this._axle[w], this._sv3);
20793
- var lever_w = Vector3.Dot(this._sv3, chassisUp);
20794
- rearIdxList.push(w);
20795
- rearLeverList.push(lever_w);
20796
- leverSum += lever_w;
20797
- }
20798
- }
20799
- if (rearIdxList.length === 0 || Math.abs(leverSum) <= MIN_LEVER_EPS) {
20688
+ var targetYawRad = Tools.ToRadians(this.arcadeDonutDirectYawDegPerSec)
20689
+ * this._arcadeDonutDirectionSign * steerSign
20690
+ * fade * this.arcadeSteeringAssist;
20691
+ if (Math.abs(targetYawRad) <= 1e-5) {
20800
20692
  this._arcadeDonutHoldElapsedSec += timeStep;
20801
20693
  return;
20802
20694
  }
20803
- var IaddPerWheel = donutYawJz / leverSum;
20804
- for (var ii = 0; ii < rearIdxList.length; ii++) {
20805
- var w2 = rearIdxList[ii];
20806
- var wi2 = this._wheelInfo[w2];
20807
- this._axle[w2].scaleToRef(IaddPerWheel, this._sv2);
20808
- this._chassisBody.applyImpulse(this._sv2, wi2.raycastInfo.contactPointWS);
20809
- }
20695
+ this._chassisBody.getAngularVelocityToRef(this._sv9);
20696
+ var currentYawRad = Vector3.Dot(this._sv9, chassisUp);
20697
+ var lockRate = 14.0;
20698
+ var lockBlend = Scalar.Clamp(1.0 - Math.exp(-lockRate * timeStep), 0.0, 1.0);
20699
+ var nextYawRad = currentYawRad + (targetYawRad - currentYawRad) * lockBlend;
20700
+ var minHoldYawRad = Math.abs(targetYawRad) * 0.55;
20701
+ if (Math.sign(nextYawRad) !== Math.sign(targetYawRad) || Math.abs(nextYawRad) < minHoldYawRad) {
20702
+ nextYawRad = Math.sign(targetYawRad) * minHoldYawRad;
20703
+ }
20704
+ chassisUp.scaleToRef(currentYawRad, this._sv1);
20705
+ this._sv9.subtractToRef(this._sv1, this._sv2);
20706
+ chassisUp.scaleToRef(nextYawRad, this._sv3);
20707
+ this._sv2.addToRef(this._sv3, this._sv9);
20708
+ this._chassisBody.setAngularVelocity(this._sv9);
20810
20709
  this._arcadeDonutHoldElapsedSec += timeStep;
20811
20710
  }
20812
20711
  applyHandbrakeYawAssist(timeStep, absSpeedKmh, signedSpeedKmh) {
20813
20712
  this.isArcadeYawAssistActive = false;
20814
- if (this.isArcadeHandBrakeActive === false) {
20815
- this._wasArcadeHandBrakeActive = false;
20816
- this._wasArcadeYawAssistApplyingForce = false;
20817
- this._handbrakeKickJzRemaining = 0;
20818
- this._handbrakeKickFramesRemaining = 0;
20819
- this._arcadeHandbrakeLatchedDriveSign = 0;
20820
- this._arcadeHandbrakeHoldElapsedSec = 0;
20821
- this._arcadeHandbrakeSlewedSteerRad = 0;
20822
- this._arcadeHandbrakeClampReleaseFadeSec = 999;
20713
+ if (!this.arcadeHandbrakeAssistEnabled)
20823
20714
  return;
20824
- }
20825
- const TAU_RESPONSE = 0.18;
20826
- const V_ENGAGE_MIN_KMH = 7.0;
20827
- const V_ENGAGE_FULL_KMH = 65.0;
20828
- const V_KICK_FULL_KMH = 65.0;
20829
- const I_Z_FACTOR = 0.22;
20830
- const MIN_STEER_RAD = 0.02;
20831
- const MIN_LEVER_EPS = 0.001;
20832
- const ASSIST_MIN_NM = 25.0;
20833
- const SLIDE_TAPER_RANGE_RAD = Math.PI / 4;
20834
- const K_ASSIST = this.arcadeHandbrakeYawAuthority;
20835
- const R_MAX_DEG_PER_SEC = this.arcadeHandbrakeMaxYawRateDegPerSec;
20836
- const K_KICK_DEG_PER_SEC = this.arcadeHandbrakeKickStrengthDegPerSec;
20837
- const V_REF_MPS = this.arcadeHandbrakeReferenceSpeedKmh / 3.6;
20838
- const MAX_SLIDE_ANGLE_RAD = Tools.ToRadians(this.arcadeHandbrakeMaxSlideAngleDeg);
20839
- const KICK_FRAMES = Math.max(1, this.arcadeHandbrakeKickFrames | 0);
20840
- this._arcadeYawAssistDebugFrameCounter++;
20841
- var debugEnabled = this.arcadeYawAssistDebugLogEnabled === true;
20842
- var debugIntervalHit = debugEnabled && this.arcadeYawAssistDebugLogIntervalFrames > 0 && (this._arcadeYawAssistDebugFrameCounter % this.arcadeYawAssistDebugLogIntervalFrames) === 0;
20843
- var signedFrontSteerRad = this.getSignedFrontSteeringAngleRad();
20844
- var steeringMagnitude = Math.abs(signedFrontSteerRad);
20845
- var eligible = this.isArcadeHandBrakeActive === true && this.arcadeSteeringAssist > 0 && steeringMagnitude > MIN_STEER_RAD && absSpeedKmh > V_ENGAGE_MIN_KMH;
20846
- var risingEdge = this.isArcadeHandBrakeActive === true && this._wasArcadeHandBrakeActive === false;
20847
- if (this.arcadeHandbrakeSteerSlewLimitEnabled === true && !risingEdge) {
20848
- var slewMaxRad = Tools.ToRadians(this.arcadeHandbrakeSteerSlewLimitDegPerSec) * timeStep;
20849
- var steerDelta = signedFrontSteerRad - this._arcadeHandbrakeSlewedSteerRad;
20850
- if (steerDelta > slewMaxRad)
20851
- steerDelta = slewMaxRad;
20852
- else if (steerDelta < -slewMaxRad)
20853
- steerDelta = -slewMaxRad;
20854
- this._arcadeHandbrakeSlewedSteerRad += steerDelta;
20855
- }
20856
- else {
20857
- this._arcadeHandbrakeSlewedSteerRad = signedFrontSteerRad;
20858
- }
20859
- var effectiveSteerRad = this._arcadeHandbrakeSlewedSteerRad;
20860
- const cm = this._chassisTransform.m;
20715
+ var steeringMagnitude = this.getSteeringMagnitude();
20716
+ var steeringAuthorityInput = this.getSteeringAuthorityInput();
20717
+ if (!this.isArcadeHandBrakeActive || steeringMagnitude < 0.02)
20718
+ return;
20719
+ var speedMps = Math.max(0.0, absSpeedKmh / 3.6);
20720
+ var speedScale = Scalar.Clamp((speedMps - 0.5) / 3.0, 0.0, 1.0);
20721
+ if (speedScale <= 0.0)
20722
+ return;
20723
+ const m = this._chassisTransform.m;
20724
+ const ri = this._indexRightAxis;
20861
20725
  const ui = this._indexUpAxis;
20862
20726
  const fi = this._indexForwardAxis;
20863
- const ri = this._indexRightAxis;
20864
- const chassisUp = this._sv5;
20865
- const chassisForward = this._sv6;
20866
- const chassisRight = this._sv9;
20867
- chassisUp.set(cm[ui * 4], cm[ui * 4 + 1], cm[ui * 4 + 2]);
20868
- chassisForward.set(cm[fi * 4], cm[fi * 4 + 1], cm[fi * 4 + 2]);
20869
- chassisRight.set(cm[ri * 4], cm[ri * 4 + 1], cm[ri * 4 + 2]);
20870
- this._chassisBody.getLinearVelocityToRef(this._sv8);
20871
- var signedVxMps = Vector3.Dot(this._sv8, chassisForward);
20872
- var velRightMps = Vector3.Dot(this._sv8, chassisRight);
20873
- var speedMagMps = Math.sqrt(this._sv8.x * this._sv8.x + this._sv8.y * this._sv8.y + this._sv8.z * this._sv8.z);
20874
- var slipAngleRad = (speedMagMps > 0.1) ? Math.atan2(velRightMps, signedVxMps) : 0;
20875
- var driveSign = this._arcadeHandbrakeLatchedDriveSign !== 0
20876
- ? this._arcadeHandbrakeLatchedDriveSign
20877
- : (signedVxMps >= 0 ? 1 : -1);
20878
- var relSlipRad;
20879
- if (driveSign > 0) {
20880
- relSlipRad = slipAngleRad;
20881
- }
20882
- else {
20883
- relSlipRad = slipAngleRad >= 0 ? slipAngleRad - Math.PI : slipAngleRad + Math.PI;
20884
- }
20885
- var relSlipAbs = Math.abs(relSlipRad);
20886
- var relSlipSign = relSlipAbs > 1e-3 ? (relSlipRad > 0 ? 1 : -1) : 0;
20887
- var L = this.getApproxWheelbaseMeters();
20888
- if (L < 0.5)
20889
- L = 2.5;
20890
- var Iz = I_Z_FACTOR * this._chassisMass * L * L;
20891
- var rTarget = 0;
20892
- var currentYawRate = 0;
20893
- var gate = 0;
20894
- var slideTaper = 1.0;
20895
- var desiredMz = 0;
20896
- this._chassisBody.getAngularVelocityToRef(this._sv4);
20897
- currentYawRate = Vector3.Dot(this._sv4, chassisUp);
20898
- if (eligible) {
20899
- var gateRange = V_ENGAGE_FULL_KMH - V_ENGAGE_MIN_KMH;
20900
- var gateRaw = gateRange > 0 ? (absSpeedKmh - V_ENGAGE_MIN_KMH) / gateRange : 1.0;
20901
- gate = Scalar.Clamp(gateRaw, 0, 1);
20902
- gate = gate * gate * (3.0 - 2.0 * gate);
20903
- var vForTarget = driveSign * Math.min(speedMagMps, V_REF_MPS);
20904
- var rTargetRaw = K_ASSIST * vForTarget * effectiveSteerRad / L;
20905
- var rMaxLinear = Scalar.Clamp(speedMagMps / V_REF_MPS, 0, 1);
20906
- var lowSpeedShape = this.arcadeHandbrakeLowSpeedShape > 0 ? this.arcadeHandbrakeLowSpeedShape : 1.0;
20907
- var rMaxSpeedFactor = this.arcadeHandbrakeSpeedGateEnabled ? Math.pow(rMaxLinear, lowSpeedShape) : 1.0;
20908
- var rMax = Tools.ToRadians(R_MAX_DEG_PER_SEC) * rMaxSpeedFactor;
20909
- if (rTargetRaw > rMax)
20910
- rTargetRaw = rMax;
20911
- else if (rTargetRaw < -rMax)
20912
- rTargetRaw = -rMax;
20913
- rTarget = rTargetRaw * gate * this.arcadeSteeringAssist;
20914
- var counterSteerClampActive = false;
20915
- if (this.arcadeHandbrakeCounterSteerClampEnabled === true) {
20916
- var yawThresholdRadPerSec = Tools.ToRadians(this.arcadeHandbrakeCounterSteerYawThresholdDegPerSec);
20917
- if (Math.abs(currentYawRate) > yawThresholdRadPerSec && rTarget * currentYawRate < 0) {
20918
- rTarget = 0;
20919
- counterSteerClampActive = true;
20920
- }
20921
- }
20922
- var releaseFadeMs = this.arcadeHandbrakeClampReleaseFadeMs;
20923
- var clampFadeActive = false;
20924
- var clampFadeMul = 1.0;
20925
- if (counterSteerClampActive) {
20926
- this._arcadeHandbrakeClampReleaseFadeSec = 0;
20927
- }
20928
- else {
20929
- this._arcadeHandbrakeClampReleaseFadeSec += timeStep;
20930
- if (releaseFadeMs > 0) {
20931
- var fadeSec = releaseFadeMs / 1000.0;
20932
- if (this._arcadeHandbrakeClampReleaseFadeSec < fadeSec) {
20933
- var fadeT = this._arcadeHandbrakeClampReleaseFadeSec / fadeSec;
20934
- clampFadeMul = fadeT * fadeT * (3.0 - 2.0 * fadeT);
20935
- rTarget *= clampFadeMul;
20936
- clampFadeActive = true;
20937
- }
20938
- }
20939
- }
20940
- if (relSlipAbs > MAX_SLIDE_ANGLE_RAD) {
20941
- var pastMax = (relSlipAbs - MAX_SLIDE_ANGLE_RAD) / SLIDE_TAPER_RANGE_RAD;
20942
- if (pastMax > 1.0)
20943
- pastMax = 1.0;
20944
- slideTaper = 1.0 - pastMax;
20945
- rTarget *= slideTaper;
20946
- }
20947
- if (rTarget > rMax)
20948
- rTarget = rMax;
20949
- else if (rTarget < -rMax)
20950
- rTarget = -rMax;
20951
- desiredMz = Iz * (rTarget - currentYawRate) / TAU_RESPONSE;
20952
- }
20953
- var newMz;
20954
- if (eligible) {
20955
- newMz = desiredMz;
20727
+ this._stb1.set(m[ri * 4], m[ri * 4 + 1], m[ri * 4 + 2]);
20728
+ this._stb2.set(m[ui * 4], m[ui * 4 + 1], m[ui * 4 + 2]);
20729
+ this._stb3.set(m[fi * 4], m[fi * 4 + 1], m[fi * 4 + 2]);
20730
+ this._chassisBody.getAngularVelocityToRef(this._sv9);
20731
+ var localRoll = Vector3.Dot(this._sv9, this._stb1);
20732
+ var localYaw = Vector3.Dot(this._sv9, this._stb2);
20733
+ var localPitch = Vector3.Dot(this._sv9, this._stb3);
20734
+ var signedFrontSteerRad = this.getSignedFrontSteeringAngleRad();
20735
+ var wheelbaseMeters = this.getApproxWheelbaseMeters();
20736
+ var bicycleYawRate = 0.0;
20737
+ if (wheelbaseMeters > 0.5 && speedMps > 0.2 && Math.abs(signedFrontSteerRad) > 1e-4) {
20738
+ }
20739
+ var minimumYawRate = steeringAuthorityInput * this.arcadeSteeringAssist * (0.25 + steeringMagnitude * 1.0) * speedScale;
20740
+ var desiredYawBoost = Math.abs(bicycleYawRate) > Math.abs(minimumYawRate) ? bicycleYawRate : minimumYawRate;
20741
+ var sameDir = (desiredYawBoost * localYaw) >= 0.0;
20742
+ if (sameDir && Math.abs(localYaw) >= Math.abs(desiredYawBoost)) {
20743
+ this.isArcadeYawAssistActive = true;
20744
+ return;
20956
20745
  }
20957
- else {
20958
- newMz = 0;
20959
- }
20960
- var assistApplyingForce = Math.abs(newMz) > ASSIST_MIN_NM;
20961
- if (eligible && this._wasArcadeHandBrakeActive === false) {
20962
- this._arcadeHandbrakeLatchedDriveSign = signedVxMps >= 0 ? 1 : -1;
20963
- driveSign = this._arcadeHandbrakeLatchedDriveSign;
20964
- this._arcadeHandbrakeHoldElapsedSec = 0;
20965
- var kickRange = V_KICK_FULL_KMH - V_ENGAGE_MIN_KMH;
20966
- var kickRaw = kickRange > 0 ? (absSpeedKmh - V_ENGAGE_MIN_KMH) / kickRange : 1.0;
20967
- var kickGate = Scalar.Clamp(kickRaw, 0, 1);
20968
- kickGate = kickGate * kickGate * (3.0 - 2.0 * kickGate);
20969
- var steerSign = signedFrontSteerRad >= 0 ? 1 : -1;
20970
- var velSign = signedVxMps >= 0 ? 1 : -1;
20971
- var kickLinear = Scalar.Clamp(speedMagMps / V_REF_MPS, 0, 1);
20972
- var kickShape = this.arcadeHandbrakeLowSpeedShape > 0 ? this.arcadeHandbrakeLowSpeedShape : 1.0;
20973
- var kickSpeedFactor = this.arcadeHandbrakeSpeedGateEnabled ? Math.pow(kickLinear, kickShape) : 1.0;
20974
- var kickRadTotal = Tools.ToRadians(K_KICK_DEG_PER_SEC) * steerSign * velSign * kickGate * kickSpeedFactor * this.arcadeSteeringAssist;
20975
- var kickSuppressed = false;
20976
- if (this.arcadeHandbrakeCounterSteerClampEnabled === true) {
20977
- var kickYawThresholdRadPerSec = Tools.ToRadians(this.arcadeHandbrakeCounterSteerYawThresholdDegPerSec);
20978
- if (Math.abs(currentYawRate) > kickYawThresholdRadPerSec && kickRadTotal * currentYawRate < 0) {
20979
- kickRadTotal = 0;
20980
- kickSuppressed = true;
20981
- }
20982
- }
20983
- this._handbrakeKickJzRemaining = Iz * kickRadTotal;
20984
- this._handbrakeKickFramesRemaining = kickSuppressed ? 0 : KICK_FRAMES;
20985
- }
20986
- var kickAngularImpulseJz = 0;
20987
- var kickRad = 0;
20988
- if (eligible && this._handbrakeKickFramesRemaining > 0) {
20989
- var thisFrameKick = this._handbrakeKickJzRemaining / this._handbrakeKickFramesRemaining;
20990
- kickAngularImpulseJz += thisFrameKick;
20991
- this._handbrakeKickJzRemaining -= thisFrameKick;
20992
- this._handbrakeKickFramesRemaining--;
20993
- }
20994
- else if (!eligible) {
20995
- this._handbrakeKickJzRemaining = 0;
20996
- this._handbrakeKickFramesRemaining = 0;
20997
- }
20998
- if (Iz > 0)
20999
- kickRad = kickAngularImpulseJz / Iz;
21000
- var directYawJz = 0;
21001
- if (eligible && this.arcadeHandbrakeDirectYawEnabled === true && Iz > 0) {
21002
- var directDurSec = this.arcadeHandbrakeDirectYawDurationMs > 0 ? this.arcadeHandbrakeDirectYawDurationMs / 1000.0 : 0;
21003
- var directFadeSec = this.arcadeHandbrakeDirectYawFadeMs > 0 ? this.arcadeHandbrakeDirectYawFadeMs / 1000.0 : 0;
21004
- var elapsed = this._arcadeHandbrakeHoldElapsedSec;
21005
- var fadeIn = directFadeSec > 0 ? Scalar.Clamp(elapsed / directFadeSec, 0, 1) : 1.0;
21006
- var fadeOut = 1.0;
21007
- if (directDurSec > 0) {
21008
- var timeLeft = directDurSec - elapsed;
21009
- if (timeLeft <= 0) {
21010
- fadeOut = 0;
21011
- }
21012
- else if (directFadeSec > 0 && timeLeft < directFadeSec) {
21013
- fadeOut = timeLeft / directFadeSec;
21014
- }
21015
- }
21016
- var directFade = Math.min(fadeIn, fadeOut);
21017
- if (directFade > 0) {
21018
- var dyLinear = Scalar.Clamp(speedMagMps / V_REF_MPS, 0, 1);
21019
- var dyShape = this.arcadeHandbrakeLowSpeedShape > 0 ? this.arcadeHandbrakeLowSpeedShape : 1.0;
21020
- var dySpeedFactor = this.arcadeHandbrakeSpeedGateEnabled ? Math.pow(dyLinear, dyShape) : 1.0;
21021
- var dySteerSign = signedFrontSteerRad >= 0 ? 1 : -1;
21022
- var dyExtraRad = Tools.ToRadians(this.arcadeHandbrakeDirectYawDegPerSec)
21023
- * driveSign * dySteerSign
21024
- * gate * dySpeedFactor
21025
- * directFade * this.arcadeSteeringAssist;
21026
- directYawJz = Iz * dyExtraRad * timeStep;
21027
- }
21028
- }
21029
- if (eligible) {
21030
- this._arcadeHandbrakeHoldElapsedSec += timeStep;
21031
- }
21032
- var leverSum = 0;
21033
- var rearGroundedCount = 0;
21034
- var IaddCtrlDesired = 0;
21035
- var IaddCtrlAppliedSum = 0;
21036
- var IaddKickPerWheel = 0;
21037
- var IaddKickAppliedSum = 0;
21038
- var IaddDirectPerWheel = 0;
21039
- var IaddDirectAppliedSum = 0;
21040
- var Jz_through_tires = 0;
21041
- var minCtrlClamp = 1.0;
21042
- var perWheelLog = "";
21043
- var rearIdxList = [];
21044
- var rearLeverList = [];
21045
- var hasController = Math.abs(newMz) > 0;
21046
- var hasKick = Math.abs(kickAngularImpulseJz) > 0;
21047
- var hasDirect = Math.abs(directYawJz) > 0;
21048
- if ((hasController || hasKick || hasDirect) && this._chassisMass > 0) {
21049
- this._chassisBody.getObjectCenterWorldToRef(this._sv1);
21050
- for (var w = 0; w < this._wheelInfo.length; w++) {
21051
- var wi = this._wheelInfo[w];
21052
- if (!wi.isFrontWheel && wi.raycastInfo.groundObject) {
21053
- wi.raycastInfo.contactPointWS.subtractToRef(this._sv1, this._sv2);
21054
- Vector3.CrossToRef(this._sv2, this._axle[w], this._sv3);
21055
- var lever_w = Vector3.Dot(this._sv3, chassisUp);
21056
- rearIdxList.push(w);
21057
- rearLeverList.push(lever_w);
21058
- leverSum += lever_w;
21059
- rearGroundedCount++;
21060
- }
21061
- }
21062
- if (rearGroundedCount > 0 && Math.abs(leverSum) > MIN_LEVER_EPS) {
21063
- if (hasController)
21064
- IaddCtrlDesired = (newMz * timeStep) / leverSum;
21065
- if (hasKick)
21066
- IaddKickPerWheel = kickAngularImpulseJz / leverSum;
21067
- if (hasDirect)
21068
- IaddDirectPerWheel = directYawJz / leverSum;
21069
- for (var ii = 0; ii < rearIdxList.length; ii++) {
21070
- var w2 = rearIdxList[ii];
21071
- var lever_w2 = rearLeverList[ii];
21072
- var wi2 = this._wheelInfo[w2];
21073
- var IaddCtrlW = hasController ? IaddCtrlDesired : 0;
21074
- var IaddTotalW = IaddCtrlW + IaddKickPerWheel + IaddDirectPerWheel;
21075
- if (IaddTotalW !== 0) {
21076
- this._axle[w2].scaleToRef(IaddTotalW, this._sv2);
21077
- this._chassisBody.applyImpulse(this._sv2, wi2.raycastInfo.contactPointWS);
21078
- IaddCtrlAppliedSum += IaddCtrlW;
21079
- IaddKickAppliedSum += IaddKickPerWheel;
21080
- IaddDirectAppliedSum += IaddDirectPerWheel;
21081
- Jz_through_tires += lever_w2 * IaddTotalW;
21082
- }
21083
- if (debugEnabled) {
21084
- perWheelLog += " w" + w2
21085
- + "{maximp=" + (wi2.suspensionForce * timeStep * wi2.frictionSlip).toFixed(1)
21086
- + " side=" + this._sideImpulse[w2].toFixed(1)
21087
- + " fwd=" + (this._forwardImpulse[w2] * 0.5).toFixed(1)
21088
- + " ctrlDes=" + IaddCtrlDesired.toFixed(1)
21089
- + " ctrl=" + IaddCtrlW.toFixed(1)
21090
- + " kick=" + IaddKickPerWheel.toFixed(1)
21091
- + " direct=" + IaddDirectPerWheel.toFixed(1)
21092
- + " tot=" + IaddTotalW.toFixed(1) + "}";
21093
- }
21094
- }
21095
- }
21096
- }
21097
- this._arcadeYawAssistLastKickRad = kickRad;
21098
- this._arcadeYawAssistLastIaddPerWheel = IaddCtrlDesired + IaddKickPerWheel + IaddDirectPerWheel;
21099
- this._arcadeYawAssistLastClampScalar = minCtrlClamp;
21100
- this._arcadeYawAssistLastLeverSum = leverSum;
21101
- var assistActiveThisFrame = eligible || assistApplyingForce;
21102
- this.isArcadeYawAssistActive = assistActiveThisFrame;
21103
- this._wasArcadeHandBrakeActive = this.isArcadeHandBrakeActive;
21104
- this._wasArcadeYawAssistApplyingForce = assistApplyingForce;
20746
+ var yawDeltaMax = (0.15 + steeringMagnitude * 0.35) * speedScale;
20747
+ var yawDelta = Scalar.Clamp(desiredYawBoost * (2.0 + steeringMagnitude * 4.0) * timeStep, -yawDeltaMax, yawDeltaMax);
20748
+ if (Math.abs(yawDelta) < 1e-6)
20749
+ return;
20750
+ localYaw += yawDelta;
20751
+ this._sv9.set(this._stb1.x * localRoll + this._stb2.x * localYaw + this._stb3.x * localPitch, this._stb1.y * localRoll + this._stb2.y * localYaw + this._stb3.y * localPitch, this._stb1.z * localRoll + this._stb2.z * localYaw + this._stb3.z * localPitch);
20752
+ this._chassisBody.setAngularVelocity(this._sv9);
20753
+ this.isArcadeYawAssistActive = true;
21105
20754
  }
21106
20755
  resolveWheelSpinDirection(wheelIndex, requestedDriveImpulse, appliedDriveImpulse) {
21107
20756
  if (Math.abs(requestedDriveImpulse) > 0.0001) {
@@ -21299,6 +20948,24 @@ export class btRaycastVehicle {
21299
20948
  this._forwardWS[i].normalize();
21300
20949
  this._sideImpulse[i] = this.resolveSingleBilateral(this._chassisBody, wheel.raycastInfo.contactPointWS, this._axle[i]);
21301
20950
  this._sideImpulse[i] *= this.sideFrictionStiffness;
20951
+ if (this.arcadeSideSlipSaturationEnabled && this._sideImpulse[i] !== 0) {
20952
+ this.velocityAtWorldPoint(this._chassisBody, wheel.raycastInfo.contactPointWS, this._sv8);
20953
+ var vLat = Vector3.Dot(this._axle[i], this._sv8);
20954
+ var vFwd = Vector3.Dot(this._forwardWS[i], this._sv8);
20955
+ var wheelSpeedSqr = vLat * vLat + vFwd * vFwd;
20956
+ var minSpeed = this.arcadeSideSlipMinSpeedMps;
20957
+ if (wheelSpeedSqr > minSpeed * minSpeed) {
20958
+ var slipRad = Math.atan2(Math.abs(vLat), Math.max(Math.abs(vFwd), 1e-3));
20959
+ var peakRad = Tools.ToRadians(Math.max(this.arcadeSideSlipPeakDeg, 0.1));
20960
+ if (slipRad > peakRad) {
20961
+ var holdFactor = Math.sin(peakRad) / Math.max(Math.sin(slipRad), 1e-3);
20962
+ var falloffSpan = Math.max(this.arcadeSideSlipFalloffDeg - this.arcadeSideSlipPeakDeg, 0.1);
20963
+ var t = Math.min(Math.max((Tools.ToDegrees(slipRad) - this.arcadeSideSlipPeakDeg) / falloffSpan, 0.0), 1.0);
20964
+ var rolloff = Scalar.Lerp(1.0, this.arcadeSideSlipFalloffFactor, t);
20965
+ this._sideImpulse[i] *= holdFactor * rolloff;
20966
+ }
20967
+ }
20968
+ }
21302
20969
  }
21303
20970
  }
21304
20971
  var sideFactor = 1.0;
@@ -21424,12 +21091,6 @@ export class btRaycastVehicle {
21424
21091
  this._wheelInfo[wheel_i].skidInfo = Math.min(this._wheelInfo[wheel_i].skidInfo, arcadeSkidInfo);
21425
21092
  }
21426
21093
  }
21427
- var isAnyArcadeModeActiveNow = this.isArcadeHandBrakeActive || this.isArcadeWheelSkidActive || this.isArcadeBurnoutModeActive || this.isArcadeDonutModeActive;
21428
- if (this._wasAnyArcadeModeActive && !isAnyArcadeModeActiveNow) {
21429
- this._postHandbrakeLogFrames = 180;
21430
- this._postHandbrakeLogCounter = 0;
21431
- }
21432
- this._wasAnyArcadeModeActive = isAnyArcadeModeActiveNow;
21433
21094
  if (sliding) {
21434
21095
  for (var wheel_i = 0; wheel_i < numWheels; wheel_i++) {
21435
21096
  if (this._sideImpulse[wheel_i] !== 0) {
@@ -21453,7 +21114,8 @@ export class btRaycastVehicle {
21453
21114
  avgSideImpulse /= groundedSideCount;
21454
21115
  var sideBlendToCoM = 0;
21455
21116
  var absSpeedKmh = Math.abs(this._currentVehicleSpeedKmHour);
21456
- if (this.sideToSideStabilityEnabled && absSpeedKmh > this.sideToSideStabilityStartKmh) {
21117
+ var arcadeSlideActive = this.isArcadeHandBrakeActive || this.isArcadeWheelSkidActive || this.isArcadeBurnoutModeActive || this.isArcadeDonutModeActive;
21118
+ if (!arcadeSlideActive && this.sideToSideStabilityEnabled && absSpeedKmh > this.sideToSideStabilityStartKmh) {
21457
21119
  var sideBlendRange = this.sideToSideStabilityFullKmh - this.sideToSideStabilityStartKmh;
21458
21120
  if (sideBlendRange > 0) {
21459
21121
  sideBlendToCoM = 0.7 * Math.min((absSpeedKmh - this.sideToSideStabilityStartKmh) / sideBlendRange, 1.0);
@@ -21522,12 +21184,22 @@ export class btRaycastVehicle {
21522
21184
  clampChassisYawRate(deltaTime) {
21523
21185
  if (this.maximumYawRateLow <= 0 && this.maximumYawRateHigh <= 0)
21524
21186
  return;
21525
- const arcadeActive = (this.isArcadeHandBrakeActive === true || this.isArcadeBurnoutModeActive === true || this.isArcadeDonutModeActive === true || this.isArcadeWheelSkidActive === true);
21526
- if (arcadeActive === true && this.arcadeYawCapMultiplier <= 0)
21187
+ const arcadeActive = (this.isArcadeHandBrakeActive === true || this.isArcadeBurnoutModeActive === true || this.isArcadeDonutModeActive === true);
21188
+ if (arcadeActive === true && this.isArcadeHandBrakeActive === true && this.arcadeHandbrakeYawCapMultiplier <= 0)
21189
+ return;
21190
+ if (arcadeActive === true && this.isArcadeBurnoutModeActive === true && this.arcadeBurnoutYawCapMultiplier <= 0)
21191
+ return;
21192
+ if (arcadeActive === true && this.isArcadeDonutModeActive === true && this.arcadeDonutYawCapMultiplier <= 0)
21527
21193
  return;
21528
21194
  let capDeg = Scalar.Lerp(this.maximumYawRateLow, this.maximumYawRateHigh, this.smoothedGradientSpeed);
21529
- if (arcadeActive === true)
21530
- capDeg *= this.arcadeYawCapMultiplier;
21195
+ if (arcadeActive === true) {
21196
+ if (this.isArcadeHandBrakeActive === true)
21197
+ capDeg *= this.arcadeHandbrakeYawCapMultiplier;
21198
+ if (this.isArcadeBurnoutModeActive === true)
21199
+ capDeg *= this.arcadeBurnoutYawCapMultiplier;
21200
+ if (this.isArcadeDonutModeActive === true)
21201
+ capDeg *= this.arcadeDonutYawCapMultiplier;
21202
+ }
21531
21203
  if (capDeg <= 0)
21532
21204
  return;
21533
21205
  const capRad = Tools.ToRadians(capDeg);
@@ -23190,81 +22862,59 @@ export class RaycastVehicle {
23190
22862
  this.m_vehicle.arcadeSteeringAssist = value;
23191
22863
  }
23192
22864
  }
23193
- getArcadeDonutDirectYawDegPerSec() {
23194
- if (this.m_vehicle != null) {
23195
- return this.m_vehicle.arcadeDonutDirectYawDegPerSec;
23196
- }
23197
- return 1.0;
23198
- }
23199
- setArcadeDonutDirectYawDegPerSec(value) {
23200
- if (this.m_vehicle != null) {
23201
- this.m_vehicle.arcadeDonutDirectYawDegPerSec = value;
23202
- }
23203
- }
23204
- getArcadeHandbrakeDirectYawDegPerSec() {
22865
+ getArcadeDonutDirectYawEnabled() {
23205
22866
  if (this.m_vehicle != null) {
23206
- return this.m_vehicle.arcadeHandbrakeDirectYawDegPerSec;
22867
+ return this.m_vehicle.arcadeDonutDirectYawEnabled;
23207
22868
  }
23208
- return 1.0;
23209
- }
23210
- setArcadeHandbrakeDirectYawDegPerSec(value) {
23211
- if (this.m_vehicle != null) {
23212
- this.m_vehicle.arcadeHandbrakeDirectYawDegPerSec = value;
23213
- }
23214
- }
23215
- getArcadeHandbrakeMaxSlideAngleDeg() {
23216
- if (this.m_vehicle != null) {
23217
- return this.m_vehicle.arcadeHandbrakeMaxSlideAngleDeg;
23218
- }
23219
- return 1.0;
22869
+ return false;
23220
22870
  }
23221
- setArcadeHandbrakeMaxSlideAngleDeg(value) {
22871
+ setArcadeDonutDirectYawEnabled(value) {
23222
22872
  if (this.m_vehicle != null) {
23223
- this.m_vehicle.arcadeHandbrakeMaxSlideAngleDeg = value;
22873
+ this.m_vehicle.arcadeDonutDirectYawEnabled = value;
23224
22874
  }
23225
22875
  }
23226
- getArcadeHandbrakeBicycleYawAuthority() {
22876
+ getArcadeDonutDirectYawDegPerSec() {
23227
22877
  if (this.m_vehicle != null) {
23228
- return this.m_vehicle.arcadeHandbrakeYawAuthority;
22878
+ return this.m_vehicle.arcadeDonutDirectYawDegPerSec;
23229
22879
  }
23230
22880
  return 1.0;
23231
22881
  }
23232
- setArcadeHandbrakeBicycleYawAuthority(value) {
22882
+ setArcadeDonutDirectYawDegPerSec(value) {
23233
22883
  if (this.m_vehicle != null) {
23234
- this.m_vehicle.arcadeHandbrakeYawAuthority = value;
22884
+ this.m_vehicle.arcadeDonutDirectYawDegPerSec = value;
23235
22885
  }
23236
22886
  }
23237
- getArcadeHandbrakeMaxYawRateDegPerSec() {
22887
+ getArcadeHandbrakeYawCapMultiplier() {
23238
22888
  if (this.m_vehicle != null) {
23239
- return this.m_vehicle.arcadeHandbrakeMaxYawRateDegPerSec;
22889
+ return this.m_vehicle.arcadeHandbrakeYawCapMultiplier;
23240
22890
  }
23241
22891
  return 1.0;
23242
22892
  }
23243
- setArcadeHandbrakeMaxYawRateDegPerSec(value) {
22893
+ setArcadeHandbrakeYawCapMultiplier(value) {
23244
22894
  if (this.m_vehicle != null) {
23245
- this.m_vehicle.arcadeHandbrakeMaxYawRateDegPerSec = value;
22895
+ this.m_vehicle.arcadeHandbrakeYawCapMultiplier = value;
23246
22896
  }
23247
22897
  }
23248
- getArcadeHandbrakeReferenceSpeedKmh() {
22898
+ getArcadeBurnoutYawCapMultiplier() {
23249
22899
  if (this.m_vehicle != null) {
23250
- return this.m_vehicle.arcadeHandbrakeReferenceSpeedKmh;
22900
+ return this.m_vehicle.arcadeBurnoutYawCapMultiplier;
23251
22901
  }
23252
22902
  return 1.0;
23253
22903
  }
23254
- setArcadeHandbrakeReferenceSpeedKmh(value) {
22904
+ setArcadeBurnoutYawCapMultiplier(value) {
23255
22905
  if (this.m_vehicle != null) {
23256
- this.m_vehicle.arcadeHandbrakeReferenceSpeedKmh = value;
22906
+ this.m_vehicle.arcadeBurnoutYawCapMultiplier = value;
23257
22907
  }
23258
22908
  }
23259
- getArcadeHandbrakeKickStrengthDegPerSec() {
22909
+ getArcadeDonutYawCapMultiplier() {
23260
22910
  if (this.m_vehicle != null) {
23261
- return this.m_vehicle.arcadeHandbrakeKickStrengthDegPerSec;
22911
+ return this.m_vehicle.arcadeDonutYawCapMultiplier;
23262
22912
  }
23263
22913
  return 1.0;
23264
22914
  }
23265
- setArcadeHandbrakeKickStrengthDegPerSec(value) {
22915
+ setArcadeDonutYawCapMultiplier(value) {
23266
22916
  if (this.m_vehicle != null) {
23267
- this.m_vehicle.arcadeHandbrakeKickStrengthDegPerSec = value;
22917
+ this.m_vehicle.arcadeDonutYawCapMultiplier = value;
23268
22918
  }
23269
22919
  }
23270
22920
  getArcadeBurnoutActive() {
@@ -23526,22 +23176,6 @@ export class RaycastVehicle {
23526
23176
  this.m_vehicle.wheelAtRestSpeedThresholdKmh = value;
23527
23177
  }
23528
23178
  }
23529
- setWheelSpinDebugLogEnabled(enabled) {
23530
- if (this.m_vehicle != null) {
23531
- this.m_vehicle.wheelSpinDebugLogEnabled = enabled;
23532
- }
23533
- }
23534
- getWheelSpinDebugLogEnabled() {
23535
- if (this.m_vehicle != null) {
23536
- return this.m_vehicle.wheelSpinDebugLogEnabled;
23537
- }
23538
- return false;
23539
- }
23540
- setWheelSpinDebugLogIntervalFrames(frames) {
23541
- if (this.m_vehicle != null) {
23542
- this.m_vehicle.wheelSpinDebugLogIntervalFrames = frames;
23543
- }
23544
- }
23545
23179
  updateWheelInformation() {
23546
23180
  const wheels = this.getNumWheels();
23547
23181
  if (wheels > 0) {