@needle-tools/car-physics
Version:
Car physics for Needle Engine: Create physical cars with ease
2 lines (1 loc) • 20.2 kB
JavaScript
import{getParam as T,serializable as n,ParticleSystem as J,Behaviour as k,getBoundingBox as V,getTempVector as m,Mathf as w,getTempQuaternion as F,Gizmos as P,ParticleSystemBaseBehaviour as X,Rigidbody as E,BoxCollider as L,delayForFrames as Y,FrameEvent as Z,EventList as W,OrbitControls as ee,Camera as z,GameObject as te,findObjectOfType as ie,SmoothFollow as se,Application as re}from"@needle-tools/engine";import{Object3D as O,Vector2 as Q,Quaternion as M,Vector3 as j,Euler as K}from"three";var I=(a=>(a[a.all=0]="all",a[a.rear=1]="rear",a[a.front=2]="front",a))(I||{}),b=(a=>(a[a.front=0]="front",a[a.rear=1]="rear",a))(b||{}),ae=Object.defineProperty,f=(a,e,t,r)=>{for(var i=void 0,s=a.length-1,o;s>=0;s--)(o=a[s])&&(i=o(e,t,i)||i);return i&&ae(e,t,i),i};const D=T("debugwheels");class c extends k{get index(){return this._wheelIndex}wheelModel;axle=b.front;radius=-1;suspensionRestLength=-1;maxSuspensionTravel=-1;suspensionCompression=3;suspensionRelax=5;suspensionStiff=-1;maxSuspensionForce=-1;sideFrictionStiffness=.7;frictionSlip=new Q(1,20);skidParticle;skidVisualSideThreshold=5;skidVisualBreakThreshold=.1;skidParticleBehaviour;wheelModelRight;wheelModelUp;car;vehicle;_wheelIndex=-1;_activeRadius=-1;_initialQuaternion;async initialize(e,t,r){this.car=e,this.vehicle=t,this._wheelIndex=r;const i=this.wheelModel||this.gameObject;let s=this.radius;if(s<=0&&(s=V(i).getSize(m()).y*.5),s<0){console.error("CarWheel: Radius is invalid, please set it manually or make sure the wheel is attached to a model");return}this._activeRadius=Math.max(.01,s),this._initialQuaternion=i.quaternion.clone(),this.wheelModel?.quaternion.identity(),this.gameObject?.quaternion.identity();const o=e.gameObject.worldQuaternion.clone();e.gameObject.worldQuaternion=new M;const h=new M;h.copy(e.gameObject.worldQuaternion).multiply(i.worldQuaternion.clone().invert()),e.gameObject.worldQuaternion=o,this.wheelModelUp=new j(0,1,0).clone().applyQuaternion(h),this.wheelModelRight=new j(1,0,0).clone().applyQuaternion(h);const S=i.worldPosition,u=this.car.gameObject.worldToLocal(S);u.multiply(this.car.gameObject.worldScale),u.y+=this._activeRadius*.5;const x=m(0,-1,0),g=m(-1,0,0);let p=this.suspensionRestLength;(!p||p<=0)&&(p=this._activeRadius*.5);let l=this.maxSuspensionTravel;(!l||l<=0)&&(l=this._activeRadius*.5);let d=this.suspensionStiff;(!d||d<=0)&&(d=50);let y=this.maxSuspensionForce;(!y||y<=0)&&(y=1e8),D&&console.debug(this.name,{restLength:p,suspensionTravel:l,suspensionStiff:d,maxSupsensionForce:y,radius:this._activeRadius},this),this.vehicle.addWheel(u,x,g,p,this._activeRadius),this.vehicle.setWheelMaxSuspensionTravel(r,l),this.vehicle.setWheelMaxSuspensionForce(r,y),this.vehicle.setWheelSuspensionStiffness(r,d),this.vehicle.setWheelSuspensionCompression(r,this.suspensionCompression),this.vehicle.setWheelSuspensionRelaxation(r,this.suspensionRelax),this.vehicle.setWheelSideFrictionStiffness(r,this.sideFrictionStiffness),this.vehicle.setWheelFrictionSlip(r,this.frictionSlip.y),this.skidParticle&&(this.skidParticleBehaviour=new $,this.skidParticle.addBehaviour(this.skidParticleBehaviour))}applyPhysics(e,t,r){this.car.carDrive==I.front&&this.axle==b.front||this.car.carDrive==I.rear&&this.axle==b.rear||this.car.carDrive==I.all||(e=0),this.vehicle.setWheelEngineForce(this._wheelIndex,e),this.vehicle.setWheelBrake(this._wheelIndex,t),this.axle==b.front&&this.vehicle.setWheelSteering(this._wheelIndex,-r);let i=m(this.car.velocity).clampLength(0,1).dot(this.car.gameObject.worldRight);i=1-Math.abs(i);const s=w.lerp(this.frictionSlip.x,this.frictionSlip.y,i);this.vehicle.setWheelFrictionSlip(this._wheelIndex,s)}updateVisuals(){const e=this.wheelModel||this.gameObject,t=this.vehicle.wheelRotation(this._wheelIndex),r=this.vehicle.wheelSteering(this._wheelIndex),i=F().setFromAxisAngle(this.wheelModelUp,r),s=F().setFromAxisAngle(this.wheelModelRight,t),o=i.multiply(s);e.quaternion.copy(o),e.quaternion.multiply(this._initialQuaternion);const h=this.vehicle.wheelContactPoint(this._wheelIndex),S=this.vehicle.wheelIsInContact(this._wheelIndex),u=m();if(h&&(D&&P.DrawWireSphere(h,.02,16777045,0,!1),u.copy(this.car.gameObject.worldUp).multiplyScalar(this._activeRadius),u.add(h),e.worldPosition=u),this.skidParticleBehaviour){const x=Math.abs(this.vehicle.wheelSideImpulse(this._wheelIndex)??0),g=Math.abs(this.vehicle.wheelBrake(this._wheelIndex)??0),p=x>this.skidVisualSideThreshold||g>this.skidVisualBreakThreshold,l=S&&h!=null&&p;if(this.skidParticle&&h){const d=m(h);d.y+=this.skidParticle.main.startSize.constant/4,this.skidParticle.worldPosition=d}this.skidParticleBehaviour.isSkidding=l}if(D){const x=this._activeRadius*.1,g=m(this.car.gameObject.worldRight).multiplyScalar(-1);g.applyEuler(new K(0,r,0)),P.DrawCircle(u,g,this._activeRadius,255,0,!1);const p=m(u),l=m(u).add(m(g).multiplyScalar(this._activeRadius));P.DrawLine(p,l,16711680,0,!1),P.DrawSphere(l,x,16711680,0,!1);const d=m(this.car.gameObject.worldForward).multiplyScalar(this._activeRadius*1);d.applyEuler(new K(0,r,0));const y=m(u).add(d);P.DrawLine(u,y,255,0,!1),P.DrawSphere(y,x,255,0,!1)}}}f([n(O)],c.prototype,"wheelModel"),f([n()],c.prototype,"axle"),f([n()],c.prototype,"radius"),f([n()],c.prototype,"suspensionRestLength"),f([n()],c.prototype,"maxSuspensionTravel"),f([n()],c.prototype,"suspensionCompression"),f([n()],c.prototype,"suspensionRelax"),f([n()],c.prototype,"suspensionStiff"),f([n()],c.prototype,"maxSuspensionForce"),f([n()],c.prototype,"sideFrictionStiffness"),f([n(Q)],c.prototype,"frictionSlip"),f([n(J)],c.prototype,"skidParticle"),f([n()],c.prototype,"skidVisualSideThreshold"),f([n()],c.prototype,"skidVisualBreakThreshold");class $ extends X{isSkidding=!1;update(e,t){const r=e;if(this.system.trails?.enabled&&r){this.isSkidding||e.color.setW(0);let i=r.previous?.tail;for(;i&&i.hasPrev();){const s=i;s.data??={},s.data.isSkidding===void 0&&(s.data.isSkidding=this.isSkidding),s.data.isSkidding===!1&&i.data.color?.setW(0),i=i.prev}}}}var oe=Object.defineProperty,R=(a,e,t,r)=>{for(var i=void 0,s=a.length-1,o;s>=0;s--)(o=a[s])&&(i=o(e,t,i)||i);return i&&oe(e,t,i),i};const U=T("debugcar");class v extends k{carDrive=I.all;mass=500;maxSteer=40;steerSmoothingFactor=.1;accelerationForce=12;breakForce=12;topSpeed=25;wheels=[];steerImpulse(e){this._steerInput+=e,this._steerInput=w.clamp(this._steerInput,-1,1)}get currentSteer(){return this._currentSteer}set currentSteer(e){this._currentSteer=e}accelerationImpulse(e){this._currAcc+=e}breakImpulse(e){this._currBreak+=e}get rigidbody(){return this._rigidbody}get rapierRigidbody(){return this.context.physics.engine?.getBody(this._rigidbody)}get vehicle(){return this._vehicle}get velocity(){return this._rigidbody?.getVelocity()}get currentSpeed(){return this._vehicle?.currentVehicleSpeed()||0}get currentSpeedInKmh(){return this.currentSpeed*3.6}get maxSpeedInKmh(){return this.topSpeed*3.6}get currentSpeed01(){return this._vehicle?this._vehicle.currentVehicleSpeed()/this.topSpeed:0}get airtime(){return this._airtime}set airtime(e){this._airtime=e}_vehicle;_rigidbody;_currentSteer=0;_currAcc=0;_currBreak=0;_steerInput=0;_airtime=0;awake(){if(this._rigidbody||(this._rigidbody=this.gameObject.addComponent(E)),!this.gameObject.getComponentInChildren(L)){const e=L.add(this.gameObject),t=new O;t.addComponent(e),this.gameObject.add(t),t.position.copy(e.center),e.center.set(0,0,0),e.center.y+=e.size.y*.1,e.size.x*=.85,e.size.y*=.7,e.size.z*=.85,e.updateProperties()}}_physicsRoutine;async onEnable(){if(this.mass<=0&&(this.mass=1),this._rigidbody=this.gameObject.getOrAddComponent(E),this._rigidbody.mass=this.mass,this._rigidbody.autoMass=this.mass<=0,await this.context.physics.engine?.initialize().then(()=>Y(1)),!this.activeAndEnabled)return;const e=this.context.physics.engine?.world;if(!e){console.error("[CarPhysics] Physics world not found");return}if(!this.rapierRigidbody){console.error("[CarPhysics] Rigidbody not found");return}if(this._vehicle||(this._vehicle=e.createVehicleController(this.rapierRigidbody)),this._vehicle.indexUpAxis=1,this._vehicle.setIndexForwardAxis=2,this.wheels.length===0&&this.wheels.push(...this.gameObject.getComponentsInChildren(c).filter(t=>t.activeAndEnabled)),this.wheels.length<=0){console.debug(`[CarPhysics] No wheels found on ${this.gameObject.name}, trying to find them`);const t=ne(this);t.length>0&&(console.debug(`[CarPhysics] Found ${t.length} wheels: ${t.map(r=>`${r.name} (${b[r.axle]})`).join(", ")}`),this.wheels.push(...t))}this.wheels.length<=0&&console.warn(`[CarPhysics] No wheels found on ${this.gameObject.name}`),U&&console.log(`[CarPhysics] ${this.name} has ${this.wheels.length} wheels:`,this.wheels),this.wheels.forEach((t,r)=>{t.initialize(this,this._vehicle,r)}),this._physicsRoutine=this.startCoroutine(this.physicsLoop(),Z.PostPhysicsStep)}onDisable(){this._vehicle&&this.context.physics.engine?.world?.removeVehicleController(this._vehicle),this._vehicle?.free(),this._vehicle=null,this._physicsRoutine&&this.stopCoroutine(this._physicsRoutine)}onBeforeRender(){if(!this._vehicle)return;if(this.steerSmoothingFactor>0){const t=this.context.time.deltaTime/this.steerSmoothingFactor;this._currentSteer=w.lerp(this._currentSteer,this._steerInput,w.clamp01(t))}else this._currentSteer=this._steerInput;this.applyPhysics(),this._steerInput=0,this._currAcc=0,this._currBreak=0;let e=!1;if(this.wheels.forEach(t=>{t.updateVisuals(),e||(e||=this._vehicle.wheelIsInContact(t.index))}),e?this._airtime=0:this._airtime+=this.context.time.deltaTime,U){const t=this._vehicle.chassis(),r=t.translation(),i=m(r).add(m(0,2,0)),s=`vel: ${this._vehicle.currentVehicleSpeed().toFixed(2)}`;P.DrawLabel(i,s,.1,0,16777215,0),this.wheels.forEach(o=>{const h=this._vehicle.wheelChassisConnectionPointCs(o.index);h&&P.DrawLine(m(r),m(h).applyQuaternion(t.rotation()).add(r),255,0,!1)})}}teleport(e,t,r=!0){!this.rapierRigidbody||!this._vehicle||(e&&this.rapierRigidbody.setTranslation(e,!0),t&&this.rapierRigidbody.setRotation(t,!0),r&&this._rigidbody.setVelocity(0,0,0))}*physicsLoop(){for(;;){if(this._vehicle){const e=this.context.time.deltaTime;this._vehicle?.updateVehicle(e)}yield null}}applyPhysics(){this._currAcc=w.clamp(this._currAcc,-1,1);let e=this._currAcc===0?.2:0,t=0;const r=this._rigidbody.getVelocity(),i=this._vehicle.currentVehicleSpeed(),s=i>this.topSpeed,o=this.context.time.deltaTime*this.mass*this.currentSpeed01*20;this._rigidbody.applyImpulse(m(0,-o,0)),this._currAcc<0&&i>.05&&r.dot(this.gameObject.worldForward)>0&&(e=this.breakForce*-this._currAcc),e+=Math.max(0,this._currBreak)*this.breakForce,this._currAcc!=0&&!s&&(t=this.accelerationForce/this.context.time.deltaTime*this._currAcc);const h=w.lerp(this.maxSteer,this.maxSteer*.5,this.currentSpeed01),S=this._currentSteer*h*w.Deg2Rad;this.wheels.forEach(u=>{u.applyPhysics(t,e,S)})}}R([n()],v.prototype,"carDrive"),R([n()],v.prototype,"mass"),R([n()],v.prototype,"maxSteer"),R([n()],v.prototype,"steerSmoothingFactor"),R([n()],v.prototype,"accelerationForce"),R([n()],v.prototype,"breakForce"),R([n()],v.prototype,"topSpeed"),R([n(c)],v.prototype,"wheels");function ne(a){const e=new Array;if(t(a.gameObject),e.length<=0){const r=a.gameObject.worldPosition,i=a.gameObject.worldQuaternion;a.gameObject.worldPosition=new j,a.gameObject.worldQuaternion=new M;const s=V(a.gameObject);a.gameObject.worldQuaternion=i,a.gameObject.worldPosition=r;const o=s.max.y-s.min.y,h=Math.max(s.max.x-s.min.x,s.max.z-s.min.z),S=o/h,u=s.getSize(new j).length()*.1,x=s.min.y;let g=(s.max.x-s.min.x)*.1,p=(s.max.z-s.min.z)*.1;S>1&&(g*=-S*1.5,p*=-S*1.5);const l=new O;l.position.set(s.min.x+g,x,s.max.z-p),l.name="WheelFrontLeft",e.push(l.addComponent(c,{axle:b.front,radius:u})),a.gameObject.add(l);const d=new O;d.position.set(s.max.x-g,x,s.max.z-p),d.name="WheelFrontRight",e.push(d.addComponent(c,{axle:b.front,radius:u})),a.gameObject.add(d);const y=new O;y.position.set(s.min.x+g,x,s.min.z+p),y.name="WheelRearLeft",e.push(y.addComponent(c,{axle:b.rear,radius:u})),a.gameObject.add(y);const _=new O;_.position.set(s.max.x-g,x,s.min.z+p),_.name="WheelRearRight",e.push(_.addComponent(c,{axle:b.rear,radius:u})),a.gameObject.add(_)}return e;function t(r){for(const i of r.children){const s=i.name.toLowerCase();if(s.includes("wheel")&&!i.getComponent(c)){const o=s.includes("front")||s.includes("fl")||s.includes("fr"),h=i.addComponent(c,{axle:o?b.front:b.rear});e.push(h)}}for(const i of r.children){if(e.length>0)break;i instanceof O&&t(i)}}}var he=Object.defineProperty,B=(a,e,t,r)=>{for(var i=void 0,s=a.length-1,o;s>=0;s--)(o=a[s])&&(i=o(e,t,i)||i);return i&&he(e,t,i),i};class C extends k{carPhysics;autoReset=!0;manualReset=!0;onReset=new W;reset(){this.carPhysics?.teleport(this.posOnStart,this.rotOnStart,!0),this.context.mainCamera.getComponent(ee)?.setCameraTargetPosition(this.camStartPos,!0),this.onReset?.invoke()}posOnStart;rotOnStart;camStartPos;start(){this.posOnStart=this.gameObject.worldPosition.clone(),this.rotOnStart=this.gameObject.worldQuaternion.clone(),this.camStartPos=this.context.mainCamera.position.clone()}onEnable(){this.carPhysics||=this.gameObject.getComponent(v),window.addEventListener("blur",this.onBlur)}onDisable(){window.removeEventListener("blur",this.onBlur)}onBeforeRender(){this.handleInput(),this.manualReset&&this.context.input.isKeyDown("r")&&this.reset(),this.autoReset&&(this.resetWhenRolledOver(),this.resetWhenFallingoff())}onBlur=e=>{if(!this.context.application.hasFocus){const t=navigator.getGamepads()?.[0];t&&t.vibrationActuator?.playEffect("dual-rumble",{startDelay:0,duration:0,weakMagnitude:1,strongMagnitude:1})}};_lastResetTime=-1;resetWhenFallingoff(){this.carPhysics&&this.carPhysics.airtime>5&&this.context.time.realtimeSinceStartup-this._lastResetTime>5&&(this._lastResetTime=this.context.time.realtimeSinceStartup,this.reset())}rolledOverDuration=0;resetWhenRolledOver(){if(!this.carPhysics)return;const e=this.gameObject.worldUp.dot(m(0,1,0))<.65,t=this.carPhysics.rigidbody.getVelocity().length()<.1;e&&t?this.rolledOverDuration+=this.context.time.deltaTime:this.rolledOverDuration=0,this.rolledOverDuration>1&&this.rescueVehicle()}async rescueVehicle(){if(!this.carPhysics)return;const e=this.gameObject.worldPosition;e.y+=1;const t=this.gameObject.worldForward;t.y=0,t.normalize();const r=F().setFromUnitVectors(m(0,0,-1),t);this.carPhysics.teleport(e,r)}_lastVehicleVelocity=0;_lastHeroRumbleTime=-1;_currentSteer=0;_currentSteerAccum=0;handleInput(){if(!this.carPhysics?.vehicle)return;let e=0,t=0,r=0;if(this.context.xr){t+=this.context.xr.rightController?.getButton("a-button")?.value||0,t-=this.context.xr.leftController?.getButton("x-button")?.value||0;const s=this.context.xr.rightController?.getButton("xr-standard-squeeze")?.value||0,o=this.context.xr.leftController?.getButton("xr-standard-squeeze")?.value||0;if(s>.5&&o>.5){const h=this.context.xr.leftController.gripPosition.y-this.context.xr.rightController.gripPosition.y;e=w.clamp(h,-2,2)}}else this.context.input.isKeyPressed("a")||this.context.input.isKeyPressed("ArrowLeft")?e-=1:(this.context.input.isKeyPressed("d")||this.context.input.isKeyPressed("ArrowRight"))&&(e+=1),(this.context.input.isKeyPressed("s")||this.context.input.isKeyPressed("ArrowDown"))&&(t-=1),(this.context.input.isKeyPressed("w")||this.context.input.isKeyPressed("ArrowUp"))&&(t+=1),this.context.input.isKeyPressed(" ")&&(r+=1);const i=navigator.getGamepads()?.[0];if(i?.connected){const s=i.axes[0],o=i.axes[1];if(Math.abs(s)>.01){const p=s<0?-1:1;e+=Math.pow(s,2)*p}Math.abs(o)>.01&&(t-=o);const h=i.buttons[0],S=i.buttons[1],u=i.buttons[6],x=i.buttons[7];(h.pressed||x.pressed)&&(t+=1),(S.pressed||u.pressed)&&(t-=1),i.buttons[2].pressed&&this.reset();const g=this.carPhysics.velocity.length();if(this.context.time.realtimeSinceStartup-this._lastHeroRumbleTime>.3){g>.01&&i.vibrationActuator?.playEffect("dual-rumble",{startDelay:0,duration:this.context.time.deltaTime,weakMagnitude:.1,strongMagnitude:.1});const p=this.carPhysics.wheels,l=200;let d=0;for(const y of p){const _=this.carPhysics.vehicle.wheelSuspensionForce(y.index);if(_&&_<l){const N=1-_/l;d=Math.max(d,N)}}if(d>0){const y=Math.pow(d,2);i.vibrationActuator?.playEffect("dual-rumble",{startDelay:0,duration:d*500,weakMagnitude:y*1,strongMagnitude:y*1})}}if(g){const p=this._lastVehicleVelocity;this._lastVehicleVelocity=g;const l=p-g;l>1&&(this._lastHeroRumbleTime=this.context.time.realtimeSinceStartup,i.vibrationActuator?.playEffect("dual-rumble",{startDelay:0,duration:150,weakMagnitude:w.clamp01(l/3),strongMagnitude:w.clamp01(l/3)}))}}e*=Math.max(.2,Math.min(1,2*Math.abs(this.carPhysics.currentSteer))),this._currentSteer=w.lerp(this._currentSteer,e,this.context.time.deltaTime/.12),this.carPhysics.steerImpulse(this._currentSteer),this.carPhysics.breakImpulse(r),this.carPhysics.accelerationImpulse(t)}}B([n(v)],C.prototype,"carPhysics"),B([n()],C.prototype,"autoReset"),B([n()],C.prototype,"manualReset"),B([n(W)],C.prototype,"onReset");var ce=Object.defineProperty,le=(a,e,t,r)=>{for(var i=void 0,s=a.length-1,o;s>=0;s--)(o=a[s])&&(i=o(e,t,i)||i);return i&&ce(e,t,i),i};class q extends k{carPhysics;steerLeftState=0;steerRightState=0;throttleState=0;breakState=0;update(){this.throttleInput(),this.steerInput()}throttleInput(){this.carPhysics?.accelerationImpulse(w.clamp(this.throttleState+this.breakState,-1,1))}steerInput(){this.carPhysics?.steerImpulse(w.clamp(this.steerLeftState+this.steerRightState,-1,1))}steerLeftPress(){this.steerLeftState=-1}steerLeftRelease(){this.steerLeftState=0}steerRightPress(){this.steerRightState=1}steerRightRelease(){this.steerRightState=0}throttlePress(){this.throttleState=1}throttleRelease(){}brakePress(){this.throttleState=0,this.breakState=-1}brakeRelease(){this.breakState=0}}le([n(v)],q.prototype,"carPhysics");var de=Object.defineProperty,G=(a,e,t,r)=>{for(var i=void 0,s=a.length-1,o;s>=0;s--)(o=a[s])&&(i=o(e,t,i)||i);return i&&de(e,t,i),i};class A extends k{cameraRig=null;cars;awake(){this.cars??=[]}start(){this.cars?.length||(this.cars=[...te.findObjectsOfType(C)]),this.cars.length>0&&this.selectCarByIndex(0)}onEnable(){this.context.input.addEventListener("keyup",this.onKey),this.context.domElement.addEventListener("click",this.onClick)}onDisable(){this.context.input.removeEventListener("keyup",this.onKey),this.context.domElement.removeEventListener("click",this.onClick)}selectCar(e){this.cars||(this.cars=[]);let t=this.cars.indexOf(e);t===-1&&(this.cars.push(e),t=this.cars.length-1),this.selectCarByIndex(t)}gamepadButtonDown=!1;update(){const e=navigator.getGamepads()?.[0];if(e)if(e.buttons?.[3]?.pressed){if(!this.gamepadButtonDown){this.gamepadButtonDown=!0;const t=this.cars.find(r=>r.activeAndEnabled);if(t){const r=((t?this.cars.indexOf(t):-1)+1)%this.cars.length;this.selectCarByIndex(r)}}}else this.gamepadButtonDown&&(this.gamepadButtonDown=!1)}onKey=e=>{const t=parseInt(e.key)-1;t>=0&&t<this.cars.length&&this.selectCarByIndex(t)};onClick=e=>{if(!this.cars?.length||e instanceof MouseEvent&&e.button!=0)return;const t=this.context.physics.raycast();if(t.length){const r=t[0]?.object.getComponentInParent(C),i=r?this.cars.indexOf(r):-1;i>=0&&this.selectCarByIndex(i)}};selectCarByIndex(e){for(const r of this.cars)r&&(r.enabled=!1);const t=this.cars[e];if(t){t.enabled=!0;const r=ie(q);r&&(r.carPhysics=t.gameObject.getComponentInChildren(v)||void 0);const i=t.gameObject.getComponentInChildren(z);if(i)this.context.setCurrentCamera(i);else if(this.cameraRig){this.context.setCurrentCamera(this.cameraRig);const s=this.cameraRig.gameObject.getComponentInParent(se);s&&(s.target=t.gameObject)}}}}G([n(z)],A.prototype,"cameraRig"),G([n(C)],A.prototype,"cars");var ue=Object.defineProperty,pe=(a,e,t,r)=>{for(var i=void 0,s=a.length-1,o;s>=0;s--)(o=a[s])&&(i=o(e,t,i)||i);return i&&ue(e,t,i),i};class H extends k{url="https://stream.laut.fm/gta-classics";_audio=null;onEnable(){this.url&&(this._audio=new Audio(this.url),this._audio.autoplay=!0,re.registerWaitForInteraction(()=>{this.enabled&&this._audio?.play()}))}onDisable(){this._audio?.pause()}}pe([n()],H.prototype,"url");export{b as CarAxle,C as CarController,I as CarDrive,v as CarPhysics,H as CarRadio,A as CarSelection,c as CarWheel,$ as SkidTrailBehaviour};