gdcore-tools 2.0.0-gd-v5.4.219-autobuild → 2.0.0-gd-v5.4.220-autobuild
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.
- package/dist/Runtime/Extensions/Physics2Behavior/JsExtension.js +19 -19
- package/dist/Runtime/Extensions/Physics2Behavior/physics2runtimebehavior.js.map +1 -1
- package/dist/Runtime/Extensions/Physics2Behavior/physics2tools.js +1 -1
- package/dist/Runtime/Extensions/Physics2Behavior/physics2tools.js.map +2 -2
- package/dist/Runtime/Extensions/Physics3DBehavior/JsExtension.js +2442 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.js +2 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.js.map +7 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/Physics3DTools.js +2 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/Physics3DTools.js.map +7 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.js +2 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.js.map +7 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/jolt-physics.d.ts +4874 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/jolt-physics.wasm.js +2 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/jolt-physics.wasm.js.map +7 -0
- package/dist/Runtime/Extensions/Physics3DBehavior/jolt-physics.wasm.wasm +0 -0
- package/dist/Runtime/Extensions/PlatformBehavior/platformerobjectruntimebehavior.js.map +2 -2
- package/dist/Runtime/Extensions/TileMap/helper/TileMapHelper.js +1 -1
- package/dist/Runtime/Extensions/TileMap/helper/TileMapHelper.js.map +1 -1
- package/dist/Runtime/RuntimeInstanceContainer.js +1 -1
- package/dist/Runtime/RuntimeInstanceContainer.js.map +2 -2
- package/dist/Runtime/pixi-renderers/pixi-image-manager.js +1 -1
- package/dist/Runtime/pixi-renderers/pixi-image-manager.js.map +2 -2
- package/dist/Runtime/pixi-renderers/runtimegame-pixi-renderer.js +1 -1
- package/dist/Runtime/pixi-renderers/runtimegame-pixi-renderer.js.map +2 -2
- package/dist/lib/libGD.cjs +1 -1
- package/dist/lib/libGD.wasm +0 -0
- package/gd.d.ts +4 -2
- package/package.json +1 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var gdjs;(function(n){const g=async()=>{try{const t=(await import("./jolt-physics.wasm.js")).default;if(!t)throw new Error("No default export found in Jolt.");const e=await t();window.Jolt=e}catch(u){throw console.error("Unable to load Jolt physics library.",u),u}};n.registerAsynchronouslyLoadingLibraryPromise(g());class b{constructor(t,e){this._tempVec3=new Jolt.Vec3;this._tempRVec3=new Jolt.RVec3;this._tempQuat=new Jolt.Quat;this.stepped=!1;this._physics3DHooks=[];this._registeredBehaviors=new Set,this.gravityX=e.gravityX,this.gravityY=e.gravityY,this.gravityZ=e.gravityZ,this.worldScale=e.worldScale,this.worldInvScale=1/this.worldScale;const i=new Jolt.JoltSettings;n.Physics3DSharedData.setupCollisionFiltering(i),this.jolt=new Jolt.JoltInterface(i),Jolt.destroy(i),this.physicsSystem=this.jolt.GetPhysicsSystem(),this.physicsSystem.SetGravity(this.getVec3(this.gravityX,this.gravityY,this.gravityZ)),this.bodyInterface=this.physicsSystem.GetBodyInterface(),this.contactListener=new Jolt.ContactListenerJS,this.physicsSystem.SetContactListener(this.contactListener),this.contactListener.OnContactAdded=(s,o,a,h)=>{const d=Jolt.wrapPointer(s,Jolt.Body),l=Jolt.wrapPointer(o,Jolt.Body),r=d.gdjsAssociatedBehavior,f=l.gdjsAssociatedBehavior;!r||!f||(r.onContactBegin(f),f.onContactBegin(r))},this.contactListener.OnContactRemoved=s=>{const o=Jolt.wrapPointer(s,Jolt.SubShapeIDPair),a=this.physicsSystem.GetBodyLockInterface(),h=a.TryGetBody(o.GetBody1ID()),d=a.TryGetBody(o.GetBody2ID()),l=h.gdjsAssociatedBehavior,r=d.gdjsAssociatedBehavior;!l||!r||(l.onContactEnd(r),r.onContactEnd(l))},this.contactListener.OnContactPersisted=(s,o,a,h)=>{},this.contactListener.OnContactValidate=(s,o,a,h)=>Jolt.ValidateResult_AcceptAllContactsForThisBodyPair}getVec3(t,e,i){const s=this._tempVec3;return s.Set(t,e,i),s}getRVec3(t,e,i){const s=this._tempRVec3;return s.Set(t,e,i),s}getQuat(t,e,i,s){const o=this._tempQuat;return o.Set(t,e,i,s),o}static getSharedData(t,e){if(!t.physics3DSharedData){const i=t.getInitialSharedDataForBehavior(e);t.physics3DSharedData=new n.Physics3DSharedData(t,i)}return t.physics3DSharedData}static setupCollisionFiltering(t){const e=new Jolt.ObjectLayerPairFilterMask,i=new Jolt.BroadPhaseLayer(n.Physics3DSharedData.staticBroadPhaseLayerIndex),s=new Jolt.BroadPhaseLayer(n.Physics3DSharedData.dynamicBroadPhaseLayerIndex),o=new Jolt.BroadPhaseLayerInterfaceMask(2);o.ConfigureLayer(i,n.Physics3DSharedData.staticLayersMask,0),o.ConfigureLayer(s,n.Physics3DSharedData.dynamicLayersMask,0),Jolt.destroy(i),Jolt.destroy(s),t.mObjectLayerPairFilter=e,t.mBroadPhaseLayerInterface=o,t.mObjectVsBroadPhaseLayerFilter=new Jolt.ObjectVsBroadPhaseLayerFilterMask(o)}addToBehaviorsList(t){this._registeredBehaviors.add(t)}removeFromBehaviorsList(t){this._registeredBehaviors.delete(t)}step(t){for(const i of this._registeredBehaviors)i._contactsStartedThisFrame.length=0,i._contactsEndedThisFrame.length=0;for(const i of this._registeredBehaviors)i.updateBodyFromObject();for(const i of this._physics3DHooks)i.doBeforePhysicsStep(t);const e=t>1/55?2:1;this.jolt.Step(t,e),this.stepped=!0;for(const i of this._registeredBehaviors)i.updateObjectFromBody()}registerHook(t){this._physics3DHooks.push(t)}}b.staticLayersMask=15,b.dynamicLayersMask=240,b.allLayersMask=255,b.staticBroadPhaseLayerIndex=1,b.dynamicBroadPhaseLayerIndex=1,n.Physics3DSharedData=b,n.registerRuntimeSceneUnloadedCallback(function(u){const t=u.physics3DSharedData;t&&(Jolt.destroy(t.jolt),Jolt.destroy(t.contactListener),Jolt.destroy(t._tempVec3),Jolt.destroy(t._tempRVec3),Jolt.destroy(t._tempQuat),u.physics3DSharedData=null)});class p extends n.RuntimeBehavior{constructor(t,e,i){super(t,e,i);this.shapeScale=1;this._contactsStartedThisFrame=[];this._contactsEndedThisFrame=[];this._currentContacts=[];this._body=null;this._needToRecreateBody=!1;this._needToRecreateShape=!1;this._shapeHalfDepth=0;this._objectOldX=0;this._objectOldY=0;this._objectOldZ=0;this._objectOldRotationX=0;this._objectOldRotationY=0;this._objectOldRotationZ=0;this._objectOldWidth=0;this._objectOldHeight=0;this._objectOldDepth=0;this.bodyUpdater=new n.Physics3DRuntimeBehavior.DefaultBodyUpdater(this),this.owner3D=i,this.bodyType=e.bodyType,this.bullet=e.bullet,this.fixedRotation=e.fixedRotation,this.shape=e.shape,this.shapeOrientation=e.shapeOrientation,this.shapeDimensionA=e.shapeDimensionA,this.shapeDimensionB=e.shapeDimensionB,this.shapeDimensionC=e.shapeDimensionC,this.density=e.density,this.friction=e.friction,this.restitution=e.restitution,this.linearDamping=Math.max(0,e.linearDamping),this.angularDamping=Math.max(0,e.angularDamping),this.gravityScale=e.gravityScale,this.layers=e.layers,this.masks=e.masks,this._destroyedDuringFrameLogic=!1,this._sharedData=b.getSharedData(t.getScene(),e.name),this._sharedData.addToBehaviorsList(this)}getVec3(t,e,i){const s=this._sharedData._tempVec3;return s.Set(t,e,i),s}getRVec3(t,e,i){const s=this._sharedData._tempRVec3;return s.Set(t,e,i),s}getQuat(t,e,i,s){const o=this._sharedData._tempQuat;return o.Set(t,e,i,s),o}updateFromBehaviorData(t,e){return t.bullet!==e.bullet&&this.setBullet(e.bullet),t.fixedRotation!==e.fixedRotation&&this.setFixedRotation(e.fixedRotation),t.shapeDimensionA!==e.shapeDimensionA&&(this.shapeDimensionA=e.shapeDimensionA,this._needToRecreateShape=!0),t.shapeDimensionB!==e.shapeDimensionB&&(this.shapeDimensionB=e.shapeDimensionB,this._needToRecreateShape=!0),t.density!==e.density&&this.setDensity(e.density),t.friction!==e.friction&&this.setFriction(e.friction),t.restitution!==e.restitution&&this.setRestitution(e.restitution),t.linearDamping!==e.linearDamping&&this.setLinearDamping(e.linearDamping),t.angularDamping!==e.angularDamping&&this.setAngularDamping(e.angularDamping),t.gravityScale!==e.gravityScale&&this.setGravityScale(e.gravityScale),!(t.layers!==e.layers||t.masks!==e.masks||t.vertices!==e.vertices||t.bodyType!==e.bodyType||t.shape!==e.shape)}getNetworkSyncData(){let t;if(this._body){const e=this._body.GetPosition(),i=this._body.GetRotation(),s=this._body.GetLinearVelocity(),o=this._body.GetAngularVelocity();t={px:e.GetX(),py:e.GetY(),pz:e.GetZ(),rx:i.GetX(),ry:i.GetY(),rz:i.GetZ(),rw:i.GetW(),lvx:s.GetX(),lvy:s.GetY(),lvz:s.GetZ(),avx:o.GetX(),avy:o.GetY(),avz:o.GetZ(),aw:this._body.IsActive()}}else t={px:void 0,py:void 0,pz:void 0,rx:void 0,ry:void 0,rz:void 0,rw:void 0,lvx:void 0,lvy:void 0,lvz:void 0,avx:void 0,avy:void 0,avz:void 0,aw:void 0};return{...super.getNetworkSyncData(),props:{...t,layers:this.layers,masks:this.masks}}}updateFromNetworkSyncData(t){super.updateFromNetworkSyncData(t);const e=t.props;e.px!==void 0&&e.py!==void 0&&e.pz!==void 0&&this._body&&this._sharedData.bodyInterface.SetPosition(this._body.GetID(),this.getVec3(e.px,e.py,e.pz),Jolt.EActivation_DontActivate),e.rx!==void 0&&e.ry!==void 0&&e.rz!==void 0&&e.rw!==void 0&&this._body&&this._sharedData.bodyInterface.SetRotation(this._body.GetID(),this.getQuat(e.rx,e.ry,e.rz,e.rw),Jolt.EActivation_DontActivate),e.lvx!==void 0&&e.lvy!==void 0&&e.lvz!==void 0&&this._body&&this._sharedData.bodyInterface.SetLinearVelocity(this._body.GetID(),this.getVec3(e.lvx,e.lvy,e.lvz)),e.avx!==void 0&&e.avy!==void 0&&e.avz!==void 0&&this._body&&this._sharedData.bodyInterface.SetAngularVelocity(this._body.GetID(),this.getVec3(e.avx,e.avy,e.avz)),e.layers!==void 0&&(this.layers=e.layers),e.masks!==void 0&&(this.masks=e.masks)}onDeActivate(){this._sharedData.removeFromBehaviorsList(this),this._body!==null&&(this._sharedData.bodyInterface.RemoveBody(this._body.GetID()),this._sharedData.bodyInterface.DestroyBody(this._body.GetID()),this._body=null),this._contactsEndedThisFrame.length=0,this._contactsStartedThisFrame.length=0,this._currentContacts.length=0}onActivate(){this._sharedData.addToBehaviorsList(this),this._contactsEndedThisFrame.length=0,this._contactsStartedThisFrame.length=0,this._currentContacts.length=0,this.updateBodyFromObject()}onDestroy(){this._destroyedDuringFrameLogic=!0,this.onDeActivate()}createShape(){let t=this.owner3D.getWidth()*this._sharedData.worldInvScale,e=this.owner3D.getHeight()*this._sharedData.worldInvScale,i=this.owner3D.getDepth()*this._sharedData.worldInvScale;if(this.shapeOrientation==="X"){const c=i;i=t,t=c}else if(this.shapeOrientation==="Y"){const c=i;i=e,e=c}const s=this.shapeScale*this._sharedData.worldInvScale,o=this.shapeDimensionA*s,a=this.shapeDimensionB*s,h=this.shapeDimensionC*s,d=this._sharedData.worldInvScale;let l,r;if(this.shape==="Box"){const c=o>0?o:t>0?t:d,y=a>0?a:e>0?e:d,_=h>0?h:i>0?i:d,D=Math.min(d,Math.min(c,y,_)/4);l=new Jolt.BoxShapeSettings(this.getVec3(c/2,y/2,_/2),D),r=this.getQuat(0,0,0,1),this._shapeHalfDepth=_/2}else if(this.shape==="Capsule"){const c=o>0?o:t>0?Math.sqrt(t*e)/2:d,y=a>0?a:i>0?i:d;l=new Jolt.CapsuleShapeSettings(Math.max(0,y/2-c),c),r=this._getShapeOrientationQuat(),this._shapeHalfDepth=this.shapeOrientation!=="Z"?c:y/2}else if(this.shape==="Cylinder"){const c=o>0?o:t>0?Math.sqrt(t*e)/2:d,y=a>0?a:i>0?i:d,_=Math.min(d,Math.min(y,c)/4);l=new Jolt.CylinderShapeSettings(y/2,c,_),r=this._getShapeOrientationQuat(),this._shapeHalfDepth=this.shapeOrientation!=="Z"?c:y/2}else{const c=o>0?o:t>0?Math.pow(t*e*i,1/3)/2:d;l=new Jolt.SphereShapeSettings(c),r=this.getQuat(0,0,0,1),this._shapeHalfDepth=c}l.mDensity=this.density;const f=new Jolt.RotatedTranslatedShapeSettings(this.getVec3(0,0,0),r,l).Create().Get();return Jolt.destroy(l),f}_getShapeOrientationQuat(){return this.shapeOrientation==="X"?this.getQuat(0,0,Math.sqrt(2)/2,-Math.sqrt(2)/2):this.shapeOrientation==="Y"?this.getQuat(0,0,0,1):this.getQuat(Math.sqrt(2)/2,0,0,Math.sqrt(2)/2)}_recreateShape(){this.bodyUpdater.recreateShape(),this._objectOldWidth=this.owner3D.getWidth(),this._objectOldHeight=this.owner3D.getHeight(),this._objectOldDepth=this.owner3D.getDepth()}getShapeScale(){return this.shapeScale}setShapeScale(t){t!==this.shapeScale&&t>0&&(this.shapeScale=t,this._needToRecreateShape=!0)}getBody(){return this._body===null&&this._createBody(),this._body}_createBody(){return this._needToRecreateBody=!1,this._needToRecreateShape=!1,!this.activated()||this._destroyedDuringFrameLogic?!1:(this._body=this.bodyUpdater.createAndAddBody(),this._body.gdjsAssociatedBehavior=this,this._objectOldWidth=this.owner3D.getWidth(),this._objectOldHeight=this.owner3D.getHeight(),this._objectOldDepth=this.owner3D.getDepth(),!0)}getBodyLayer(){return Jolt.ObjectLayerPairFilterMask.prototype.sGetObjectLayer(this.bodyType==="Static"?this.layers&n.Physics3DSharedData.staticLayersMask:this.layers&n.Physics3DSharedData.dynamicLayersMask,this.bodyType==="Static"?n.Physics3DSharedData.allLayersMask:this.masks)}doStepPreEvents(t){!this._sharedData.stepped&&!t.getScene().getTimeManager().isFirstFrame()&&this._sharedData.step(t.getScene().getTimeManager().getElapsedTime()/1e3)}doStepPostEvents(t){this._sharedData.stepped=!1}onObjectHotReloaded(){this.updateBodyFromObject()}recreateBody(){if(!this._body){this._createBody();return}const t=this._sharedData.bodyInterface,e=this._body.GetLinearVelocity(),i=e.GetX(),s=e.GetY(),o=e.GetZ(),a=this._body.GetAngularVelocity(),h=a.GetX(),d=a.GetY(),l=a.GetZ();let r=this._body.GetID();t.RemoveBody(r),t.DestroyBody(r),this._contactsEndedThisFrame.length=0,this._contactsStartedThisFrame.length=0,this._currentContacts.length=0,this._createBody(),!!this._body&&(r=this._body.GetID(),t.SetLinearVelocity(r,this.getVec3(i,s,o)),t.SetAngularVelocity(r,this.getVec3(h,d,l)))}updateObjectFromBody(){this.bodyUpdater.updateObjectFromBody(),this._objectOldX=this.owner3D.getX(),this._objectOldY=this.owner3D.getY(),this._objectOldZ=this.owner3D.getZ(),this._objectOldRotationX=this.owner3D.getRotationX(),this._objectOldRotationY=this.owner3D.getRotationY(),this._objectOldRotationZ=this.owner3D.getAngle()}updateBodyFromObject(){this._body===null&&!this._createBody()||(this._needToRecreateBody&&this.recreateBody(),(this._needToRecreateShape||!this.hasCustomShapeDimension()&&(this._objectOldWidth!==this.owner3D.getWidth()||this._objectOldHeight!==this.owner3D.getHeight()||this._objectOldDepth!==this.owner3D.getDepth()))&&(this._needToRecreateShape=!1,this._recreateShape()),this.bodyUpdater.updateBodyFromObject())}hasCustomShapeDimension(){return this.shapeDimensionA>0||this.shapeDimensionB>0||this.shapeDimensionC>0}getPhysicsPosition(t){return t.Set(this.owner3D.getCenterXInScene()*this._sharedData.worldInvScale,this.owner3D.getCenterYInScene()*this._sharedData.worldInvScale,this.owner3D.getCenterZInScene()*this._sharedData.worldInvScale),t}getPhysicsRotation(t){const e=this.owner3D.get3DRendererObject();return t.Set(e.quaternion.x,e.quaternion.y,e.quaternion.z,e.quaternion.w),t}moveObjectToPhysicsPosition(t){this.owner3D.setCenterXInScene(t.GetX()*this._sharedData.worldScale),this.owner3D.setCenterYInScene(t.GetY()*this._sharedData.worldScale),this.owner3D.setCenterZInScene(t.GetZ()*this._sharedData.worldScale)}moveObjectToPhysicsRotation(t){const e=this.owner3D.get3DRendererObject();e.quaternion.x=t.GetX(),e.quaternion.y=t.GetY(),e.quaternion.z=t.GetZ(),e.quaternion.w=t.GetW();const i=new THREE.Euler(0,0,0,"ZYX");i.setFromQuaternion(e.quaternion),this.owner3D.setRotationX(n.toDegrees(i.x)),this.owner3D.setRotationY(n.toDegrees(i.y)),this.owner3D.setAngle(n.toDegrees(i.z))}getWorldScale(){return this._sharedData.worldScale}getGravityX(){return this._sharedData.gravityX}getGravityY(){return this._sharedData.gravityY}getGravityZ(){return this._sharedData.gravityZ}setGravityX(t){this._sharedData.gravityX!==t&&(this._sharedData.gravityX=t,this._sharedData.physicsSystem.SetGravity(this.getVec3(this._sharedData.gravityX,this._sharedData.gravityY,this._sharedData.gravityZ)))}setGravityY(t){this._sharedData.gravityX!==t&&(this._sharedData.gravityX=t,this._sharedData.physicsSystem.SetGravity(this.getVec3(this._sharedData.gravityX,this._sharedData.gravityY,this._sharedData.gravityZ)))}setGravityZ(t){this._sharedData.gravityX!==t&&(this._sharedData.gravityZ=t,this._sharedData.physicsSystem.SetGravity(this.getVec3(this._sharedData.gravityX,this._sharedData.gravityY,this._sharedData.gravityZ)))}isDynamic(){return this.bodyType==="Dynamic"}isStatic(){return this.bodyType==="Static"}isKinematic(){return this.bodyType==="Kinematic"}isBullet(){return this.bullet}setBullet(t){if(this.bullet===t||(this.bullet=t,this._body===null&&!this._createBody()))return;const e=this._body;this._sharedData.bodyInterface.SetMotionQuality(e.GetID(),this.bullet?Jolt.EMotionQuality_LinearCast:Jolt.EMotionQuality_Discrete)}hasFixedRotation(){return this.fixedRotation}setFixedRotation(t){this.fixedRotation!==t&&(this.fixedRotation=t,this._needToRecreateBody=!0)}getDensity(){return this.density}setDensity(t){t<0&&(t=0),this.density!==t&&(this.density=t,this._needToRecreateShape=!0)}getFriction(){return this.friction}setFriction(t){if(t<0&&(t=0),this.friction===t||(this.friction=t,this._body===null&&!this._createBody()))return;const e=this._body;this._sharedData.bodyInterface.SetFriction(e.GetID(),t)}getRestitution(){return this.restitution}setRestitution(t){if(t<0&&(t=0),this.restitution===t||(this.restitution=t,this._body===null&&!this._createBody()))return;const e=this._body;this._sharedData.bodyInterface.SetRestitution(e.GetID(),t)}getLinearDamping(){return this.linearDamping}setLinearDamping(t){if(t<0&&(t=0),this.linearDamping===t||(this.linearDamping=t,this._body===null&&!this._createBody()))return;this._body.GetMotionProperties().SetLinearDamping(t)}getAngularDamping(){return this.angularDamping}setAngularDamping(t){if(t<0&&(t=0),this.angularDamping===t||(this.angularDamping=t,this._body===null&&!this._createBody()))return;this._body.GetMotionProperties().SetAngularDamping(t)}getGravityScale(){return this.gravityScale}setGravityScale(t){if(this.gravityScale===t||(this.gravityScale=t,this._body===null&&!this._createBody()))return;this._body.GetMotionProperties().SetGravityFactor(t)}layerEnabled(t){return t=Math.floor(t),t<1||t>8?!1:!!(this.layers&1<<t-1)}enableLayer(t,e){t=Math.floor(t),!(t<1||t>8)&&(e?this.layers|=1<<t-1:this.layers&=~(1<<t-1),this._needToRecreateBody=!0)}maskEnabled(t){return t=Math.floor(t),t<1||t>16?!1:!!(this.masks&1<<t-1)}enableMask(t,e){t=Math.floor(t),!(t<1||t>16)&&(e?this.masks|=1<<t-1:this.masks&=~(1<<t-1),this._needToRecreateBody=!0)}getLinearVelocityX(){return this._body===null&&!this._createBody()?0:this._body.GetLinearVelocity().GetX()*this._sharedData.worldScale}setLinearVelocityX(t){if(this._body===null&&!this._createBody())return;const e=this._body;this._sharedData.bodyInterface.SetLinearVelocity(e.GetID(),this.getVec3(t*this._sharedData.worldInvScale,e.GetLinearVelocity().GetY(),e.GetLinearVelocity().GetZ()))}getLinearVelocityY(){return this._body===null&&!this._createBody()?0:this._body.GetLinearVelocity().GetY()*this._sharedData.worldScale}setLinearVelocityY(t){if(this._body===null&&!this._createBody())return;const e=this._body;this._sharedData.bodyInterface.SetLinearVelocity(e.GetID(),this.getVec3(e.GetLinearVelocity().GetX(),t*this._sharedData.worldInvScale,e.GetLinearVelocity().GetZ()))}getLinearVelocityZ(){return this._body===null&&!this._createBody()?0:this._body.GetLinearVelocity().GetZ()*this._sharedData.worldScale}setLinearVelocityZ(t){if(this._body===null&&!this._createBody())return;const e=this._body;this._sharedData.bodyInterface.SetLinearVelocity(e.GetID(),this.getVec3(e.GetLinearVelocity().GetX(),e.GetLinearVelocity().GetY(),t*this._sharedData.worldInvScale))}getLinearVelocityLength(){return this._body===null&&!this._createBody()?0:this._body.GetLinearVelocity().Length()*this._sharedData.worldScale}getAngularVelocityX(){if(this._body===null&&!this._createBody())return 0;const t=this._body;return n.toDegrees(t.GetAngularVelocity().GetX())}setAngularVelocityX(t){if(this._body===null&&!this._createBody())return;const e=this._body;this._sharedData.bodyInterface.SetAngularVelocity(e.GetID(),this.getVec3(n.toRad(t),e.GetAngularVelocity().GetY(),e.GetAngularVelocity().GetZ()))}getAngularVelocityY(){if(this._body===null&&!this._createBody())return 0;const t=this._body;return n.toDegrees(t.GetAngularVelocity().GetY())}setAngularVelocityY(t){if(this._body===null&&!this._createBody())return;const e=this._body;this._sharedData.bodyInterface.SetAngularVelocity(e.GetID(),this.getVec3(e.GetAngularVelocity().GetX(),n.toRad(t),e.GetAngularVelocity().GetZ()))}getAngularVelocityZ(){if(this._body===null&&!this._createBody())return 0;const t=this._body;return n.toDegrees(t.GetAngularVelocity().GetZ())}setAngularVelocityZ(t){if(this._body===null&&!this._createBody())return;const e=this._body;this._sharedData.bodyInterface.SetAngularVelocity(e.GetID(),this.getVec3(e.GetAngularVelocity().GetX(),e.GetAngularVelocity().GetY(),n.toRad(t)))}applyForce(t,e,i,s,o,a){if(this._body===null&&!this._createBody())return;const h=this._body;this._sharedData.bodyInterface.AddForce(h.GetID(),this.getVec3(t,e,i),this.getRVec3(s*this._sharedData.worldInvScale,o*this._sharedData.worldInvScale,a*this._sharedData.worldInvScale),Jolt.EActivation_Activate)}applyForceAtCenter(t,e,i){if(this._body===null&&!this._createBody())return;const s=this._body;this._sharedData.bodyInterface.AddForce(s.GetID(),this.getVec3(t,e,i),Jolt.EActivation_Activate)}applyForceTowardPosition(t,e,i,s){if(this._body===null&&!this._createBody())return;const o=this._body,a=e-o.GetPosition().GetX(),h=i-o.GetPosition().GetY(),d=s-o.GetPosition().GetZ(),l=a*a+h*h+d*d;if(l===0)return;const r=t/l;this._sharedData.bodyInterface.AddForce(o.GetID(),this.getVec3(a*r,h*r,d*r),Jolt.EActivation_Activate)}applyImpulse(t,e,i,s,o,a){if(this._body===null&&!this._createBody())return;const h=this._body;this._sharedData.bodyInterface.AddImpulse(h.GetID(),this.getVec3(t,e,i),this.getRVec3(s*this._sharedData.worldInvScale,o*this._sharedData.worldInvScale,a*this._sharedData.worldInvScale))}applyImpulseAtCenter(t,e,i){if(this._body===null&&!this._createBody())return;const s=this._body;this._sharedData.bodyInterface.AddImpulse(s.GetID(),this.getVec3(t,e,i))}applyImpulseTowardPosition(t,e,i,s,o,a,h){if(this._body===null&&!this._createBody())return;const d=this._body,l=e-o,r=i-a,f=s-h,c=l*l+r*r+f*f;if(c===0)return;const y=t/c;this._sharedData.bodyInterface.AddImpulse(d.GetID(),this.getVec3(l*y,r*y,f*y),this.getRVec3(o*this._sharedData.worldInvScale,a*this._sharedData.worldInvScale,h*this._sharedData.worldInvScale))}applyTorque(t,e,i){if(this._body===null&&!this._createBody())return;const s=this._body;this._sharedData.bodyInterface.AddTorque(s.GetID(),this.getVec3(n.toRad(t),n.toRad(e),n.toRad(i)),Jolt.EActivation_Activate)}applyAngularImpulse(t,e,i){if(this._body===null&&!this._createBody())return;const s=this._body;this._sharedData.bodyInterface.AddAngularImpulse(s.GetID(),this.getVec3(n.toRad(t),n.toRad(e),n.toRad(i)))}getMass(){if(this._body===null&&!this._createBody())return 0;const t=this._body;return 1/t.GetMotionProperties().GetInverseMass()}getInertiaAroundX(){if(this._body===null&&!this._createBody())return 0;const t=this._body;return 1/t.GetMotionProperties().GetInverseInertiaDiagonal().GetX()}getInertiaAroundY(){if(this._body===null&&!this._createBody())return 0;const t=this._body;return 1/t.GetMotionProperties().GetInverseInertiaDiagonal().GetY()}getInertiaAroundZ(){if(this._body===null&&!this._createBody())return 0;const t=this._body;return 1/t.GetMotionProperties().GetInverseInertiaDiagonal().GetZ()}getMassCenterX(){return this._body===null&&!this._createBody()?0:this._body.GetCenterOfMassPosition().GetX()*this._sharedData.worldScale}getMassCenterY(){return this._body===null&&!this._createBody()?0:this._body.GetCenterOfMassPosition().GetY()*this._sharedData.worldScale}getMassCenterZ(){return this._body===null&&!this._createBody()?0:this._body.GetCenterOfMassPosition().GetZ()*this._sharedData.worldScale}onContactBegin(t){this._currentContacts.push(t);let e=this._contactsEndedThisFrame.indexOf(t);e!==-1?this._contactsEndedThisFrame.splice(e,1):this._contactsStartedThisFrame.push(t)}onContactEnd(t){this._contactsEndedThisFrame.push(t);const e=this._currentContacts.indexOf(t);e!==-1&&this._currentContacts.splice(e,1)}static areObjectsColliding(t,e,i){const s=t.getBehavior(i);return s?!!(s._currentContacts.some(o=>o.owner===e)||s._contactsStartedThisFrame.some(o=>o.owner===e)):!1}static hasCollisionStartedBetween(t,e,i){const s=t.getBehavior(i);return s?s._contactsStartedThisFrame.some(o=>o.owner===e):!1}static hasCollisionStoppedBetween(t,e,i){const s=t.getBehavior(i);return s?s._contactsEndedThisFrame.some(o=>o.owner===e):!1}}n.Physics3DRuntimeBehavior=p,n.registerBehavior("Physics3D::Physics3DBehavior",n.Physics3DRuntimeBehavior),function(t){class u{constructor(i){this.behavior=i}createAndAddBody(){const{behavior:i}=this,{_sharedData:s}=i,o=i.createShape(),a=new Jolt.BodyCreationSettings(o,i.getPhysicsPosition(s.getRVec3(0,0,0)),i.getPhysicsRotation(s.getQuat(0,0,0,1)),i.bodyType==="Static"?Jolt.EMotionType_Static:i.bodyType==="Kinematic"?Jolt.EMotionType_Kinematic:Jolt.EMotionType_Dynamic,i.getBodyLayer());a.mMotionQuality=i.bullet?Jolt.EMotionQuality_LinearCast:Jolt.EMotionQuality_Discrete,a.mAllowedDOFs=i.fixedRotation?Jolt.EAllowedDOFs_TranslationX|Jolt.EAllowedDOFs_TranslationY|Jolt.EAllowedDOFs_TranslationZ:Jolt.EAllowedDOFs_All,a.mFriction=i.friction,a.mRestitution=i.restitution,a.mLinearDamping=i.linearDamping,a.mAngularDamping=i.angularDamping,a.mGravityFactor=i.gravityScale;const h=s.bodyInterface,d=h.CreateBody(a);return Jolt.destroy(a),h.AddBody(d.GetID(),Jolt.EActivation_Activate),d}updateObjectFromBody(){const{behavior:i}=this,{_body:s}=i;s!==null&&(i.moveObjectToPhysicsPosition(s.GetPosition()),i.moveObjectToPhysicsRotation(s.GetRotation()))}updateBodyFromObject(){const{behavior:i}=this,{owner3D:s,_sharedData:o}=i;if(i._body===null&&!i._createBody())return;const a=i._body;(this.behavior._objectOldX!==s.getX()||this.behavior._objectOldY!==s.getY()||this.behavior._objectOldZ!==s.getZ()||this.behavior._objectOldRotationX!==s.getRotationX()||this.behavior._objectOldRotationY!==s.getRotationY()||this.behavior._objectOldRotationZ!==s.getAngle())&&o.bodyInterface.SetPositionAndRotationWhenChanged(a.GetID(),this.behavior.getPhysicsPosition(o.getRVec3(0,0,0)),this.behavior.getPhysicsRotation(o.getQuat(0,0,0,1)),Jolt.EActivation_Activate)}recreateShape(){const{behavior:i}=this,{_sharedData:s}=i;if(i._body===null&&!i._createBody())return;const o=i._body;s.bodyInterface.SetShape(o.GetID(),i.createShape(),!0,Jolt.EActivation_Activate)}}t.DefaultBodyUpdater=u}(p=n.Physics3DRuntimeBehavior||(n.Physics3DRuntimeBehavior={}))})(gdjs||(gdjs={}));
|
|
2
|
+
//# sourceMappingURL=Physics3DRuntimeBehavior.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../GDevelop/Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.ts"],
|
|
4
|
+
"sourcesContent": ["/// <reference path=\"./jolt-physics.d.ts\" />\n\nnamespace Jolt {\n export interface Body {\n gdjsAssociatedBehavior: gdjs.Physics3DRuntimeBehavior | null;\n }\n}\n\nnamespace gdjs {\n const loadJolt = async () => {\n try {\n const module = await import('./jolt-physics.wasm.js');\n const initializeJoltPhysics = module.default;\n if (!initializeJoltPhysics) {\n throw new Error('No default export found in Jolt.');\n }\n\n const Jolt = await initializeJoltPhysics();\n window.Jolt = Jolt;\n } catch (err) {\n console.error('Unable to load Jolt physics library.', err);\n throw err;\n }\n };\n gdjs.registerAsynchronouslyLoadingLibraryPromise(loadJolt());\n\n export interface RuntimeScene {\n physics3DSharedData: gdjs.Physics3DSharedData | null;\n }\n interface Physics3DNetworkSyncDataType {\n px: number | undefined;\n py: number | undefined;\n pz: number | undefined;\n rx: number | undefined;\n ry: number | undefined;\n rz: number | undefined;\n rw: number | undefined;\n lvx: number | undefined;\n lvy: number | undefined;\n lvz: number | undefined;\n avx: number | undefined;\n avy: number | undefined;\n avz: number | undefined;\n aw: boolean | undefined;\n layers: number;\n masks: number;\n }\n\n export interface Physics3DNetworkSyncData extends BehaviorNetworkSyncData {\n props: Physics3DNetworkSyncDataType;\n }\n\n export class Physics3DSharedData {\n gravityX: float;\n gravityY: float;\n gravityZ: float;\n worldScale: float;\n worldInvScale: float;\n\n jolt: Jolt.JoltInterface;\n physicsSystem: Jolt.PhysicsSystem;\n bodyInterface: Jolt.BodyInterface;\n /** Contact listener to keep track of current collisions */\n contactListener: Jolt.ContactListenerJS;\n /** Avoid creating new vectors all the time */\n _tempVec3 = new Jolt.Vec3();\n _tempRVec3 = new Jolt.RVec3();\n _tempQuat = new Jolt.Quat();\n\n stepped: boolean = false;\n /**\n * List of physics behavior in the runtimeScene. It should be updated\n * when a new physics object is created (constructor), on destruction (onDestroy),\n * on behavior activation (onActivate) and on behavior deactivation (onDeActivate).\n */\n _registeredBehaviors: Set<Physics3DRuntimeBehavior>;\n\n private _physics3DHooks: Array<\n gdjs.Physics3DRuntimeBehavior.Physics3DHook\n > = [];\n\n constructor(instanceContainer: gdjs.RuntimeInstanceContainer, sharedData) {\n this._registeredBehaviors = new Set<Physics3DRuntimeBehavior>();\n this.gravityX = sharedData.gravityX;\n this.gravityY = sharedData.gravityY;\n this.gravityZ = sharedData.gravityZ;\n this.worldScale = sharedData.worldScale;\n this.worldInvScale = 1 / this.worldScale;\n\n // Initialize Jolt\n const settings = new Jolt.JoltSettings();\n gdjs.Physics3DSharedData.setupCollisionFiltering(settings);\n this.jolt = new Jolt.JoltInterface(settings);\n Jolt.destroy(settings);\n this.physicsSystem = this.jolt.GetPhysicsSystem();\n this.physicsSystem.SetGravity(\n this.getVec3(this.gravityX, this.gravityY, this.gravityZ)\n );\n this.bodyInterface = this.physicsSystem.GetBodyInterface();\n\n this.contactListener = new Jolt.ContactListenerJS();\n this.physicsSystem.SetContactListener(this.contactListener);\n this.contactListener.OnContactAdded = (\n bodyPtrA: number,\n bodyPtrB: number,\n manifoldPtr: number,\n settingsPtr: number\n ): void => {\n const bodyA = Jolt.wrapPointer(bodyPtrA, Jolt.Body);\n const bodyB = Jolt.wrapPointer(bodyPtrB, Jolt.Body);\n\n const behaviorA = bodyA.gdjsAssociatedBehavior;\n const behaviorB = bodyB.gdjsAssociatedBehavior;\n if (!behaviorA || !behaviorB) {\n return;\n }\n\n behaviorA.onContactBegin(behaviorB);\n behaviorB.onContactBegin(behaviorA);\n };\n this.contactListener.OnContactRemoved = (\n subShapePairPtr: number\n ): void => {\n const subShapePair = Jolt.wrapPointer(\n subShapePairPtr,\n Jolt.SubShapeIDPair\n );\n\n // This is ok because bodies are not deleted during the Physics step.\n const bodyLockInterface = this.physicsSystem.GetBodyLockInterface();\n const bodyA = bodyLockInterface.TryGetBody(subShapePair.GetBody1ID());\n const bodyB = bodyLockInterface.TryGetBody(subShapePair.GetBody2ID());\n\n const behaviorA = bodyA.gdjsAssociatedBehavior;\n const behaviorB = bodyB.gdjsAssociatedBehavior;\n if (!behaviorA || !behaviorB) {\n return;\n }\n\n behaviorA.onContactEnd(behaviorB);\n behaviorB.onContactEnd(behaviorA);\n };\n this.contactListener.OnContactPersisted = (\n bodyPtrA: number,\n bodyPtrB: number,\n manifoldPtr: number,\n settingsPtr: number\n ): void => {\n // TODO we could rely on this event.\n };\n this.contactListener.OnContactValidate = (\n bodyPtrA: number,\n bodyPtrB: number,\n inBaseOffset: number,\n inCollisionResult: number\n ): number => {\n return Jolt.ValidateResult_AcceptAllContactsForThisBodyPair;\n };\n }\n\n getVec3(x: float, y: float, z: float): Jolt.Vec3 {\n const tempVec3 = this._tempVec3;\n tempVec3.Set(x, y, z);\n return tempVec3;\n }\n\n getRVec3(x: float, y: float, z: float): Jolt.RVec3 {\n const tempRVec3 = this._tempRVec3;\n tempRVec3.Set(x, y, z);\n return tempRVec3;\n }\n\n getQuat(x: float, y: float, z: float, w: float): Jolt.Quat {\n const tempQuat = this._tempQuat;\n tempQuat.Set(x, y, z, w);\n return tempQuat;\n }\n\n static getSharedData(\n runtimeScene: gdjs.RuntimeScene,\n behaviorName: string\n ): gdjs.Physics3DSharedData {\n if (!runtimeScene.physics3DSharedData) {\n const initialData = runtimeScene.getInitialSharedDataForBehavior(\n behaviorName\n );\n runtimeScene.physics3DSharedData = new gdjs.Physics3DSharedData(\n runtimeScene,\n initialData\n );\n }\n return runtimeScene.physics3DSharedData;\n }\n\n // There are 4 bits for static layers and 4 bits for dynamic layers.\n static readonly staticLayersMask = 0x0f;\n static readonly dynamicLayersMask = 0xf0;\n static readonly allLayersMask = 0xff;\n static readonly staticBroadPhaseLayerIndex = 1;\n static readonly dynamicBroadPhaseLayerIndex = 1;\n\n private static setupCollisionFiltering(settings: Jolt.JoltSettings): void {\n const objectFilter = new Jolt.ObjectLayerPairFilterMask();\n const staticBroadPhaseLayer = new Jolt.BroadPhaseLayer(\n gdjs.Physics3DSharedData.staticBroadPhaseLayerIndex\n );\n const dynamicBroadPhaseLayer = new Jolt.BroadPhaseLayer(\n gdjs.Physics3DSharedData.dynamicBroadPhaseLayerIndex\n );\n const broadPhaseLayerInterfaceMask = new Jolt.BroadPhaseLayerInterfaceMask(\n 2\n );\n broadPhaseLayerInterfaceMask.ConfigureLayer(\n staticBroadPhaseLayer,\n gdjs.Physics3DSharedData.staticLayersMask,\n 0\n );\n broadPhaseLayerInterfaceMask.ConfigureLayer(\n dynamicBroadPhaseLayer,\n gdjs.Physics3DSharedData.dynamicLayersMask,\n 0\n );\n // BroadPhaseLayer have been copied into bpInterface\n Jolt.destroy(staticBroadPhaseLayer);\n Jolt.destroy(dynamicBroadPhaseLayer);\n\n settings.mObjectLayerPairFilter = objectFilter;\n settings.mBroadPhaseLayerInterface = broadPhaseLayerInterfaceMask;\n settings.mObjectVsBroadPhaseLayerFilter = new Jolt.ObjectVsBroadPhaseLayerFilterMask(\n broadPhaseLayerInterfaceMask\n );\n }\n\n /**\n * Add a physics object to the list of existing object.\n */\n addToBehaviorsList(physicsBehavior: gdjs.Physics3DRuntimeBehavior): void {\n this._registeredBehaviors.add(physicsBehavior);\n }\n\n /**\n * Remove a physics object to the list of existing object.\n */\n removeFromBehaviorsList(\n physicsBehavior: gdjs.Physics3DRuntimeBehavior\n ): void {\n this._registeredBehaviors.delete(physicsBehavior);\n }\n\n step(deltaTime: float): void {\n for (const physicsBehavior of this._registeredBehaviors) {\n physicsBehavior._contactsStartedThisFrame.length = 0;\n physicsBehavior._contactsEndedThisFrame.length = 0;\n }\n for (const physicsBehavior of this._registeredBehaviors) {\n physicsBehavior.updateBodyFromObject();\n }\n for (const physics3DHook of this._physics3DHooks) {\n physics3DHook.doBeforePhysicsStep(deltaTime);\n }\n\n const numSteps = deltaTime > 1.0 / 55.0 ? 2 : 1;\n this.jolt.Step(deltaTime, numSteps);\n this.stepped = true;\n\n // It's important that updateBodyFromObject and updateObjectFromBody are\n // called at the same time because other behavior may move the object in\n // their doStepPreEvents.\n for (const physicsBehavior of this._registeredBehaviors) {\n physicsBehavior.updateObjectFromBody();\n }\n }\n\n /**\n * A hook must typically be registered by a behavior that requires this one\n * in its onCreate function.\n * The hook must stay forever to avoid side effects like a hooks order\n * change. To handle deactivated behavior, the hook can check that its\n * behavior is activated before doing anything.\n */\n registerHook(hook: gdjs.Physics3DRuntimeBehavior.Physics3DHook) {\n this._physics3DHooks.push(hook);\n }\n }\n gdjs.registerRuntimeSceneUnloadedCallback(function (runtimeScene) {\n const physics3DSharedData = runtimeScene.physics3DSharedData;\n if (physics3DSharedData) {\n Jolt.destroy(physics3DSharedData.jolt);\n Jolt.destroy(physics3DSharedData.contactListener);\n Jolt.destroy(physics3DSharedData._tempVec3);\n Jolt.destroy(physics3DSharedData._tempRVec3);\n Jolt.destroy(physics3DSharedData._tempQuat);\n runtimeScene.physics3DSharedData = null;\n }\n });\n\n export class Physics3DRuntimeBehavior extends gdjs.RuntimeBehavior {\n bodyUpdater: gdjs.Physics3DRuntimeBehavior.BodyUpdater;\n owner3D: gdjs.RuntimeObject3D;\n\n bodyType: string;\n bullet: boolean;\n fixedRotation: boolean;\n private shape: string;\n private shapeOrientation: string;\n private shapeDimensionA: any;\n private shapeDimensionB: any;\n private shapeDimensionC: any;\n private density: float;\n friction: float;\n restitution: float;\n linearDamping: float;\n angularDamping: float;\n gravityScale: float;\n private layers: integer;\n private masks: integer;\n private shapeScale: number = 1;\n\n /**\n * Array containing the beginning of contacts reported by onContactBegin. Each contact\n * should be unique to avoid recording glitches where the object loses and regain\n * contact between two frames. The array is updated each time the method\n * onContactBegin is called by the listener, which is only called when stepping\n * the world i.e. in the first preEvent called by a physics behavior. This array is\n * cleared just before stepping the world.\n */\n _contactsStartedThisFrame: Array<Physics3DRuntimeBehavior> = [];\n\n /**\n * Array containing the end of contacts reported by onContactEnd. The array is updated\n * each time the method onContactEnd is called by the listener, which can be called at\n * any time. This array is cleared just before stepping the world.\n */\n _contactsEndedThisFrame: Array<Physics3DRuntimeBehavior> = [];\n\n /**\n * Array containing the exact current contacts with the objects. It is updated\n * each time the methods onContactBegin and onContactEnd are called by the contact\n * listener.\n */\n private _currentContacts: Array<Physics3DRuntimeBehavior> = [];\n\n private _destroyedDuringFrameLogic: boolean;\n _body: Jolt.Body | null = null;\n /**\n * When set to `true` the body will be recreated before the next physics step.\n */\n private _needToRecreateBody: boolean = false;\n /**\n * When set to `true` the shape will be recreated before the next physics step.\n */\n private _needToRecreateShape: boolean = false;\n /**\n * Used by {@link gdjs.PhysicsCharacter3DRuntimeBehavior} to convert coordinates.\n */\n _shapeHalfDepth: float = 0;\n\n /**\n * sharedData is a reference to the shared data of the scene, that registers\n * every physics behavior that is created so that collisions can be cleared\n * before stepping the world.\n */\n _sharedData: Physics3DSharedData;\n\n _objectOldX: float = 0;\n _objectOldY: float = 0;\n _objectOldZ: float = 0;\n _objectOldRotationX: float = 0;\n _objectOldRotationY: float = 0;\n _objectOldRotationZ: float = 0;\n _objectOldWidth: float = 0;\n _objectOldHeight: float = 0;\n _objectOldDepth: float = 0;\n\n constructor(\n instanceContainer: gdjs.RuntimeInstanceContainer,\n behaviorData,\n owner: gdjs.RuntimeObject3D\n ) {\n super(instanceContainer, behaviorData, owner);\n this.bodyUpdater = new gdjs.Physics3DRuntimeBehavior.DefaultBodyUpdater(\n this\n );\n this.owner3D = owner;\n this.bodyType = behaviorData.bodyType;\n this.bullet = behaviorData.bullet;\n this.fixedRotation = behaviorData.fixedRotation;\n this.shape = behaviorData.shape;\n this.shapeOrientation = behaviorData.shapeOrientation;\n this.shapeDimensionA = behaviorData.shapeDimensionA;\n this.shapeDimensionB = behaviorData.shapeDimensionB;\n this.shapeDimensionC = behaviorData.shapeDimensionC;\n this.density = behaviorData.density;\n this.friction = behaviorData.friction;\n this.restitution = behaviorData.restitution;\n this.linearDamping = Math.max(0, behaviorData.linearDamping);\n this.angularDamping = Math.max(0, behaviorData.angularDamping);\n this.gravityScale = behaviorData.gravityScale;\n this.layers = behaviorData.layers;\n this.masks = behaviorData.masks;\n this._destroyedDuringFrameLogic = false;\n this._sharedData = Physics3DSharedData.getSharedData(\n instanceContainer.getScene(),\n behaviorData.name\n );\n this._sharedData.addToBehaviorsList(this);\n }\n\n private getVec3(x: float, y: float, z: float): Jolt.Vec3 {\n const tempVec3 = this._sharedData._tempVec3;\n tempVec3.Set(x, y, z);\n return tempVec3;\n }\n\n private getRVec3(x: float, y: float, z: float): Jolt.RVec3 {\n const tempRVec3 = this._sharedData._tempRVec3;\n tempRVec3.Set(x, y, z);\n return tempRVec3;\n }\n\n private getQuat(x: float, y: float, z: float, w: float): Jolt.Quat {\n const tempQuat = this._sharedData._tempQuat;\n tempQuat.Set(x, y, z, w);\n return tempQuat;\n }\n\n updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {\n if (oldBehaviorData.bullet !== newBehaviorData.bullet) {\n this.setBullet(newBehaviorData.bullet);\n }\n if (oldBehaviorData.fixedRotation !== newBehaviorData.fixedRotation) {\n this.setFixedRotation(newBehaviorData.fixedRotation);\n }\n if (oldBehaviorData.shapeDimensionA !== newBehaviorData.shapeDimensionA) {\n this.shapeDimensionA = newBehaviorData.shapeDimensionA;\n this._needToRecreateShape = true;\n }\n if (oldBehaviorData.shapeDimensionB !== newBehaviorData.shapeDimensionB) {\n this.shapeDimensionB = newBehaviorData.shapeDimensionB;\n this._needToRecreateShape = true;\n }\n if (oldBehaviorData.density !== newBehaviorData.density) {\n this.setDensity(newBehaviorData.density);\n }\n if (oldBehaviorData.friction !== newBehaviorData.friction) {\n this.setFriction(newBehaviorData.friction);\n }\n if (oldBehaviorData.restitution !== newBehaviorData.restitution) {\n this.setRestitution(newBehaviorData.restitution);\n }\n if (oldBehaviorData.linearDamping !== newBehaviorData.linearDamping) {\n this.setLinearDamping(newBehaviorData.linearDamping);\n }\n if (oldBehaviorData.angularDamping !== newBehaviorData.angularDamping) {\n this.setAngularDamping(newBehaviorData.angularDamping);\n }\n if (oldBehaviorData.gravityScale !== newBehaviorData.gravityScale) {\n this.setGravityScale(newBehaviorData.gravityScale);\n }\n\n // TODO: make these properties updatable.\n if (oldBehaviorData.layers !== newBehaviorData.layers) {\n return false;\n }\n if (oldBehaviorData.masks !== newBehaviorData.masks) {\n return false;\n }\n if (oldBehaviorData.vertices !== newBehaviorData.vertices) {\n return false;\n }\n if (oldBehaviorData.bodyType !== newBehaviorData.bodyType) {\n return false;\n }\n if (oldBehaviorData.shape !== newBehaviorData.shape) {\n return false;\n }\n return true;\n }\n\n getNetworkSyncData(): Physics3DNetworkSyncData {\n let bodyProps;\n if (this._body) {\n const position = this._body.GetPosition();\n const rotation = this._body.GetRotation();\n const linearVelocity = this._body.GetLinearVelocity();\n const angularVelocity = this._body.GetAngularVelocity();\n bodyProps = {\n px: position.GetX(),\n py: position.GetY(),\n pz: position.GetZ(),\n rx: rotation.GetX(),\n ry: rotation.GetY(),\n rz: rotation.GetZ(),\n rw: rotation.GetW(),\n lvx: linearVelocity.GetX(),\n lvy: linearVelocity.GetY(),\n lvz: linearVelocity.GetZ(),\n avx: angularVelocity.GetX(),\n avy: angularVelocity.GetY(),\n avz: angularVelocity.GetZ(),\n aw: this._body.IsActive(),\n };\n } else {\n bodyProps = {\n px: undefined,\n py: undefined,\n pz: undefined,\n rx: undefined,\n ry: undefined,\n rz: undefined,\n rw: undefined,\n lvx: undefined,\n lvy: undefined,\n lvz: undefined,\n avx: undefined,\n avy: undefined,\n avz: undefined,\n aw: undefined,\n };\n }\n return {\n ...super.getNetworkSyncData(),\n props: {\n ...bodyProps,\n layers: this.layers,\n masks: this.masks,\n },\n };\n }\n\n updateFromNetworkSyncData(networkSyncData: Physics3DNetworkSyncData) {\n super.updateFromNetworkSyncData(networkSyncData);\n\n const behaviorSpecificProps = networkSyncData.props;\n if (\n behaviorSpecificProps.px !== undefined &&\n behaviorSpecificProps.py !== undefined &&\n behaviorSpecificProps.pz !== undefined\n ) {\n if (this._body) {\n this._sharedData.bodyInterface.SetPosition(\n this._body.GetID(),\n this.getVec3(\n behaviorSpecificProps.px,\n behaviorSpecificProps.py,\n behaviorSpecificProps.pz\n ),\n Jolt.EActivation_DontActivate\n );\n }\n }\n if (\n behaviorSpecificProps.rx !== undefined &&\n behaviorSpecificProps.ry !== undefined &&\n behaviorSpecificProps.rz !== undefined &&\n behaviorSpecificProps.rw !== undefined\n ) {\n if (this._body) {\n this._sharedData.bodyInterface.SetRotation(\n this._body.GetID(),\n this.getQuat(\n behaviorSpecificProps.rx,\n behaviorSpecificProps.ry,\n behaviorSpecificProps.rz,\n behaviorSpecificProps.rw\n ),\n Jolt.EActivation_DontActivate\n );\n }\n }\n if (\n behaviorSpecificProps.lvx !== undefined &&\n behaviorSpecificProps.lvy !== undefined &&\n behaviorSpecificProps.lvz !== undefined\n ) {\n if (this._body) {\n this._sharedData.bodyInterface.SetLinearVelocity(\n this._body.GetID(),\n this.getVec3(\n behaviorSpecificProps.lvx,\n behaviorSpecificProps.lvy,\n behaviorSpecificProps.lvz\n )\n );\n }\n }\n if (\n behaviorSpecificProps.avx !== undefined &&\n behaviorSpecificProps.avy !== undefined &&\n behaviorSpecificProps.avz !== undefined\n ) {\n if (this._body) {\n this._sharedData.bodyInterface.SetAngularVelocity(\n this._body.GetID(),\n this.getVec3(\n behaviorSpecificProps.avx,\n behaviorSpecificProps.avy,\n behaviorSpecificProps.avz\n )\n );\n }\n }\n if (behaviorSpecificProps.layers !== undefined) {\n this.layers = behaviorSpecificProps.layers;\n }\n if (behaviorSpecificProps.masks !== undefined) {\n this.masks = behaviorSpecificProps.masks;\n }\n }\n\n onDeActivate() {\n this._sharedData.removeFromBehaviorsList(this);\n if (this._body !== null) {\n this._sharedData.bodyInterface.RemoveBody(this._body.GetID());\n this._sharedData.bodyInterface.DestroyBody(this._body.GetID());\n this._body = null;\n }\n this._contactsEndedThisFrame.length = 0;\n this._contactsStartedThisFrame.length = 0;\n this._currentContacts.length = 0;\n }\n\n onActivate() {\n this._sharedData.addToBehaviorsList(this);\n\n this._contactsEndedThisFrame.length = 0;\n this._contactsStartedThisFrame.length = 0;\n this._currentContacts.length = 0;\n this.updateBodyFromObject();\n }\n\n onDestroy() {\n this._destroyedDuringFrameLogic = true;\n this.onDeActivate();\n }\n\n createShape(): Jolt.Shape {\n let width = this.owner3D.getWidth() * this._sharedData.worldInvScale;\n let height = this.owner3D.getHeight() * this._sharedData.worldInvScale;\n let depth = this.owner3D.getDepth() * this._sharedData.worldInvScale;\n if (this.shapeOrientation === 'X') {\n const swap = depth;\n depth = width;\n width = swap;\n } else if (this.shapeOrientation === 'Y') {\n const swap = depth;\n depth = height;\n height = swap;\n }\n\n const shapeScale = this.shapeScale * this._sharedData.worldInvScale;\n\n const shapeDimensionA = this.shapeDimensionA * shapeScale;\n const shapeDimensionB = this.shapeDimensionB * shapeScale;\n const shapeDimensionC = this.shapeDimensionC * shapeScale;\n\n const onePixel = this._sharedData.worldInvScale;\n\n let shapeSettings: Jolt.ConvexShapeSettings;\n /** This is fine only because no other Quat is used locally. */\n let quat: Jolt.Quat;\n if (this.shape === 'Box') {\n const boxWidth =\n shapeDimensionA > 0 ? shapeDimensionA : width > 0 ? width : onePixel;\n const boxHeight =\n shapeDimensionB > 0\n ? shapeDimensionB\n : height > 0\n ? height\n : onePixel;\n const boxDepth =\n shapeDimensionC > 0 ? shapeDimensionC : depth > 0 ? depth : onePixel;\n // The convex radius should not eat up the whole volume.\n const convexRadius = Math.min(\n onePixel,\n Math.min(boxWidth, boxHeight, boxDepth) / 4\n );\n shapeSettings = new Jolt.BoxShapeSettings(\n this.getVec3(boxWidth / 2, boxHeight / 2, boxDepth / 2),\n convexRadius\n );\n quat = this.getQuat(0, 0, 0, 1);\n this._shapeHalfDepth = boxDepth / 2;\n } else if (this.shape === 'Capsule') {\n const radius =\n shapeDimensionA > 0\n ? shapeDimensionA\n : width > 0\n ? Math.sqrt(width * height) / 2\n : onePixel;\n const capsuleDepth =\n shapeDimensionB > 0 ? shapeDimensionB : depth > 0 ? depth : onePixel;\n shapeSettings = new Jolt.CapsuleShapeSettings(\n Math.max(0, capsuleDepth / 2 - radius),\n radius\n );\n quat = this._getShapeOrientationQuat();\n this._shapeHalfDepth =\n this.shapeOrientation !== 'Z' ? radius : capsuleDepth / 2;\n } else if (this.shape === 'Cylinder') {\n const radius =\n shapeDimensionA > 0\n ? shapeDimensionA\n : width > 0\n ? Math.sqrt(width * height) / 2\n : onePixel;\n const cylinderDepth =\n shapeDimensionB > 0 ? shapeDimensionB : depth > 0 ? depth : onePixel;\n // The convex radius should not eat up the whole volume.\n const convexRadius = Math.min(\n onePixel,\n Math.min(cylinderDepth, radius) / 4\n );\n shapeSettings = new Jolt.CylinderShapeSettings(\n cylinderDepth / 2,\n radius,\n convexRadius\n );\n quat = this._getShapeOrientationQuat();\n this._shapeHalfDepth =\n this.shapeOrientation !== 'Z' ? radius : cylinderDepth / 2;\n } else {\n // Create a 'Sphere' by default.\n const radius =\n shapeDimensionA > 0\n ? shapeDimensionA\n : width > 0\n ? Math.pow(width * height * depth, 1 / 3) / 2\n : onePixel;\n shapeSettings = new Jolt.SphereShapeSettings(radius);\n quat = this.getQuat(0, 0, 0, 1);\n this._shapeHalfDepth = radius;\n }\n shapeSettings.mDensity = this.density;\n const rotatedShape = new Jolt.RotatedTranslatedShapeSettings(\n this.getVec3(0, 0, 0),\n quat,\n shapeSettings\n )\n .Create()\n .Get();\n\n Jolt.destroy(shapeSettings);\n return rotatedShape;\n }\n\n private _getShapeOrientationQuat(): Jolt.Quat {\n if (this.shapeOrientation === 'X') {\n // Top on X axis.\n return this.getQuat(0, 0, Math.sqrt(2) / 2, -Math.sqrt(2) / 2);\n } else if (this.shapeOrientation === 'Y') {\n // Top on Y axis.\n return this.getQuat(0, 0, 0, 1);\n } else {\n // Top on Z axis.\n return this.getQuat(Math.sqrt(2) / 2, 0, 0, Math.sqrt(2) / 2);\n }\n }\n\n private _recreateShape(): void {\n this.bodyUpdater.recreateShape();\n\n this._objectOldWidth = this.owner3D.getWidth();\n this._objectOldHeight = this.owner3D.getHeight();\n this._objectOldDepth = this.owner3D.getDepth();\n }\n\n getShapeScale(): float {\n return this.shapeScale;\n }\n\n setShapeScale(shapeScale: float): void {\n if (shapeScale !== this.shapeScale && shapeScale > 0) {\n this.shapeScale = shapeScale;\n this._needToRecreateShape = true;\n }\n }\n\n getBody(): Jolt.Body {\n if (this._body === null) {\n this._createBody();\n }\n return this._body!;\n }\n\n _createBody(): boolean {\n this._needToRecreateBody = false;\n this._needToRecreateShape = false;\n\n if (!this.activated() || this._destroyedDuringFrameLogic) return false;\n\n this._body = this.bodyUpdater.createAndAddBody();\n this._body.gdjsAssociatedBehavior = this;\n\n this._objectOldWidth = this.owner3D.getWidth();\n this._objectOldHeight = this.owner3D.getHeight();\n this._objectOldDepth = this.owner3D.getDepth();\n return true;\n }\n\n /**\n * @returns The body layer id according to the behavior configuration.\n */\n getBodyLayer(): number {\n return Jolt.ObjectLayerPairFilterMask.prototype.sGetObjectLayer(\n // Make sure objects don't register in the wrong layer group.\n this.bodyType === 'Static'\n ? this.layers & gdjs.Physics3DSharedData.staticLayersMask\n : this.layers & gdjs.Physics3DSharedData.dynamicLayersMask,\n // Static objects accept all collisions as it's the mask of dynamic objects that matters.\n this.bodyType === 'Static'\n ? gdjs.Physics3DSharedData.allLayersMask\n : this.masks\n );\n }\n\n doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {\n // Step the world if not done this frame yet.\n // Don't step at the first frame to allow events to handle overlapping objects.\n if (\n !this._sharedData.stepped &&\n !instanceContainer.getScene().getTimeManager().isFirstFrame()\n ) {\n this._sharedData.step(\n instanceContainer.getScene().getTimeManager().getElapsedTime() /\n 1000.0\n );\n }\n }\n\n doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {\n // Reset world step to update next frame\n this._sharedData.stepped = false;\n }\n\n onObjectHotReloaded() {\n this.updateBodyFromObject();\n }\n\n recreateBody() {\n if (!this._body) {\n this._createBody();\n return;\n }\n\n const bodyInterface = this._sharedData.bodyInterface;\n const linearVelocity = this._body.GetLinearVelocity();\n const linearVelocityX = linearVelocity.GetX();\n const linearVelocityY = linearVelocity.GetY();\n const linearVelocityZ = linearVelocity.GetZ();\n const angularVelocity = this._body.GetAngularVelocity();\n const angularVelocityX = angularVelocity.GetX();\n const angularVelocityY = angularVelocity.GetY();\n const angularVelocityZ = angularVelocity.GetZ();\n\n let bodyID = this._body.GetID();\n bodyInterface.RemoveBody(bodyID);\n bodyInterface.DestroyBody(bodyID);\n this._contactsEndedThisFrame.length = 0;\n this._contactsStartedThisFrame.length = 0;\n this._currentContacts.length = 0;\n\n this._createBody();\n if (!this._body) {\n return;\n }\n bodyID = this._body.GetID();\n bodyInterface.SetLinearVelocity(\n bodyID,\n this.getVec3(linearVelocityX, linearVelocityY, linearVelocityZ)\n );\n bodyInterface.SetAngularVelocity(\n bodyID,\n this.getVec3(angularVelocityX, angularVelocityY, angularVelocityZ)\n );\n }\n\n updateObjectFromBody() {\n this.bodyUpdater.updateObjectFromBody();\n\n // Update cached transform.\n this._objectOldX = this.owner3D.getX();\n this._objectOldY = this.owner3D.getY();\n this._objectOldZ = this.owner3D.getZ();\n this._objectOldRotationX = this.owner3D.getRotationX();\n this._objectOldRotationY = this.owner3D.getRotationY();\n this._objectOldRotationZ = this.owner3D.getAngle();\n }\n\n updateBodyFromObject() {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n\n if (this._needToRecreateBody) {\n this.recreateBody();\n }\n\n // The object size has changed, recreate the shape.\n // The width has changed and there is no custom dimension A (box: width, circle: radius, edge: length) or\n // The height has changed, the shape is not an edge (edges doesn't have height),\n // it isn't a box with custom height or a circle with custom radius\n if (\n this._needToRecreateShape ||\n (!this.hasCustomShapeDimension() &&\n (this._objectOldWidth !== this.owner3D.getWidth() ||\n this._objectOldHeight !== this.owner3D.getHeight() ||\n this._objectOldDepth !== this.owner3D.getDepth()))\n ) {\n this._needToRecreateShape = false;\n this._recreateShape();\n }\n\n this.bodyUpdater.updateBodyFromObject();\n }\n\n hasCustomShapeDimension() {\n return (\n this.shapeDimensionA > 0 ||\n this.shapeDimensionB > 0 ||\n this.shapeDimensionC > 0\n );\n }\n\n getPhysicsPosition(result: Jolt.RVec3): Jolt.RVec3 {\n result.Set(\n this.owner3D.getCenterXInScene() * this._sharedData.worldInvScale,\n this.owner3D.getCenterYInScene() * this._sharedData.worldInvScale,\n this.owner3D.getCenterZInScene() * this._sharedData.worldInvScale\n );\n return result;\n }\n\n getPhysicsRotation(result: Jolt.Quat): Jolt.Quat {\n const threeObject = this.owner3D.get3DRendererObject();\n result.Set(\n threeObject.quaternion.x,\n threeObject.quaternion.y,\n threeObject.quaternion.z,\n threeObject.quaternion.w\n );\n return result;\n }\n\n moveObjectToPhysicsPosition(physicsPosition: Jolt.RVec3): void {\n this.owner3D.setCenterXInScene(\n physicsPosition.GetX() * this._sharedData.worldScale\n );\n this.owner3D.setCenterYInScene(\n physicsPosition.GetY() * this._sharedData.worldScale\n );\n this.owner3D.setCenterZInScene(\n physicsPosition.GetZ() * this._sharedData.worldScale\n );\n }\n\n moveObjectToPhysicsRotation(physicsRotation: Jolt.Quat): void {\n const threeObject = this.owner3D.get3DRendererObject();\n threeObject.quaternion.x = physicsRotation.GetX();\n threeObject.quaternion.y = physicsRotation.GetY();\n threeObject.quaternion.z = physicsRotation.GetZ();\n threeObject.quaternion.w = physicsRotation.GetW();\n // TODO Avoid this instantiation\n const euler = new THREE.Euler(0, 0, 0, 'ZYX');\n euler.setFromQuaternion(threeObject.quaternion);\n this.owner3D.setRotationX(gdjs.toDegrees(euler.x));\n this.owner3D.setRotationY(gdjs.toDegrees(euler.y));\n this.owner3D.setAngle(gdjs.toDegrees(euler.z));\n }\n\n getWorldScale(): float {\n return this._sharedData.worldScale;\n }\n\n getGravityX(): float {\n return this._sharedData.gravityX;\n }\n\n getGravityY(): float {\n return this._sharedData.gravityY;\n }\n\n getGravityZ(): float {\n return this._sharedData.gravityZ;\n }\n\n setGravityX(gravityX: float): void {\n if (this._sharedData.gravityX === gravityX) {\n return;\n }\n\n this._sharedData.gravityX = gravityX;\n this._sharedData.physicsSystem.SetGravity(\n this.getVec3(\n this._sharedData.gravityX,\n this._sharedData.gravityY,\n this._sharedData.gravityZ\n )\n );\n }\n\n setGravityY(gravityY: float): void {\n if (this._sharedData.gravityX === gravityY) {\n return;\n }\n\n this._sharedData.gravityX = gravityY;\n this._sharedData.physicsSystem.SetGravity(\n this.getVec3(\n this._sharedData.gravityX,\n this._sharedData.gravityY,\n this._sharedData.gravityZ\n )\n );\n }\n\n setGravityZ(gravityZ: float): void {\n if (this._sharedData.gravityX === gravityZ) {\n return;\n }\n\n this._sharedData.gravityZ = gravityZ;\n this._sharedData.physicsSystem.SetGravity(\n this.getVec3(\n this._sharedData.gravityX,\n this._sharedData.gravityY,\n this._sharedData.gravityZ\n )\n );\n }\n\n isDynamic(): boolean {\n return this.bodyType === 'Dynamic';\n }\n\n isStatic(): boolean {\n return this.bodyType === 'Static';\n }\n\n isKinematic(): boolean {\n return this.bodyType === 'Kinematic';\n }\n\n isBullet(): boolean {\n return this.bullet;\n }\n\n setBullet(enable: boolean): void {\n if (this.bullet === enable) {\n return;\n }\n this.bullet = enable;\n\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetMotionQuality(\n body.GetID(),\n this.bullet\n ? Jolt.EMotionQuality_LinearCast\n : Jolt.EMotionQuality_Discrete\n );\n }\n\n hasFixedRotation(): boolean {\n return this.fixedRotation;\n }\n\n setFixedRotation(enable: boolean): void {\n if (this.fixedRotation === enable) {\n return;\n }\n this.fixedRotation = enable;\n this._needToRecreateBody = true;\n }\n\n getDensity() {\n return this.density;\n }\n\n setDensity(density: float): void {\n // Non-negative values only\n if (density < 0) {\n density = 0;\n }\n if (this.density === density) {\n return;\n }\n this.density = density;\n this._needToRecreateShape = true;\n }\n\n getFriction(): float {\n return this.friction;\n }\n\n setFriction(friction: float): void {\n // Non-negative values only\n if (friction < 0) {\n friction = 0;\n }\n if (this.friction === friction) {\n return;\n }\n this.friction = friction;\n\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetFriction(body.GetID(), friction);\n }\n\n getRestitution(): float {\n return this.restitution;\n }\n\n setRestitution(restitution: float): void {\n // Non-negative values only\n if (restitution < 0) {\n restitution = 0;\n }\n if (this.restitution === restitution) {\n return;\n }\n this.restitution = restitution;\n\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetRestitution(body.GetID(), restitution);\n }\n\n getLinearDamping(): float {\n return this.linearDamping;\n }\n\n setLinearDamping(linearDamping: float): void {\n // Non-negative values only\n if (linearDamping < 0) {\n linearDamping = 0;\n }\n if (this.linearDamping === linearDamping) {\n return;\n }\n this.linearDamping = linearDamping;\n\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n body.GetMotionProperties().SetLinearDamping(linearDamping);\n }\n\n getAngularDamping(): float {\n return this.angularDamping;\n }\n\n setAngularDamping(angularDamping: float): void {\n // Non-negative values only\n if (angularDamping < 0) {\n angularDamping = 0;\n }\n if (this.angularDamping === angularDamping) {\n return;\n }\n this.angularDamping = angularDamping;\n\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n body.GetMotionProperties().SetAngularDamping(angularDamping);\n }\n\n getGravityScale(): float {\n return this.gravityScale;\n }\n\n setGravityScale(gravityScale: float): void {\n if (this.gravityScale === gravityScale) {\n return;\n }\n this.gravityScale = gravityScale;\n\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n body.GetMotionProperties().SetGravityFactor(gravityScale);\n }\n\n layerEnabled(layer: integer): boolean {\n // Layer must be an integer\n layer = Math.floor(layer);\n if (layer < 1 || layer > 8) {\n return false;\n }\n return !!(this.layers & (1 << (layer - 1)));\n }\n\n enableLayer(layer: integer, enable: boolean): void {\n // Layer must be an integer\n layer = Math.floor(layer);\n if (layer < 1 || layer > 8) {\n return;\n }\n\n if (enable) {\n this.layers |= 1 << (layer - 1);\n } else {\n this.layers &= ~(1 << (layer - 1));\n }\n\n this._needToRecreateBody = true;\n }\n\n maskEnabled(mask: integer): boolean {\n // Mask must be an integer\n mask = Math.floor(mask);\n if (mask < 1 || mask > 16) {\n return false;\n }\n return !!(this.masks & (1 << (mask - 1)));\n }\n\n enableMask(mask: integer, enable: boolean): void {\n // Mask must be an integer\n mask = Math.floor(mask);\n if (mask < 1 || mask > 16) {\n return;\n }\n\n if (enable) {\n this.masks |= 1 << (mask - 1);\n } else {\n this.masks &= ~(1 << (mask - 1));\n }\n\n this._needToRecreateBody = true;\n }\n\n getLinearVelocityX(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return body.GetLinearVelocity().GetX() * this._sharedData.worldScale;\n }\n\n setLinearVelocityX(linearVelocityX: float): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetLinearVelocity(\n body.GetID(),\n this.getVec3(\n linearVelocityX * this._sharedData.worldInvScale,\n body.GetLinearVelocity().GetY(),\n body.GetLinearVelocity().GetZ()\n )\n );\n }\n\n getLinearVelocityY(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return body.GetLinearVelocity().GetY() * this._sharedData.worldScale;\n }\n\n setLinearVelocityY(linearVelocityY: float): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetLinearVelocity(\n body.GetID(),\n this.getVec3(\n body.GetLinearVelocity().GetX(),\n linearVelocityY * this._sharedData.worldInvScale,\n body.GetLinearVelocity().GetZ()\n )\n );\n }\n\n getLinearVelocityZ(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return body.GetLinearVelocity().GetZ() * this._sharedData.worldScale;\n }\n\n setLinearVelocityZ(linearVelocityZ: float): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetLinearVelocity(\n body.GetID(),\n this.getVec3(\n body.GetLinearVelocity().GetX(),\n body.GetLinearVelocity().GetY(),\n linearVelocityZ * this._sharedData.worldInvScale\n )\n );\n }\n\n getLinearVelocityLength(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return body.GetLinearVelocity().Length() * this._sharedData.worldScale;\n }\n\n getAngularVelocityX(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return gdjs.toDegrees(body.GetAngularVelocity().GetX());\n }\n\n setAngularVelocityX(angularVelocityX: float): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetAngularVelocity(\n body.GetID(),\n this.getVec3(\n gdjs.toRad(angularVelocityX),\n body.GetAngularVelocity().GetY(),\n body.GetAngularVelocity().GetZ()\n )\n );\n }\n\n getAngularVelocityY(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return gdjs.toDegrees(body.GetAngularVelocity().GetY());\n }\n\n setAngularVelocityY(angularVelocityY: float): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetAngularVelocity(\n body.GetID(),\n this.getVec3(\n body.GetAngularVelocity().GetX(),\n gdjs.toRad(angularVelocityY),\n body.GetAngularVelocity().GetZ()\n )\n );\n }\n\n getAngularVelocityZ(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return gdjs.toDegrees(body.GetAngularVelocity().GetZ());\n }\n\n setAngularVelocityZ(angularVelocityZ: float): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.SetAngularVelocity(\n body.GetID(),\n this.getVec3(\n body.GetAngularVelocity().GetX(),\n body.GetAngularVelocity().GetY(),\n gdjs.toRad(angularVelocityZ)\n )\n );\n }\n\n applyForce(\n forceX: float,\n forceY: float,\n forceZ: float,\n positionX: float,\n positionY: float,\n positionZ: float\n ): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.AddForce(\n body.GetID(),\n this.getVec3(forceX, forceY, forceZ),\n this.getRVec3(\n positionX * this._sharedData.worldInvScale,\n positionY * this._sharedData.worldInvScale,\n positionZ * this._sharedData.worldInvScale\n ),\n Jolt.EActivation_Activate\n );\n }\n\n applyForceAtCenter(forceX: float, forceY: float, forceZ: float): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.AddForce(\n body.GetID(),\n this.getVec3(forceX, forceY, forceZ),\n Jolt.EActivation_Activate\n );\n }\n\n applyForceTowardPosition(\n length: float,\n towardX: float,\n towardY: float,\n towardZ: float\n ): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n const deltaX = towardX - body.GetPosition().GetX();\n const deltaY = towardY - body.GetPosition().GetY();\n const deltaZ = towardZ - body.GetPosition().GetZ();\n const distance = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;\n if (distance === 0) {\n return;\n }\n const ratio = length / distance;\n\n this._sharedData.bodyInterface.AddForce(\n body.GetID(),\n this.getVec3(deltaX * ratio, deltaY * ratio, deltaZ * ratio),\n Jolt.EActivation_Activate\n );\n }\n\n applyImpulse(\n impulseX: float,\n impulseY: float,\n impulseZ: float,\n positionX: float,\n positionY: float,\n positionZ: float\n ): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.AddImpulse(\n body.GetID(),\n this.getVec3(impulseX, impulseY, impulseZ),\n this.getRVec3(\n positionX * this._sharedData.worldInvScale,\n positionY * this._sharedData.worldInvScale,\n positionZ * this._sharedData.worldInvScale\n )\n );\n }\n\n applyImpulseAtCenter(\n impulseX: float,\n impulseY: float,\n impulseZ: float\n ): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.AddImpulse(\n body.GetID(),\n this.getVec3(impulseX, impulseY, impulseZ)\n );\n }\n\n applyImpulseTowardPosition(\n length: float,\n towardX: float,\n towardY: float,\n towardZ: float,\n originX: float,\n originY: float,\n originZ: float\n ): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n const deltaX = towardX - originX;\n const deltaY = towardY - originY;\n const deltaZ = towardZ - originZ;\n const distance = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;\n if (distance === 0) {\n return;\n }\n const ratio = length / distance;\n\n this._sharedData.bodyInterface.AddImpulse(\n body.GetID(),\n this.getVec3(deltaX * ratio, deltaY * ratio, deltaZ * ratio),\n this.getRVec3(\n originX * this._sharedData.worldInvScale,\n originY * this._sharedData.worldInvScale,\n originZ * this._sharedData.worldInvScale\n )\n );\n }\n\n applyTorque(torqueX: float, torqueY: float, torqueZ: float): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.AddTorque(\n body.GetID(),\n this.getVec3(\n gdjs.toRad(torqueX),\n gdjs.toRad(torqueY),\n gdjs.toRad(torqueZ)\n ),\n Jolt.EActivation_Activate\n );\n }\n\n applyAngularImpulse(\n angularImpulseX: float,\n angularImpulseY: float,\n angularImpulseZ: float\n ): void {\n if (this._body === null) {\n if (!this._createBody()) return;\n }\n const body = this._body!;\n\n this._sharedData.bodyInterface.AddAngularImpulse(\n body.GetID(),\n this.getVec3(\n gdjs.toRad(angularImpulseX),\n gdjs.toRad(angularImpulseY),\n gdjs.toRad(angularImpulseZ)\n )\n );\n }\n\n getMass(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return 1 / body.GetMotionProperties().GetInverseMass();\n }\n\n /**\n * @returns The inertia for a rotation around X axis of the object at its\n * default rotation (0\u00B0; 0\u00B0; 0\u00B0).\n */\n getInertiaAroundX(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return 1 / body.GetMotionProperties().GetInverseInertiaDiagonal().GetX();\n }\n\n /**\n * @returns The inertia for a rotation around Y axis of the object at its\n * default rotation (0\u00B0; 0\u00B0; 0\u00B0).\n */\n getInertiaAroundY(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return 1 / body.GetMotionProperties().GetInverseInertiaDiagonal().GetY();\n }\n\n /**\n * @returns The inertia for a rotation around Z axis of the object at its\n * default rotation (0\u00B0; 0\u00B0; 0\u00B0).\n */\n getInertiaAroundZ(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return 1 / body.GetMotionProperties().GetInverseInertiaDiagonal().GetZ();\n }\n\n getMassCenterX(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return (\n body.GetCenterOfMassPosition().GetX() * this._sharedData.worldScale\n );\n }\n\n getMassCenterY(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return (\n body.GetCenterOfMassPosition().GetY() * this._sharedData.worldScale\n );\n }\n\n getMassCenterZ(): float {\n if (this._body === null) {\n if (!this._createBody()) return 0;\n }\n const body = this._body!;\n\n return (\n body.GetCenterOfMassPosition().GetZ() * this._sharedData.worldScale\n );\n }\n\n onContactBegin(otherBehavior: Physics3DRuntimeBehavior): void {\n this._currentContacts.push(otherBehavior);\n\n // There might be contacts that end during the frame and\n // start again right away. It is considered a glitch\n // and should not be detected.\n let i = this._contactsEndedThisFrame.indexOf(otherBehavior);\n if (i !== -1) {\n this._contactsEndedThisFrame.splice(i, 1);\n } else {\n this._contactsStartedThisFrame.push(otherBehavior);\n }\n }\n\n onContactEnd(otherBehavior: Physics3DRuntimeBehavior): void {\n this._contactsEndedThisFrame.push(otherBehavior);\n\n const index = this._currentContacts.indexOf(otherBehavior);\n if (index !== -1) {\n this._currentContacts.splice(index, 1);\n }\n }\n\n static areObjectsColliding(\n object1: gdjs.RuntimeObject,\n object2: gdjs.RuntimeObject,\n behaviorName: string\n ): boolean {\n const behavior1 = object1.getBehavior(\n behaviorName\n ) as Physics3DRuntimeBehavior | null;\n if (!behavior1) return false;\n\n if (\n behavior1._currentContacts.some(\n (behavior) => behavior.owner === object2\n )\n ) {\n return true;\n }\n // If a contact has started at this frame and ended right away, it\n // won't appear in current contacts but the condition should return\n // true anyway.\n if (\n behavior1._contactsStartedThisFrame.some(\n (behavior) => behavior.owner === object2\n )\n ) {\n return true;\n }\n\n // No contact found\n return false;\n }\n\n static hasCollisionStartedBetween(\n object1: gdjs.RuntimeObject,\n object2: gdjs.RuntimeObject,\n behaviorName: string\n ): boolean {\n const behavior1 = object1.getBehavior(\n behaviorName\n ) as Physics3DRuntimeBehavior | null;\n if (!behavior1) return false;\n\n return behavior1._contactsStartedThisFrame.some(\n (behavior) => behavior.owner === object2\n );\n }\n\n static hasCollisionStoppedBetween(\n object1: gdjs.RuntimeObject,\n object2: gdjs.RuntimeObject,\n behaviorName: string\n ): boolean {\n const behavior1 = object1.getBehavior(\n behaviorName\n ) as Physics3DRuntimeBehavior | null;\n if (!behavior1) return false;\n\n return behavior1._contactsEndedThisFrame.some(\n (behavior) => behavior.owner === object2\n );\n }\n }\n\n gdjs.registerBehavior(\n 'Physics3D::Physics3DBehavior',\n gdjs.Physics3DRuntimeBehavior\n );\n\n export namespace Physics3DRuntimeBehavior {\n /**\n * Allow extensions relying on the 3D physics to customize its\n * behavior a bit.\n */\n export interface Physics3DHook {\n /**\n * Called before the physics engine step.\n */\n doBeforePhysicsStep(timeDelta: float): void;\n }\n\n export interface BodyUpdater {\n createAndAddBody(): Jolt.Body;\n updateObjectFromBody(): void;\n updateBodyFromObject(): void;\n recreateShape(): void;\n }\n\n export class DefaultBodyUpdater {\n behavior: gdjs.Physics3DRuntimeBehavior;\n\n constructor(behavior: gdjs.Physics3DRuntimeBehavior) {\n this.behavior = behavior;\n }\n\n createAndAddBody(): Jolt.Body {\n const { behavior } = this;\n const { _sharedData } = behavior;\n\n const shape = behavior.createShape();\n const bodyCreationSettings = new Jolt.BodyCreationSettings(\n shape,\n behavior.getPhysicsPosition(_sharedData.getRVec3(0, 0, 0)),\n behavior.getPhysicsRotation(_sharedData.getQuat(0, 0, 0, 1)),\n behavior.bodyType === 'Static'\n ? Jolt.EMotionType_Static\n : behavior.bodyType === 'Kinematic'\n ? Jolt.EMotionType_Kinematic\n : Jolt.EMotionType_Dynamic,\n behavior.getBodyLayer()\n );\n bodyCreationSettings.mMotionQuality = behavior.bullet\n ? Jolt.EMotionQuality_LinearCast\n : Jolt.EMotionQuality_Discrete;\n bodyCreationSettings.mAllowedDOFs = behavior.fixedRotation\n ? Jolt.EAllowedDOFs_TranslationX |\n Jolt.EAllowedDOFs_TranslationY |\n Jolt.EAllowedDOFs_TranslationZ\n : Jolt.EAllowedDOFs_All;\n bodyCreationSettings.mFriction = behavior.friction;\n bodyCreationSettings.mRestitution = behavior.restitution;\n bodyCreationSettings.mLinearDamping = behavior.linearDamping;\n bodyCreationSettings.mAngularDamping = behavior.angularDamping;\n bodyCreationSettings.mGravityFactor = behavior.gravityScale;\n\n const bodyInterface = _sharedData.bodyInterface;\n const body = bodyInterface.CreateBody(bodyCreationSettings);\n Jolt.destroy(bodyCreationSettings);\n\n bodyInterface.AddBody(body.GetID(), Jolt.EActivation_Activate);\n return body;\n }\n\n updateObjectFromBody() {\n const { behavior } = this;\n const { _body } = behavior;\n // Copy transform from body to the GD object.\n // The body is null when the behavior was either deactivated or the object deleted.\n // It would be useless to try to recreate it as updateBodyFromObject already does it.\n // If the body is null, we just don't do anything\n // (but still run the physics simulation - this is independent).\n if (_body !== null) {\n behavior.moveObjectToPhysicsPosition(_body.GetPosition());\n behavior.moveObjectToPhysicsRotation(_body.GetRotation());\n }\n }\n\n updateBodyFromObject() {\n const { behavior } = this;\n const { owner3D, _sharedData } = behavior;\n if (behavior._body === null) {\n if (!behavior._createBody()) return;\n }\n const body = behavior._body!;\n\n // TODO the `if` is probably unnecessary because `SetPositionAndRotationWhenChanged` already check this.\n // The object object transform has changed, update body transform:\n if (\n this.behavior._objectOldX !== owner3D.getX() ||\n this.behavior._objectOldY !== owner3D.getY() ||\n this.behavior._objectOldZ !== owner3D.getZ() ||\n this.behavior._objectOldRotationX !== owner3D.getRotationX() ||\n this.behavior._objectOldRotationY !== owner3D.getRotationY() ||\n this.behavior._objectOldRotationZ !== owner3D.getAngle()\n ) {\n _sharedData.bodyInterface.SetPositionAndRotationWhenChanged(\n body.GetID(),\n this.behavior.getPhysicsPosition(_sharedData.getRVec3(0, 0, 0)),\n this.behavior.getPhysicsRotation(_sharedData.getQuat(0, 0, 0, 1)),\n Jolt.EActivation_Activate\n );\n }\n }\n\n recreateShape() {\n const { behavior } = this;\n const { _sharedData } = behavior;\n if (behavior._body === null) {\n if (!behavior._createBody()) return;\n }\n const body = behavior._body!;\n\n const bodyInterface = _sharedData.bodyInterface;\n bodyInterface.SetShape(\n body.GetID(),\n behavior.createShape(),\n true,\n Jolt.EActivation_Activate\n );\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var gdjs;(function(a){let c;(function(o){o.areObjectsColliding=function(r,s,e,i,t){return a.evtTools.object.twoListsTest(a.Physics3DRuntimeBehavior.areObjectsColliding,r,e,t,s)},o.haveObjectsStartedColliding=function(r,s,e,i,t){return a.evtTools.object.twoListsTest(a.Physics3DRuntimeBehavior.hasCollisionStartedBetween,r,e,t,s)},o.haveObjectsStoppedColliding=function(r,s,e,i,t){return a.evtTools.object.twoListsTest(a.Physics3DRuntimeBehavior.hasCollisionStoppedBetween,r,e,t,s)};const h=(r,s,e)=>{const i=r.getBehavior(e.character),t=s.getBehavior(e.physics);return!i||!t?!1:i.isOnFloorObject(t)},n={character:"",physics:""};o.isOnPlatform=(r,s,e,i,t)=>(n.character=s,n.physics=i,a.evtTools.object.twoListsTest(h,r,e,t,n))})(c=a.physics3d||(a.physics3d={}))})(gdjs||(gdjs={}));
|
|
2
|
+
//# sourceMappingURL=Physics3DTools.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../GDevelop/Extensions/Physics3DBehavior/Physics3DTools.ts"],
|
|
4
|
+
"sourcesContent": ["namespace gdjs {\n export namespace physics3d {\n export const areObjectsColliding = function (\n objectsLists1: Hashtable<Array<gdjs.RuntimeObject>>,\n behaviorName: string,\n objectsLists2: Hashtable<Array<gdjs.RuntimeObject>>,\n behaviorName2: string,\n inverted: boolean\n ) {\n return gdjs.evtTools.object.twoListsTest(\n gdjs.Physics3DRuntimeBehavior.areObjectsColliding,\n objectsLists1,\n objectsLists2,\n inverted,\n behaviorName\n );\n };\n\n export const haveObjectsStartedColliding = function (\n objectsLists1: Hashtable<Array<gdjs.RuntimeObject>>,\n behaviorName: string,\n objectsLists2: Hashtable<Array<gdjs.RuntimeObject>>,\n behaviorName2: string,\n inverted: boolean\n ) {\n return gdjs.evtTools.object.twoListsTest(\n gdjs.Physics3DRuntimeBehavior.hasCollisionStartedBetween,\n objectsLists1,\n objectsLists2,\n inverted,\n behaviorName\n );\n };\n\n export const haveObjectsStoppedColliding = function (\n objectsLists1: Hashtable<Array<gdjs.RuntimeObject>>,\n behaviorName: string,\n objectsLists2: Hashtable<Array<gdjs.RuntimeObject>>,\n behaviorName2: string,\n inverted: boolean\n ) {\n return gdjs.evtTools.object.twoListsTest(\n gdjs.Physics3DRuntimeBehavior.hasCollisionStoppedBetween,\n objectsLists1,\n objectsLists2,\n inverted,\n behaviorName\n );\n };\n\n type BehaviorNamePair = { character: string; physics: string };\n\n const isOnPlatformAdapter = (\n characterObject: gdjs.RuntimeObject,\n physicsObject: gdjs.RuntimeObject,\n behaviorNamePair: BehaviorNamePair\n ): boolean => {\n const characterBehavior = characterObject.getBehavior(\n behaviorNamePair.character\n ) as gdjs.PhysicsCharacter3DRuntimeBehavior;\n const physicsBehavior = physicsObject.getBehavior(\n behaviorNamePair.physics\n ) as gdjs.Physics3DRuntimeBehavior;\n if (!characterBehavior || !physicsBehavior) {\n return false;\n }\n return characterBehavior.isOnFloorObject(physicsBehavior);\n };\n\n const behaviorNamePair: BehaviorNamePair = { character: '', physics: '' };\n\n export const isOnPlatform = (\n characterObjectsLists: Hashtable<Array<gdjs.RuntimeObject>>,\n characterBehaviorName: string,\n physicsObjectsLists: Hashtable<Array<gdjs.RuntimeObject>>,\n physicsBehaviorName: string,\n inverted: boolean\n ) => {\n behaviorNamePair.character = characterBehaviorName;\n behaviorNamePair.physics = physicsBehaviorName;\n return gdjs.evtTools.object.twoListsTest(\n isOnPlatformAdapter,\n characterObjectsLists,\n physicsObjectsLists,\n inverted,\n behaviorNamePair\n );\n };\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,GAAU,MAAV,UAAU,EAAV,CACS,GAAU,GAAV,UAAU,EAAV,CACE,AAAM,sBAAsB,SACjC,EACA,EACA,EACA,EACA,EACA,CACA,MAAO,GAAK,SAAS,OAAO,aAC1B,EAAK,yBAAyB,oBAC9B,EACA,EACA,EACA,IAIS,8BAA8B,SACzC,EACA,EACA,EACA,EACA,EACA,CACA,MAAO,GAAK,SAAS,OAAO,aAC1B,EAAK,yBAAyB,2BAC9B,EACA,EACA,EACA,IAIS,8BAA8B,SACzC,EACA,EACA,EACA,EACA,EACA,CACA,MAAO,GAAK,SAAS,OAAO,aAC1B,EAAK,yBAAyB,2BAC9B,EACA,EACA,EACA,IAMJ,KAAM,GAAsB,CAC1B,EACA,EACA,IACY,CACZ,KAAM,GAAoB,EAAgB,YACxC,EAAiB,WAEb,EAAkB,EAAc,YACpC,EAAiB,SAEnB,MAAI,CAAC,GAAqB,CAAC,EAClB,GAEF,EAAkB,gBAAgB,IAGrC,EAAqC,CAAE,UAAW,GAAI,QAAS,IAE9D,AAAM,eAAe,CAC1B,EACA,EACA,EACA,EACA,IAEA,GAAiB,UAAY,EAC7B,EAAiB,QAAU,EACpB,EAAK,SAAS,OAAO,aAC1B,EACA,EACA,EACA,EACA,MApFW,mCADT",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var gdjs;(function(c){const p=class extends c.RuntimeBehavior{constructor(e,t,s){super(e,t,s);this._physics3D=null;this.character=null;this._slopeClimbingFactor=1;this._slopeClimbingMinNormalZ=Math.cos(Math.PI/4);this._forwardAngle=0;this._hasPressedForwardKey=!1;this._hasPressedBackwardKey=!1;this._hasPressedRightKey=!1;this._hasPressedLeftKey=!1;this._hasPressedJumpKey=!1;this._hasUsedStick=!1;this._stickAngle=0;this._stickForce=0;this._currentForwardSpeed=0;this._currentSidewaysSpeed=0;this._currentFallSpeed=0;this._canJump=!1;this._currentJumpSpeed=0;this._timeSinceCurrentJumpStart=0;this._jumpKeyHeldSinceJumpStart=!1;this._hasReallyMoved=!1;this._oldPhysicsPosition=[0,0];this._wasLeftKeyPressed=!1;this._wasRightKeyPressed=!1;this._wasForwardKeyPressed=!1;this._wasBackwardKeyPressed=!1;this._wasJumpKeyPressed=!1;this._wasStickUsed=!1;this._dontClearInputsBetweenFrames=!1;this.owner3D=s,this._physics3DBehaviorName=t.physics3D,this._sharedData=c.Physics3DSharedData.getSharedData(e.getScene(),t.Physics3D),this._slopeMaxAngle=0,this.setSlopeMaxAngle(t.slopeMaxAngle),this._forwardAcceleration=t.forwardAcceleration,this._forwardDeceleration=t.forwardDeceleration,this._forwardSpeedMax=t.forwardSpeedMax,this._sidewaysAcceleration=t.sidewaysAcceleration,this._sidewaysDeceleration=t.sidewaysDeceleration,this._sidewaysSpeedMax=t.sidewaysSpeedMax,this._gravity=t.gravity,this._maxFallingSpeed=t.fallingSpeedMax,this._jumpSustainTime=t.jumpSustainTime,this._jumpSpeed=this.getJumpSpeedToReach(t.jumpHeight),this._shouldBindObjectAndForwardAngle=t.shouldBindObjectAndForwardAngle}getVec3(e,t,s){const r=this._sharedData._tempVec3;return r.Set(e,t,s),r}getPhysics3D(){if(this._physics3D)return this._physics3D;const e=this.owner.getBehavior(this._physics3DBehaviorName),t=e._sharedData,s=t.jolt,r=new Jolt.ExtendedUpdateSettings;r.mWalkStairsStepUp=this.getVec3(0,0,.4);const a=new Jolt.DefaultBroadPhaseLayerFilter(s.GetObjectVsBroadPhaseLayerFilter(),c.Physics3DSharedData.dynamicBroadPhaseLayerIndex),o=new Jolt.DefaultObjectLayerFilter(s.GetObjectLayerPairFilter(),e.getBodyLayer()),n=new Jolt.BodyFilter,i=new Jolt.ShapeFilter;return this._physics3D={behavior:e,extendedUpdateSettings:r,broadPhaseLayerFilter:a,objectLayerFilter:o,bodyFilter:n,shapeFilter:i},t.registerHook(this),e.bodyUpdater=new c.PhysicsCharacter3DRuntimeBehavior.CharacterBodyUpdater(this),e.recreateBody(),this._forwardAngle=this.owner.getAngle(),this._physics3D}updateFromBehaviorData(e,t){return e.gravity!==t.gravity&&this.setGravity(t.gravity),e.maxFallingSpeed!==t.maxFallingSpeed&&this.setMaxFallingSpeed(t.maxFallingSpeed),e.forwardAcceleration!==t.forwardAcceleration&&this.setForwardAcceleration(t.forwardAcceleration),e.forwardDeceleration!==t.forwardDeceleration&&this.setForwardDeceleration(t.forwardDeceleration),e.forwardSpeedMax!==t.forwardSpeedMax&&this.setForwardSpeedMax(t.forwardSpeedMax),e.sidewaysAcceleration!==t.sidewaysAcceleration&&this.setSidewaysAcceleration(t.sidewaysAcceleration),e.sidewaysDeceleration!==t.sidewaysDeceleration&&this.setSidewaysDeceleration(t.sidewaysDeceleration),e.sidewaysSpeedMax!==t.sidewaysSpeedMax&&this.setSidewaysSpeedMax(t.sidewaysSpeedMax),e.jumpSustainTime!==t.jumpSustainTime&&this.setJumpSustainTime(t.jumpSustainTime),e.jumpHeight!==t.jumpHeight&&this.setJumpSpeed(this.getJumpSpeedToReach(t.jumpHeight)),e.shouldBindObjectAndForwardAngle!==t.shouldBindObjectAndForwardAngle&&this.setShouldBindObjectAndForwardAngle(t.shouldBindObjectAndForwardAngle),!0}getNetworkSyncData(){return this._dontClearInputsBetweenFrames=!1,{...super.getNetworkSyncData(),props:{fwa:this._forwardAngle,fws:this._currentForwardSpeed,sws:this._currentSidewaysSpeed,fs:this._currentFallSpeed,js:this._currentJumpSpeed,cj:this._canJump,lek:this._wasLeftKeyPressed,rik:this._wasRightKeyPressed,upk:this._wasForwardKeyPressed,dok:this._wasBackwardKeyPressed,juk:this._wasJumpKeyPressed,us:this._wasStickUsed,sa:this._stickAngle,sf:this._stickForce,tscjs:this._timeSinceCurrentJumpStart,jkhsjs:this._jumpKeyHeldSinceJumpStart}}}updateFromNetworkSyncData(e){super.updateFromNetworkSyncData(e);const t=e.props;this._forwardAngle=t.fwa,this._currentForwardSpeed=t.fws,this._currentSidewaysSpeed=t.sws,this._currentFallSpeed=t.fs,this._currentJumpSpeed=t.js,this._canJump=t.cj,this._hasPressedForwardKey=t.upk,this._hasPressedBackwardKey=t.dok,this._hasPressedLeftKey=t.lek,this._hasPressedRightKey=t.rik,this._hasPressedJumpKey=t.juk,this._hasUsedStick=t.us,this._stickAngle=t.sa,this._stickForce=t.sf,this._timeSinceCurrentJumpStart=t.tscjs,this._jumpKeyHeldSinceJumpStart=t.jkhsjs,this._dontClearInputsBetweenFrames=!0}getPhysicsPosition(e){const{behavior:t}=this.getPhysics3D();return e.Set(this.owner3D.getCenterXInScene()*this._sharedData.worldInvScale,this.owner3D.getCenterYInScene()*this._sharedData.worldInvScale,this.owner3D.getZ()*this._sharedData.worldInvScale+t._shapeHalfDepth),e}moveObjectToPhysicsPosition(e){const{behavior:t}=this.getPhysics3D();this.owner3D.setCenterXInScene(e.GetX()*this._sharedData.worldScale),this.owner3D.setCenterYInScene(e.GetY()*this._sharedData.worldScale),this.owner3D.setZ((e.GetZ()-t._shapeHalfDepth)*this._sharedData.worldScale)}onDeActivate(){}onActivate(){}onDestroy(){this.onDeActivate()}doStepPreEvents(e){this.getPhysics3D()}doBeforePhysicsStep(e){const{behavior:t,extendedUpdateSettings:s,broadPhaseLayerFilter:r,objectLayerFilter:a,bodyFilter:o,shapeFilter:n}=this.getPhysics3D();if(!this.character||!t._body)return;const d=this._sharedData.worldInvScale,h=this.character.GetPosition().GetX(),l=this.character.GetPosition().GetY(),F=this.character.GetPosition().GetZ();this._shouldBindObjectAndForwardAngle&&(this._forwardAngle=this.owner.getAngle()),this.updateCharacterSpeedFromInputs(e),this._currentJumpSpeed>0&&(this._timeSinceCurrentJumpStart+=e),this._hasPressedJumpKey||(this._jumpKeyHeldSinceJumpStart=!1),this._canJump&&this._hasPressedJumpKey&&!this._jumpKeyHeldSinceJumpStart&&(this._currentJumpSpeed=this._jumpSpeed,this._currentFallSpeed=0,this._canJump=!1,this._jumpKeyHeldSinceJumpStart=!0,this._timeSinceCurrentJumpStart=0),this.isOnFloor()||(this._jumpKeyHeldSinceJumpStart&&this._timeSinceCurrentJumpStart<this._jumpSustainTime||(this._currentJumpSpeed=Math.max(0,this._currentJumpSpeed-this._gravity*e)),this._currentFallSpeed=Math.min(this._maxFallingSpeed,this._currentFallSpeed+this._gravity*e));let m=0,S=0,g=0;if(this.character.IsSupported()&&this.updateGroundVelocity(t,e)){const f=this.character.GetGroundVelocity();m=f.GetX(),S=f.GetY(),g=f.GetZ()}let y=this._currentForwardSpeed,_=this._currentSidewaysSpeed;if(_!==0&&y!==0){const u=Math.hypot(y/this._forwardSpeedMax,_/this._sidewaysSpeedMax);u>1&&(y/=u,_/=u)}y*=d,_*=d;const P=c.toRad(this._forwardAngle),A=Math.cos(P),v=Math.sin(P),b=y*A-_*v,J=y*v+_*A;if(this.character.SetLinearVelocity(this.getVec3(m+b,S+J,(this._currentJumpSpeed-this._currentFallSpeed)*d)),this.isOnFloor()){const u=Math.max(Math.hypot(this.character.GetPosition().GetX()-this._oldPhysicsPosition[0],this.character.GetPosition().GetY()-this._oldPhysicsPosition[1]),Math.hypot(this.character.GetLinearVelocity().GetX(),this.character.GetLinearVelocity().GetY())*e);this._oldPhysicsPosition[0]=this.character.GetPosition().GetX(),this._oldPhysicsPosition[1]=this.character.GetPosition().GetY();const f=Math.max(-.01+1.01*Math.min(-u*this._slopeClimbingFactor,g*e),-this._maxFallingSpeed*d*e);s.mStickToFloorStepDown.Set(0,0,f)}else s.mStickToFloorStepDown.Set(0,0,0);this.character.ExtendedUpdate(e,this.character.GetUp(),s,r,a,o,n,this._sharedData.jolt.GetTempAllocator()),this.isOnFloor()&&(this._canJump=!0,this._currentFallSpeed=0,this._currentJumpSpeed=0),this._wasForwardKeyPressed=this._hasPressedForwardKey,this._wasBackwardKeyPressed=this._hasPressedBackwardKey,this._wasRightKeyPressed=this._hasPressedRightKey,this._wasLeftKeyPressed=this._hasPressedLeftKey,this._wasJumpKeyPressed=this._hasPressedJumpKey,this._wasStickUsed=this._hasPressedJumpKey,this._dontClearInputsBetweenFrames||(this._hasPressedForwardKey=!1,this._hasPressedBackwardKey=!1,this._hasPressedRightKey=!1,this._hasPressedLeftKey=!1,this._hasPressedJumpKey=!1,this._hasUsedStick=!1),this._hasReallyMoved=Math.abs(this.character.GetPosition().GetX()-h)>p.epsilon||Math.abs(this.character.GetPosition().GetY()-l)>p.epsilon||Math.abs(this.character.GetPosition().GetZ()-F)>p.epsilon}updateCharacterSpeedFromInputs(e){let t=0;this._hasPressedBackwardKey!==this._hasPressedForwardKey?this._hasPressedBackwardKey?t=-this._forwardSpeedMax:this._hasPressedForwardKey&&(t=this._forwardSpeedMax):this._hasUsedStick&&(t=-this._forwardSpeedMax*this._stickForce*Math.sin(c.toRad(this._stickAngle))),this._currentForwardSpeed=p.getAcceleratedSpeed(this._currentForwardSpeed,t,this._forwardSpeedMax,this._forwardAcceleration,this._forwardDeceleration,e);let s=0;this._hasPressedLeftKey!==this._hasPressedRightKey?this._hasPressedLeftKey?s=-this._sidewaysSpeedMax:this._hasPressedRightKey&&(s=this._sidewaysSpeedMax):this._hasUsedStick&&(s=this._sidewaysSpeedMax*this._stickForce*Math.cos(c.toRad(this._stickAngle))),this._currentSidewaysSpeed=p.getAcceleratedSpeed(this._currentSidewaysSpeed,s,this._sidewaysSpeedMax,this._sidewaysAcceleration,this._sidewaysDeceleration,e)}static getAcceleratedSpeed(e,t,s,r,a,o){let n=e;return t<0?e<=t?n=Math.min(t,e+a*o):e<=0?n-=Math.max(-s,r*o):n=Math.max(t,e-Math.max(r,a)*o):t>0?e>=t?n=Math.max(t,e-a*o):e>=0?n=Math.min(s,e+r*o):n=Math.min(t,e+Math.max(r,a)*o):(e<0&&(n=Math.min(e+a*o,0)),e>0&&(n=Math.max(e-a*o,0))),n}updateGroundVelocity(e,t){if(!this.character||!e._body)return!1;const r=this._sharedData.worldInvScale;if(!this.character.IsSupported())return!1;const a=this._sharedData.physicsSystem.GetBodyLockInterface().TryGetBody(this.character.GetGroundBodyID()),o=a.IsKinematic()&&a.GetLinearVelocity().Equals(Jolt.Vec3.prototype.sZero())&&a.GetAngularVelocity().Equals(Jolt.Vec3.prototype.sZero());if(o){const h=a.gdjsAssociatedBehavior;if(h){const l=1/t;a.SetLinearVelocity(this.getVec3((h.owner3D.getX()-h._objectOldX)*r*l,(h.owner3D.getY()-h._objectOldY)*r*l,(h.owner3D.getZ()-h._objectOldZ)*r*l)),a.SetAngularVelocity(this.getVec3(0,0,c.toRad(c.evtTools.common.angleDifference(h.owner3D.getAngle(),h._objectOldRotationZ))*l))}}this.character.UpdateGroundVelocity();const n=a.GetAngularVelocity().GetZ();if(n!==0){const h=n*t;this.character.SetRotation(Jolt.Quat.prototype.sEulerAngles(this.getVec3(0,0,this.character.GetRotation().GetRotationAngle(Jolt.Vec3.prototype.sAxisZ())+h))),this._forwardAngle+=c.toDegrees(h)}o&&(a.SetLinearVelocity(Jolt.Vec3.prototype.sZero()),a.SetAngularVelocity(Jolt.Vec3.prototype.sZero()));const i=1*Math.PI/180;return Math.abs(a.GetAngularVelocity().GetX())<i&&Math.abs(a.GetAngularVelocity().GetY())<i}doStepPostEvents(e){}onObjectHotReloaded(){}getSlopeMaxAngle(){return this._slopeMaxAngle}setSlopeMaxAngle(e){e<0||e>=90||(this._slopeMaxAngle=e,e===45?this._slopeClimbingFactor=1:this._slopeClimbingFactor=Math.max(1/1024,Math.tan(c.toRad(e))),this._slopeClimbingMinNormalZ=Math.min(Math.cos(c.toRad(e)),1-1/1024))}getGravity(){return this._gravity}setGravity(e){this._gravity=e}getMaxFallingSpeed(){return this._maxFallingSpeed}setMaxFallingSpeed(e,t=!1){if(t&&!this.isOnFloor()){const s=this._currentFallSpeed-e;s>0&&(this._currentFallSpeed-=s,this._currentJumpSpeed=Math.max(0,this.getCurrentJumpSpeed()-s))}this._maxFallingSpeed=e}getForwardAcceleration(){return this._forwardAcceleration}setForwardAcceleration(e){this._forwardAcceleration=e}getForwardDeceleration(){return this._forwardDeceleration}setForwardDeceleration(e){this._forwardDeceleration=e}getForwardSpeedMax(){return this._forwardSpeedMax}setForwardSpeedMax(e){this._forwardSpeedMax=e}getSidewaysAcceleration(){return this._sidewaysAcceleration}setSidewaysAcceleration(e){this._sidewaysAcceleration=e}getSidewaysDeceleration(){return this._sidewaysDeceleration}setSidewaysDeceleration(e){this._sidewaysDeceleration=e}getSidewaysSpeedMax(){return this._sidewaysSpeedMax}setSidewaysSpeedMax(e){this._sidewaysSpeedMax=e}getJumpSpeed(){return this._jumpSpeed}setJumpSpeed(e){this._jumpSpeed=e}getJumpSustainTime(){return this._jumpSustainTime}setJumpSustainTime(e){this._jumpSustainTime=e}getForwardAngle(){return this._forwardAngle}setForwardAngle(e){this._forwardAngle=e,this._shouldBindObjectAndForwardAngle&&this.owner.setAngle(e)}isForwardAngleAround(e,t){return Math.abs(c.evtTools.common.angleDifference(this._forwardAngle,e))<=t}shouldBindObjectAndForwardAngle(){return this._shouldBindObjectAndForwardAngle}setShouldBindObjectAndForwardAngle(e){this._shouldBindObjectAndForwardAngle=e}getCurrentForwardSpeed(){return this._currentForwardSpeed}setCurrentForwardSpeed(e){this._currentForwardSpeed=e}getCurrentSidewaysSpeed(){return this._currentSidewaysSpeed}setCurrentSidewaysSpeed(e){this._currentSidewaysSpeed=e}getCurrentFallSpeed(){return this._currentFallSpeed}setCurrentFallSpeed(e){this._currentFallSpeed=c.evtTools.common.clamp(e,0,this._maxFallingSpeed)}getCurrentJumpSpeed(){return this._currentJumpSpeed}setCurrentJumpSpeed(e){this._currentJumpSpeed=Math.max(0,e)}canJump(){return this._canJump}setCanJump(){this._canJump=!0}setCanNotAirJump(){(this.isJumping()||this.isFalling())&&(this._canJump=!1)}abortJump(){this.isJumping()&&(this._currentFallSpeed=0,this._currentJumpSpeed=0)}simulateForwardKey(){this._hasPressedForwardKey=!0}wasForwardKeyPressed(){return this._wasForwardKeyPressed}simulateBackwardKey(){this._hasPressedBackwardKey=!0}wasBackwardKeyPressed(){return this._wasBackwardKeyPressed}simulateRightKey(){this._hasPressedRightKey=!0}wasRightKeyPressed(){return this._wasRightKeyPressed}simulateLeftKey(){this._hasPressedLeftKey=!0}wasLeftKeyPressed(){return this._wasLeftKeyPressed}simulateJumpKey(){this._hasPressedJumpKey=!0}wasJumpKeyPressed(){return this._wasJumpKeyPressed}simulateStick(e,t){this._hasUsedStick=!0,this._stickAngle=e,this._stickForce=Math.max(0,Math.min(1,t))}wasStickUsed(){return this._wasStickUsed}getStickAngle(){return this._wasStickUsed?this._stickAngle:0}getStickForce(){return this._wasStickUsed?this._stickForce:0}isOnFloor(){return this.character?this.character.IsSupported()&&this.character.GetGroundNormal().GetZ()>=this._slopeClimbingMinNormalZ&&this._currentJumpSpeed<=this._currentFallSpeed:!1}isOnFloorObject(e){return!e._body||!this.character||!this.isOnFloor()?!1:this.character.GetGroundBodyID().GetIndexAndSequenceNumber()===e._body.GetID().GetIndexAndSequenceNumber()}isJumping(){return this._currentJumpSpeed>0}isFallingWithoutJumping(){return!this.isOnFloor()&&this._currentJumpSpeed===0}isFalling(){return!this.isOnFloor()&&this._currentJumpSpeed<this._currentFallSpeed}isMovingEvenALittle(){return this._hasReallyMoved&&this._currentForwardSpeed!==0||this._currentJumpSpeed!==0||this._currentFallSpeed!==0}getJumpSpeedToReach(e){e=-Math.abs(e);const t=this._gravity,s=this._maxFallingSpeed,r=this._jumpSustainTime,a=s/t,o=h=>Math.sqrt(-h*t*2),n=h=>-t*r+s+Math.sqrt(t*t*r*r-2*h*t-s*s);let i=0,d=0;return a>r?(i=-t*r+Math.sqrt(2*t*t*r*r-4*e*t),d=(t*r+i)/(2*t),d<r?i=o(e):d>a&&(i=n(e))):(i=o(e),d=i/t,d>a&&(i=n(e))),i}};let w=p;w.epsilon=2**-20,c.PhysicsCharacter3DRuntimeBehavior=w,c.registerBehavior("Physics3D::PhysicsCharacter3D",c.PhysicsCharacter3DRuntimeBehavior),function(e){class M{constructor(s){this.characterBehavior=s}createAndAddBody(){const{_slopeMaxAngle:s,owner3D:r,_sharedData:a}=this.characterBehavior,{behavior:o}=this.characterBehavior.getPhysics3D(),n=o.createShape(),i=new Jolt.CharacterVirtualSettings;i.mInnerBodyLayer=o.getBodyLayer(),i.mInnerBodyShape=n,i.mMass=n.GetMassProperties().get_mMass(),i.mMaxSlopeAngle=c.toRad(s),i.mShape=n,i.mUp=Jolt.Vec3.prototype.sAxisZ(),i.mBackFaceMode=Jolt.EBackFaceMode_CollideWithBackFaces;const d=r.getDepth()*a.worldInvScale,h=r.getWidth()*a.worldInvScale,l=r.getHeight()*a.worldInvScale,F=d/2,m=Math.sqrt(h*l)/2;i.mSupportingVolume=new Jolt.Plane(Jolt.Vec3.prototype.sAxisZ(),F-m*(1-Math.cos(c.toRad(Math.min(s+20,70)))));const S=new Jolt.CharacterVirtual(i,this.characterBehavior.getPhysicsPosition(a.getRVec3(0,0,0)),o.getPhysicsRotation(a.getQuat(0,0,0,1)),a.physicsSystem),g=a.physicsSystem.GetBodyLockInterface().TryGetBody(S.GetInnerBodyID());return this.characterBehavior.character=S,g}updateObjectFromBody(){const{behavior:s}=this.characterBehavior.getPhysics3D(),{character:r}=this.characterBehavior;!r||(this.characterBehavior.moveObjectToPhysicsPosition(r.GetPosition()),s.moveObjectToPhysicsRotation(r.GetRotation()))}updateBodyFromObject(){const{behavior:s}=this.characterBehavior.getPhysics3D(),{character:r,owner3D:a,_sharedData:o}=this.characterBehavior;!r||((s._objectOldX!==a.getX()||s._objectOldY!==a.getY()||s._objectOldZ!==a.getZ())&&this.updateCharacterPosition(),(s._objectOldRotationX!==a.getRotationX()||s._objectOldRotationY!==a.getRotationY()||s._objectOldRotationZ!==a.getAngle())&&r.SetRotation(s.getPhysicsRotation(o.getQuat(0,0,0,1))))}updateCharacterPosition(){const{character:s,_sharedData:r}=this.characterBehavior;!s||s.SetPosition(this.characterBehavior.getPhysicsPosition(r.getRVec3(0,0,0)))}recreateShape(){const{behavior:s,broadPhaseLayerFilter:r,objectLayerFilter:a,bodyFilter:o,shapeFilter:n}=this.characterBehavior.getPhysics3D(),{character:i,_sharedData:d}=this.characterBehavior;if(!i)return;const h=s.createShape();!i.SetShape(h,Number.MAX_VALUE,r,a,o,n,d.jolt.GetTempAllocator())||(i.SetInnerBodyShape(h),i.SetMass(h.GetMassProperties().get_mMass()),this.updateCharacterPosition())}}e.CharacterBodyUpdater=M}(w=c.PhysicsCharacter3DRuntimeBehavior||(c.PhysicsCharacter3DRuntimeBehavior={}))})(gdjs||(gdjs={}));
|
|
2
|
+
//# sourceMappingURL=PhysicsCharacter3DRuntimeBehavior.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../GDevelop/Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.ts"],
|
|
4
|
+
"sourcesContent": ["/// <reference path=\"./jolt-physics.d.ts\" />\n\nnamespace Jolt {\n export interface Body {\n gdjsAssociatedCharacterBehavior: gdjs.PhysicsCharacter3DRuntimeBehavior | null;\n }\n}\n\nnamespace gdjs {\n interface PhysicsCharacter3DNetworkSyncDataType {\n fwa: float;\n fws: float;\n sws: float;\n fs: float;\n js: float;\n cj: boolean;\n lek: boolean;\n rik: boolean;\n upk: boolean;\n dok: boolean;\n juk: boolean;\n us: boolean;\n sa: float;\n sf: float;\n tscjs: float;\n jkhsjs: boolean;\n }\n\n export interface PhysicsCharacter3DNetworkSyncData\n extends BehaviorNetworkSyncData {\n props: PhysicsCharacter3DNetworkSyncDataType;\n }\n\n type Physics3D = {\n behavior: gdjs.Physics3DRuntimeBehavior;\n extendedUpdateSettings: Jolt.ExtendedUpdateSettings;\n broadPhaseLayerFilter: Jolt.BroadPhaseLayerFilter;\n objectLayerFilter: Jolt.ObjectLayerFilter;\n bodyFilter: Jolt.BodyFilter;\n shapeFilter: Jolt.ShapeFilter;\n };\n\n export class PhysicsCharacter3DRuntimeBehavior\n extends gdjs.RuntimeBehavior\n implements gdjs.Physics3DRuntimeBehavior.Physics3DHook {\n owner3D: gdjs.RuntimeObject3D;\n private _physics3DBehaviorName: string;\n private _physics3D: Physics3D | null = null;\n character: Jolt.CharacterVirtual | null = null;\n /**\n * sharedData is a reference to the shared data of the scene, that registers\n * every physics behavior that is created so that collisions can be cleared\n * before stepping the world.\n */\n _sharedData: gdjs.Physics3DSharedData;\n\n // TODO Should there be angle were the character can climb but will slip?\n _slopeMaxAngle: float;\n private _slopeClimbingFactor: float = 1;\n private _slopeClimbingMinNormalZ: float = Math.cos(Math.PI / 4);\n private _forwardAngle: float = 0;\n private _shouldBindObjectAndForwardAngle: boolean;\n private _forwardAcceleration: float;\n private _forwardDeceleration: float;\n private _forwardSpeedMax: float;\n private _sidewaysAcceleration: float;\n private _sidewaysDeceleration: float;\n private _sidewaysSpeedMax: float;\n private _gravity: float;\n private _maxFallingSpeed: float;\n private _jumpSpeed: float;\n private _jumpSustainTime: float;\n\n private _hasPressedForwardKey: boolean = false;\n private _hasPressedBackwardKey: boolean = false;\n private _hasPressedRightKey: boolean = false;\n private _hasPressedLeftKey: boolean = false;\n private _hasPressedJumpKey: boolean = false;\n private _hasUsedStick: boolean = false;\n private _stickAngle: float = 0;\n private _stickForce: float = 0;\n private _currentForwardSpeed: float = 0;\n private _currentSidewaysSpeed: float = 0;\n private _currentFallSpeed: float = 0;\n private _canJump: boolean = false;\n private _currentJumpSpeed: float = 0;\n private _timeSinceCurrentJumpStart: float = 0;\n private _jumpKeyHeldSinceJumpStart: boolean = false;\n private _hasReallyMoved: boolean = false;\n private _oldPhysicsPosition: FloatPoint = [0, 0];\n\n // This is useful for extensions that need to know\n // which keys were pressed and doesn't know the mapping\n // done by the scene events.\n private _wasLeftKeyPressed: boolean = false;\n private _wasRightKeyPressed: boolean = false;\n private _wasForwardKeyPressed: boolean = false;\n private _wasBackwardKeyPressed: boolean = false;\n private _wasJumpKeyPressed: boolean = false;\n private _wasStickUsed: boolean = false;\n\n // This is useful when the object is synchronized by an external source\n // like in a multiplayer game, and we want to be able to predict the\n // movement of the object, even if the inputs are not updated every frame.\n private _dontClearInputsBetweenFrames: boolean = false;\n\n /**\n * A very small value compare to 1 pixel, yet very huge compare to rounding errors.\n */\n private static readonly epsilon = 2 ** -20;\n\n constructor(\n instanceContainer: gdjs.RuntimeInstanceContainer,\n behaviorData,\n owner: gdjs.RuntimeObject3D\n ) {\n super(instanceContainer, behaviorData, owner);\n this.owner3D = owner;\n this._physics3DBehaviorName = behaviorData.physics3D;\n this._sharedData = gdjs.Physics3DSharedData.getSharedData(\n instanceContainer.getScene(),\n behaviorData.Physics3D\n );\n\n this._slopeMaxAngle = 0;\n this.setSlopeMaxAngle(behaviorData.slopeMaxAngle);\n this._forwardAcceleration = behaviorData.forwardAcceleration;\n this._forwardDeceleration = behaviorData.forwardDeceleration;\n this._forwardSpeedMax = behaviorData.forwardSpeedMax;\n this._sidewaysAcceleration = behaviorData.sidewaysAcceleration;\n this._sidewaysDeceleration = behaviorData.sidewaysDeceleration;\n this._sidewaysSpeedMax = behaviorData.sidewaysSpeedMax;\n this._gravity = behaviorData.gravity;\n this._maxFallingSpeed = behaviorData.fallingSpeedMax;\n this._jumpSustainTime = behaviorData.jumpSustainTime;\n this._jumpSpeed = this.getJumpSpeedToReach(behaviorData.jumpHeight);\n this._shouldBindObjectAndForwardAngle =\n behaviorData.shouldBindObjectAndForwardAngle;\n }\n\n private getVec3(x: float, y: float, z: float): Jolt.Vec3 {\n const tempVec3 = this._sharedData._tempVec3;\n tempVec3.Set(x, y, z);\n return tempVec3;\n }\n\n getPhysics3D(): Physics3D {\n if (this._physics3D) {\n return this._physics3D;\n }\n const behavior = this.owner.getBehavior(\n this._physics3DBehaviorName\n ) as gdjs.Physics3DRuntimeBehavior;\n\n const sharedData = behavior._sharedData;\n const jolt = sharedData.jolt;\n const extendedUpdateSettings = new Jolt.ExtendedUpdateSettings();\n extendedUpdateSettings.mWalkStairsStepUp = this.getVec3(0, 0, 0.4);\n const broadPhaseLayerFilter = new Jolt.DefaultBroadPhaseLayerFilter(\n jolt.GetObjectVsBroadPhaseLayerFilter(),\n gdjs.Physics3DSharedData.dynamicBroadPhaseLayerIndex\n );\n const objectLayerFilter = new Jolt.DefaultObjectLayerFilter(\n jolt.GetObjectLayerPairFilter(),\n behavior.getBodyLayer()\n );\n const bodyFilter = new Jolt.BodyFilter();\n const shapeFilter = new Jolt.ShapeFilter();\n\n this._physics3D = {\n behavior,\n extendedUpdateSettings,\n broadPhaseLayerFilter,\n objectLayerFilter,\n bodyFilter,\n shapeFilter,\n };\n sharedData.registerHook(this);\n\n behavior.bodyUpdater = new gdjs.PhysicsCharacter3DRuntimeBehavior.CharacterBodyUpdater(\n this\n );\n behavior.recreateBody();\n\n // Always begin in the direction of the object.\n this._forwardAngle = this.owner.getAngle();\n\n return this._physics3D;\n }\n\n updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {\n if (oldBehaviorData.gravity !== newBehaviorData.gravity) {\n this.setGravity(newBehaviorData.gravity);\n }\n if (oldBehaviorData.maxFallingSpeed !== newBehaviorData.maxFallingSpeed) {\n this.setMaxFallingSpeed(newBehaviorData.maxFallingSpeed);\n }\n if (\n oldBehaviorData.forwardAcceleration !==\n newBehaviorData.forwardAcceleration\n ) {\n this.setForwardAcceleration(newBehaviorData.forwardAcceleration);\n }\n if (\n oldBehaviorData.forwardDeceleration !==\n newBehaviorData.forwardDeceleration\n ) {\n this.setForwardDeceleration(newBehaviorData.forwardDeceleration);\n }\n if (oldBehaviorData.forwardSpeedMax !== newBehaviorData.forwardSpeedMax) {\n this.setForwardSpeedMax(newBehaviorData.forwardSpeedMax);\n }\n if (\n oldBehaviorData.sidewaysAcceleration !==\n newBehaviorData.sidewaysAcceleration\n ) {\n this.setSidewaysAcceleration(newBehaviorData.sidewaysAcceleration);\n }\n if (\n oldBehaviorData.sidewaysDeceleration !==\n newBehaviorData.sidewaysDeceleration\n ) {\n this.setSidewaysDeceleration(newBehaviorData.sidewaysDeceleration);\n }\n if (\n oldBehaviorData.sidewaysSpeedMax !== newBehaviorData.sidewaysSpeedMax\n ) {\n this.setSidewaysSpeedMax(newBehaviorData.sidewaysSpeedMax);\n }\n if (oldBehaviorData.jumpSustainTime !== newBehaviorData.jumpSustainTime) {\n this.setJumpSustainTime(newBehaviorData.jumpSustainTime);\n }\n if (oldBehaviorData.jumpHeight !== newBehaviorData.jumpHeight) {\n this.setJumpSpeed(this.getJumpSpeedToReach(newBehaviorData.jumpHeight));\n }\n if (\n oldBehaviorData.shouldBindObjectAndForwardAngle !==\n newBehaviorData.shouldBindObjectAndForwardAngle\n ) {\n this.setShouldBindObjectAndForwardAngle(\n newBehaviorData.shouldBindObjectAndForwardAngle\n );\n }\n return true;\n }\n\n getNetworkSyncData(): PhysicsCharacter3DNetworkSyncData {\n // This method is called, so we are synchronizing this object.\n // Let's clear the inputs between frames as we control it.\n this._dontClearInputsBetweenFrames = false;\n\n return {\n ...super.getNetworkSyncData(),\n props: {\n fwa: this._forwardAngle,\n fws: this._currentForwardSpeed,\n sws: this._currentSidewaysSpeed,\n fs: this._currentFallSpeed,\n js: this._currentJumpSpeed,\n cj: this._canJump,\n lek: this._wasLeftKeyPressed,\n rik: this._wasRightKeyPressed,\n upk: this._wasForwardKeyPressed,\n dok: this._wasBackwardKeyPressed,\n juk: this._wasJumpKeyPressed,\n us: this._wasStickUsed,\n sa: this._stickAngle,\n sf: this._stickForce,\n tscjs: this._timeSinceCurrentJumpStart,\n jkhsjs: this._jumpKeyHeldSinceJumpStart,\n },\n };\n }\n\n updateFromNetworkSyncData(\n networkSyncData: PhysicsCharacter3DNetworkSyncData\n ) {\n super.updateFromNetworkSyncData(networkSyncData);\n\n const behaviorSpecificProps = networkSyncData.props;\n this._forwardAngle = behaviorSpecificProps.fwa;\n this._currentForwardSpeed = behaviorSpecificProps.fws;\n this._currentSidewaysSpeed = behaviorSpecificProps.sws;\n this._currentFallSpeed = behaviorSpecificProps.fs;\n this._currentJumpSpeed = behaviorSpecificProps.js;\n this._canJump = behaviorSpecificProps.cj;\n this._hasPressedForwardKey = behaviorSpecificProps.upk;\n this._hasPressedBackwardKey = behaviorSpecificProps.dok;\n this._hasPressedLeftKey = behaviorSpecificProps.lek;\n this._hasPressedRightKey = behaviorSpecificProps.rik;\n this._hasPressedJumpKey = behaviorSpecificProps.juk;\n this._hasUsedStick = behaviorSpecificProps.us;\n this._stickAngle = behaviorSpecificProps.sa;\n this._stickForce = behaviorSpecificProps.sf;\n this._timeSinceCurrentJumpStart = behaviorSpecificProps.tscjs;\n this._jumpKeyHeldSinceJumpStart = behaviorSpecificProps.jkhsjs;\n\n // When the object is synchronized from the network, the inputs must not be cleared.\n this._dontClearInputsBetweenFrames = true;\n }\n\n getPhysicsPosition(result: Jolt.RVec3): Jolt.RVec3 {\n const { behavior } = this.getPhysics3D();\n // The character origin is at its feet:\n // - the center is used for X and Y because Box3D origin is at the top-left corner\n // - the origin is used for Z because, when the character is made smaller,\n // it must stay on the ground and not fell from its old size.\n result.Set(\n this.owner3D.getCenterXInScene() * this._sharedData.worldInvScale,\n this.owner3D.getCenterYInScene() * this._sharedData.worldInvScale,\n this.owner3D.getZ() * this._sharedData.worldInvScale +\n behavior._shapeHalfDepth\n );\n return result;\n }\n\n moveObjectToPhysicsPosition(physicsPosition: Jolt.RVec3): void {\n const { behavior } = this.getPhysics3D();\n this.owner3D.setCenterXInScene(\n physicsPosition.GetX() * this._sharedData.worldScale\n );\n this.owner3D.setCenterYInScene(\n physicsPosition.GetY() * this._sharedData.worldScale\n );\n this.owner3D.setZ(\n (physicsPosition.GetZ() - behavior._shapeHalfDepth) *\n this._sharedData.worldScale\n );\n }\n\n onDeActivate() {}\n\n onActivate() {}\n\n onDestroy() {\n this.onDeActivate();\n }\n\n doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {\n // Trigger createAndAddBody()\n this.getPhysics3D();\n }\n\n doBeforePhysicsStep(timeDelta: float): void {\n const {\n behavior,\n extendedUpdateSettings,\n broadPhaseLayerFilter,\n objectLayerFilter,\n bodyFilter,\n shapeFilter,\n } = this.getPhysics3D();\n if (!this.character) {\n return;\n }\n const characterBody = behavior._body;\n if (!characterBody) {\n return;\n }\n const worldInvScale = this._sharedData.worldInvScale;\n\n const oldX = this.character.GetPosition().GetX();\n const oldY = this.character.GetPosition().GetY();\n const oldZ = this.character.GetPosition().GetZ();\n\n if (this._shouldBindObjectAndForwardAngle) {\n this._forwardAngle = this.owner.getAngle();\n }\n\n this.updateCharacterSpeedFromInputs(timeDelta);\n\n if (this._currentJumpSpeed > 0) {\n this._timeSinceCurrentJumpStart += timeDelta;\n }\n // Check if the jump key is continuously held since\n // the beginning of the jump.\n if (!this._hasPressedJumpKey) {\n this._jumpKeyHeldSinceJumpStart = false;\n }\n if (\n this._canJump &&\n this._hasPressedJumpKey &&\n // Avoid the character to jump in loop when the jump key is held.\n !this._jumpKeyHeldSinceJumpStart\n ) {\n this._currentJumpSpeed = this._jumpSpeed;\n this._currentFallSpeed = 0;\n this._canJump = false;\n this._jumpKeyHeldSinceJumpStart = true;\n this._timeSinceCurrentJumpStart = 0;\n }\n if (!this.isOnFloor()) {\n // Decrease jump speed after the (optional) jump sustain time is over.\n const sustainJumpSpeed =\n this._jumpKeyHeldSinceJumpStart &&\n this._timeSinceCurrentJumpStart < this._jumpSustainTime;\n if (!sustainJumpSpeed) {\n this._currentJumpSpeed = Math.max(\n 0,\n this._currentJumpSpeed - this._gravity * timeDelta\n );\n }\n this._currentFallSpeed = Math.min(\n this._maxFallingSpeed,\n this._currentFallSpeed + this._gravity * timeDelta\n );\n }\n\n // Follow moving platforms.\n let groundVelocityX = 0;\n let groundVelocityY = 0;\n let groundVelocityZ = 0;\n if (this.character.IsSupported()) {\n const shouldFollow = this.updateGroundVelocity(behavior, timeDelta);\n if (shouldFollow) {\n const groundVelocity = this.character.GetGroundVelocity();\n groundVelocityX = groundVelocity.GetX();\n groundVelocityY = groundVelocity.GetY();\n groundVelocityZ = groundVelocity.GetZ();\n }\n }\n\n // Update walking speed\n let forwardSpeed = this._currentForwardSpeed;\n let sidewaysSpeed = this._currentSidewaysSpeed;\n if (sidewaysSpeed !== 0 && forwardSpeed !== 0) {\n // It avoids the speed vector to go outside of an ellipse.\n const speedNormalizationInverseRatio = Math.hypot(\n forwardSpeed / this._forwardSpeedMax,\n sidewaysSpeed / this._sidewaysSpeedMax\n );\n if (speedNormalizationInverseRatio > 1) {\n forwardSpeed /= speedNormalizationInverseRatio;\n sidewaysSpeed /= speedNormalizationInverseRatio;\n }\n }\n forwardSpeed *= worldInvScale;\n sidewaysSpeed *= worldInvScale;\n const angle = gdjs.toRad(this._forwardAngle);\n const cosA = Math.cos(angle);\n const sinA = Math.sin(angle);\n const speedX = forwardSpeed * cosA - sidewaysSpeed * sinA;\n const speedY = forwardSpeed * sinA + sidewaysSpeed * cosA;\n this.character.SetLinearVelocity(\n this.getVec3(\n groundVelocityX + speedX,\n groundVelocityY + speedY,\n // The ground velocity is not added on Z as it's handled by mStickToFloorStepDown.\n (this._currentJumpSpeed - this._currentFallSpeed) * worldInvScale\n )\n );\n\n if (this.isOnFloor()) {\n // Keep the character on the floor when walking down-hill.\n const walkingDistance = Math.max(\n Math.hypot(\n this.character.GetPosition().GetX() - this._oldPhysicsPosition[0],\n this.character.GetPosition().GetY() - this._oldPhysicsPosition[1]\n ),\n Math.hypot(\n this.character.GetLinearVelocity().GetX(),\n this.character.GetLinearVelocity().GetY()\n ) * timeDelta\n );\n this._oldPhysicsPosition[0] = this.character.GetPosition().GetX();\n this._oldPhysicsPosition[1] = this.character.GetPosition().GetY();\n\n // A safety margin is taken as if the ground normal is too steep, the\n // character will fall next step anyway.\n const stickToFloorStepDownZ = Math.max(\n -0.01 +\n 1.01 *\n Math.min(\n // Follow the platform slope...\n -walkingDistance * this._slopeClimbingFactor,\n // ...and follow a platform falling...\n groundVelocityZ * timeDelta\n ),\n // ...but never fall faster than the max fall speed.\n -this._maxFallingSpeed * worldInvScale * timeDelta\n );\n extendedUpdateSettings.mStickToFloorStepDown.Set(\n 0,\n 0,\n stickToFloorStepDownZ\n );\n } else {\n extendedUpdateSettings.mStickToFloorStepDown.Set(0, 0, 0);\n }\n\n this.character.ExtendedUpdate(\n timeDelta,\n this.character.GetUp(),\n extendedUpdateSettings,\n broadPhaseLayerFilter,\n objectLayerFilter,\n bodyFilter,\n shapeFilter,\n this._sharedData.jolt.GetTempAllocator()\n );\n\n if (this.isOnFloor()) {\n this._canJump = true;\n this._currentFallSpeed = 0;\n this._currentJumpSpeed = 0;\n }\n\n this._wasForwardKeyPressed = this._hasPressedForwardKey;\n this._wasBackwardKeyPressed = this._hasPressedBackwardKey;\n this._wasRightKeyPressed = this._hasPressedRightKey;\n this._wasLeftKeyPressed = this._hasPressedLeftKey;\n this._wasJumpKeyPressed = this._hasPressedJumpKey;\n this._wasStickUsed = this._hasPressedJumpKey;\n\n if (!this._dontClearInputsBetweenFrames) {\n this._hasPressedForwardKey = false;\n this._hasPressedBackwardKey = false;\n this._hasPressedRightKey = false;\n this._hasPressedLeftKey = false;\n this._hasPressedJumpKey = false;\n this._hasUsedStick = false;\n }\n\n this._hasReallyMoved =\n Math.abs(this.character.GetPosition().GetX() - oldX) >\n PhysicsCharacter3DRuntimeBehavior.epsilon ||\n Math.abs(this.character.GetPosition().GetY() - oldY) >\n PhysicsCharacter3DRuntimeBehavior.epsilon ||\n Math.abs(this.character.GetPosition().GetZ() - oldZ) >\n PhysicsCharacter3DRuntimeBehavior.epsilon;\n }\n\n private updateCharacterSpeedFromInputs(timeDelta: float) {\n /** A stick with a half way force targets a lower speed than the maximum speed. */\n let targetedForwardSpeed = 0;\n // Change the speed according to the player's input.\n // TODO Give priority to the last key for faster reaction time.\n if (this._hasPressedBackwardKey !== this._hasPressedForwardKey) {\n if (this._hasPressedBackwardKey) {\n targetedForwardSpeed = -this._forwardSpeedMax;\n } else if (this._hasPressedForwardKey) {\n targetedForwardSpeed = this._forwardSpeedMax;\n }\n } else if (this._hasUsedStick) {\n targetedForwardSpeed =\n -this._forwardSpeedMax *\n this._stickForce *\n Math.sin(gdjs.toRad(this._stickAngle));\n }\n this._currentForwardSpeed = PhysicsCharacter3DRuntimeBehavior.getAcceleratedSpeed(\n this._currentForwardSpeed,\n targetedForwardSpeed,\n this._forwardSpeedMax,\n this._forwardAcceleration,\n this._forwardDeceleration,\n timeDelta\n );\n /** A stick with a half way force targets a lower speed than the maximum speed. */\n let targetedSidewaysSpeed = 0;\n if (this._hasPressedLeftKey !== this._hasPressedRightKey) {\n if (this._hasPressedLeftKey) {\n targetedSidewaysSpeed = -this._sidewaysSpeedMax;\n } else if (this._hasPressedRightKey) {\n targetedSidewaysSpeed = this._sidewaysSpeedMax;\n }\n } else if (this._hasUsedStick) {\n targetedSidewaysSpeed =\n this._sidewaysSpeedMax *\n this._stickForce *\n Math.cos(gdjs.toRad(this._stickAngle));\n }\n this._currentSidewaysSpeed = PhysicsCharacter3DRuntimeBehavior.getAcceleratedSpeed(\n this._currentSidewaysSpeed,\n targetedSidewaysSpeed,\n this._sidewaysSpeedMax,\n this._sidewaysAcceleration,\n this._sidewaysDeceleration,\n timeDelta\n );\n }\n\n private static getAcceleratedSpeed(\n currentSpeed: float,\n targetedSpeed: float,\n speedMax: float,\n acceleration: float,\n deceleration: float,\n timeDelta: float\n ): float {\n let newSpeed = currentSpeed;\n if (targetedSpeed < 0) {\n if (currentSpeed <= targetedSpeed) {\n // Reduce the speed to match the stick force.\n newSpeed = Math.min(\n targetedSpeed,\n currentSpeed + deceleration * timeDelta\n );\n } else if (currentSpeed <= 0) {\n // Accelerate\n newSpeed -= Math.max(-speedMax, acceleration * timeDelta);\n } else {\n // Turn back at least as fast as it would stop.\n newSpeed = Math.max(\n targetedSpeed,\n currentSpeed - Math.max(acceleration, deceleration) * timeDelta\n );\n }\n } else if (targetedSpeed > 0) {\n if (currentSpeed >= targetedSpeed) {\n // Reduce the speed to match the stick force.\n newSpeed = Math.max(\n targetedSpeed,\n currentSpeed - deceleration * timeDelta\n );\n } else if (currentSpeed >= 0) {\n // Accelerate\n newSpeed = Math.min(\n speedMax,\n currentSpeed + acceleration * timeDelta\n );\n } else {\n // Turn back at least as fast as it would stop.\n newSpeed = Math.min(\n targetedSpeed,\n currentSpeed + Math.max(acceleration, deceleration) * timeDelta\n );\n }\n } else {\n // Decelerate and stop.\n if (currentSpeed < 0) {\n newSpeed = Math.min(currentSpeed + deceleration * timeDelta, 0);\n }\n if (currentSpeed > 0) {\n newSpeed = Math.max(currentSpeed - deceleration * timeDelta, 0);\n }\n }\n return newSpeed;\n }\n\n private updateGroundVelocity(\n behavior: Physics3DRuntimeBehavior,\n timeDelta: float\n ): boolean {\n if (!this.character) {\n return false;\n }\n const characterBody = behavior._body;\n if (!characterBody) {\n return false;\n }\n const worldInvScale = this._sharedData.worldInvScale;\n\n if (!this.character.IsSupported()) {\n return false;\n }\n\n const groundBody = this._sharedData.physicsSystem\n .GetBodyLockInterface()\n .TryGetBody(this.character.GetGroundBodyID());\n\n const stillKinematicPlatform =\n groundBody.IsKinematic() &&\n groundBody.GetLinearVelocity().Equals(Jolt.Vec3.prototype.sZero()) &&\n groundBody.GetAngularVelocity().Equals(Jolt.Vec3.prototype.sZero());\n if (stillKinematicPlatform) {\n const groundBehavior = groundBody.gdjsAssociatedBehavior;\n if (groundBehavior) {\n const inverseTimeDelta = 1 / timeDelta;\n // The platform may be moved by position changes instead of velocity.\n // Emulate a velocity from the position changes.\n groundBody.SetLinearVelocity(\n this.getVec3(\n (groundBehavior.owner3D.getX() - groundBehavior._objectOldX) *\n worldInvScale *\n inverseTimeDelta,\n (groundBehavior.owner3D.getY() - groundBehavior._objectOldY) *\n worldInvScale *\n inverseTimeDelta,\n (groundBehavior.owner3D.getZ() - groundBehavior._objectOldZ) *\n worldInvScale *\n inverseTimeDelta\n )\n );\n groundBody.SetAngularVelocity(\n this.getVec3(\n 0,\n 0,\n gdjs.toRad(\n gdjs.evtTools.common.angleDifference(\n groundBehavior.owner3D.getAngle(),\n groundBehavior._objectOldRotationZ\n )\n ) * inverseTimeDelta\n )\n );\n }\n }\n this.character.UpdateGroundVelocity();\n\n const groundAngularVelocityZ = groundBody.GetAngularVelocity().GetZ();\n if (groundAngularVelocityZ !== 0) {\n // Make the character rotate with the platform on Z axis.\n const angleDelta = groundAngularVelocityZ * timeDelta;\n this.character.SetRotation(\n Jolt.Quat.prototype.sEulerAngles(\n this.getVec3(\n 0,\n 0,\n this.character\n .GetRotation()\n .GetRotationAngle(Jolt.Vec3.prototype.sAxisZ()) + angleDelta\n )\n )\n );\n // Also update the forward angle to make sure it stays the same\n // relatively to the object angle.\n this._forwardAngle += gdjs.toDegrees(angleDelta);\n }\n if (stillKinematicPlatform) {\n groundBody.SetLinearVelocity(Jolt.Vec3.prototype.sZero());\n groundBody.SetAngularVelocity(Jolt.Vec3.prototype.sZero());\n }\n\n // Characters should not try to magnet on a body that rolls on the ground.\n const rollingSpeedMax = (1 * Math.PI) / 180;\n const shouldFollow =\n Math.abs(groundBody.GetAngularVelocity().GetX()) < rollingSpeedMax &&\n Math.abs(groundBody.GetAngularVelocity().GetY()) < rollingSpeedMax;\n return shouldFollow;\n }\n\n doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {}\n\n onObjectHotReloaded() {}\n\n /**\n * Get maximum angle of a slope for the Character to run on it as a floor.\n * @returns the slope maximum angle, in degrees.\n */\n getSlopeMaxAngle(): float {\n return this._slopeMaxAngle;\n }\n\n /**\n * Set the maximum slope angle of the Character.\n * @param slopeMaxAngle The new maximum slope angle.\n */\n setSlopeMaxAngle(slopeMaxAngle: float): void {\n if (slopeMaxAngle < 0 || slopeMaxAngle >= 90) {\n return;\n }\n this._slopeMaxAngle = slopeMaxAngle;\n\n //Avoid rounding errors\n if (slopeMaxAngle === 45) {\n this._slopeClimbingFactor = 1;\n } else {\n // Avoid a `_slopeClimbingFactor` set to exactly 0.\n // Otherwise, this can lead the floor finding functions to consider\n // a floor to be \"too high\" to reach, even if the object is very slightly\n // inside it, which can happen because of rounding errors.\n // See \"Floating-point error mitigations\" tests.\n this._slopeClimbingFactor = Math.max(\n 1 / 1024,\n Math.tan(gdjs.toRad(slopeMaxAngle))\n );\n }\n // The floor is in 3D but to go back to 2D trigonometry, we can take the\n // 2D space generated by the floor normal and the Z axis, given that:\n // - The normal keeps the same Z coordinate (as the Z axis is included in the 2D space)\n // - The normal keeps the same length (as the normal is included in the 2D space)\n this._slopeClimbingMinNormalZ = Math.min(\n Math.cos(gdjs.toRad(slopeMaxAngle)),\n 1 - 1 / 1024\n );\n }\n\n /**\n * Get the gravity of the Character.\n * @returns The current gravity.\n */\n getGravity(): float {\n return this._gravity;\n }\n\n /**\n * Set the gravity of the Character.\n * @param gravity The new gravity.\n */\n setGravity(gravity: float): void {\n this._gravity = gravity;\n }\n\n /**\n * Get the maximum falling speed of the Character.\n * @returns The maximum falling speed.\n */\n getMaxFallingSpeed(): float {\n return this._maxFallingSpeed;\n }\n\n /**\n * Set the maximum falling speed of the Character.\n * @param maxFallingSpeed The maximum falling speed.\n * @param tryToPreserveAirSpeed If true and if jumping, tune the current\n * jump speed to preserve the overall speed in the air.\n */\n setMaxFallingSpeed(\n maxFallingSpeed: float,\n tryToPreserveAirSpeed: boolean = false\n ): void {\n if (tryToPreserveAirSpeed && !this.isOnFloor()) {\n // If the falling speed is too high compared to the new max falling speed,\n // reduce it and adapt the jump speed to preserve the overall vertical speed.\n const fallingSpeedOverflow = this._currentFallSpeed - maxFallingSpeed;\n if (fallingSpeedOverflow > 0) {\n this._currentFallSpeed -= fallingSpeedOverflow;\n this._currentJumpSpeed = Math.max(\n 0,\n this.getCurrentJumpSpeed() - fallingSpeedOverflow\n );\n }\n }\n this._maxFallingSpeed = maxFallingSpeed;\n }\n\n /**\n * Get the forward acceleration value of the Character.\n * @returns The current acceleration.\n */\n getForwardAcceleration(): float {\n return this._forwardAcceleration;\n }\n\n /**\n * Set the forward acceleration of the Character.\n * @param forwardAcceleration The new acceleration.\n */\n setForwardAcceleration(forwardAcceleration: float): void {\n this._forwardAcceleration = forwardAcceleration;\n }\n\n /**\n * Get the forward deceleration of the Character.\n * @returns The current deceleration.\n */\n getForwardDeceleration(): float {\n return this._forwardDeceleration;\n }\n\n /**\n * Set the forward deceleration of the Character.\n * @param forwardDeceleration The new deceleration.\n */\n setForwardDeceleration(forwardDeceleration: float): void {\n this._forwardDeceleration = forwardDeceleration;\n }\n\n /**\n * Get the forward maximum speed of the Character.\n * @returns The maximum speed.\n */\n getForwardSpeedMax(): float {\n return this._forwardSpeedMax;\n }\n\n /**\n * Set the forward maximum speed of the Character.\n * @param forwardSpeedMax The new maximum speed.\n */\n setForwardSpeedMax(forwardSpeedMax: float): void {\n this._forwardSpeedMax = forwardSpeedMax;\n }\n\n /**\n * Get the sideways acceleration value of the Character.\n * @returns The current acceleration.\n */\n getSidewaysAcceleration(): float {\n return this._sidewaysAcceleration;\n }\n\n /**\n * Set the sideways acceleration of the Character.\n * @param sidewaysAcceleration The new acceleration.\n */\n setSidewaysAcceleration(sidewaysAcceleration: float): void {\n this._sidewaysAcceleration = sidewaysAcceleration;\n }\n\n /**\n * Get the sideways deceleration of the Character.\n * @returns The current deceleration.\n */\n getSidewaysDeceleration(): float {\n return this._sidewaysDeceleration;\n }\n\n /**\n * Set the sideways deceleration of the Character.\n * @param sidewaysDeceleration The new deceleration.\n */\n setSidewaysDeceleration(sidewaysDeceleration: float): void {\n this._sidewaysDeceleration = sidewaysDeceleration;\n }\n\n /**\n * Get the sideways maximum speed of the Character.\n * @returns The maximum speed.\n */\n getSidewaysSpeedMax(): float {\n return this._sidewaysSpeedMax;\n }\n\n /**\n * Set the sideways maximum speed of the Character.\n * @param sidewaysSpeedMax The new maximum speed.\n */\n setSidewaysSpeedMax(sidewaysSpeedMax: float): void {\n this._sidewaysSpeedMax = sidewaysSpeedMax;\n }\n\n /**\n * Get the jump speed of the Character.\n * @returns The jump speed.\n */\n getJumpSpeed(): float {\n return this._jumpSpeed;\n }\n\n /**\n * Set the jump speed of the Character.\n * @param jumpSpeed The new jump speed.\n */\n setJumpSpeed(jumpSpeed: float): void {\n this._jumpSpeed = jumpSpeed;\n }\n\n /**\n * Get the jump sustain time of the Character.\n * @returns The jump sustain time.\n */\n getJumpSustainTime(): float {\n return this._jumpSustainTime;\n }\n\n /**\n * Set the jump sustain time of the Character.\n * @param jumpSpeed The new jump sustain time.\n */\n setJumpSustainTime(jumpSustainTime: float): void {\n this._jumpSustainTime = jumpSustainTime;\n }\n\n getForwardAngle(): float {\n return this._forwardAngle;\n }\n\n setForwardAngle(angle: float): void {\n this._forwardAngle = angle;\n if (this._shouldBindObjectAndForwardAngle) {\n this.owner.setAngle(angle);\n }\n }\n\n isForwardAngleAround(degreeAngle: float, tolerance: float) {\n return (\n Math.abs(\n gdjs.evtTools.common.angleDifference(this._forwardAngle, degreeAngle)\n ) <= tolerance\n );\n }\n\n shouldBindObjectAndForwardAngle(): boolean {\n return this._shouldBindObjectAndForwardAngle;\n }\n\n setShouldBindObjectAndForwardAngle(\n shouldBindObjectAndForwardAngle: boolean\n ): void {\n this._shouldBindObjectAndForwardAngle = shouldBindObjectAndForwardAngle;\n }\n\n /**\n * Get the current speed of the Character.\n * @returns The current speed.\n */\n getCurrentForwardSpeed(): float {\n return this._currentForwardSpeed;\n }\n\n /**\n * Set the current speed of the Character.\n * @param currentForwardSpeed The current speed.\n */\n setCurrentForwardSpeed(currentForwardSpeed: float): void {\n this._currentForwardSpeed = currentForwardSpeed;\n }\n\n /**\n * Get the current speed of the Character.\n * @returns The current speed.\n */\n getCurrentSidewaysSpeed(): float {\n return this._currentSidewaysSpeed;\n }\n\n /**\n * Set the current speed of the Character.\n * @param currentSidewaysSpeed The current speed.\n */\n setCurrentSidewaysSpeed(currentSidewaysSpeed: float): void {\n this._currentSidewaysSpeed = currentSidewaysSpeed;\n }\n\n /**\n * Get the speed at which the object is falling. It is 0 when the object is\n * on a floor, and non 0 as soon as the object leaves the floor.\n * @returns The current fall speed.\n */\n getCurrentFallSpeed(): float {\n return this._currentFallSpeed;\n }\n\n /**\n * Set the current fall speed.\n */\n setCurrentFallSpeed(currentFallSpeed: float) {\n this._currentFallSpeed = gdjs.evtTools.common.clamp(\n currentFallSpeed,\n 0,\n this._maxFallingSpeed\n );\n }\n\n /**\n * Get the current jump speed of the Character.\n * @returns The current jump speed.\n */\n getCurrentJumpSpeed(): float {\n return this._currentJumpSpeed;\n }\n\n /**\n * Set the current jump speed.\n */\n setCurrentJumpSpeed(currentJumpSpeed: float) {\n this._currentJumpSpeed = Math.max(0, currentJumpSpeed);\n }\n\n /**\n * Check if the Character can jump.\n * @returns Returns true if the object can jump.\n */\n canJump(): boolean {\n return this._canJump;\n }\n\n /**\n * Allow the Character to jump again.\n */\n setCanJump(): void {\n this._canJump = true;\n }\n\n /**\n * Forbid the Character to air jump.\n */\n setCanNotAirJump(): void {\n if (this.isJumping() || this.isFalling()) {\n this._canJump = false;\n }\n }\n\n /**\n * Abort the current jump.\n *\n * When the character is not in the jumping state this method has no effect.\n */\n abortJump(): void {\n if (this.isJumping()) {\n this._currentFallSpeed = 0;\n this._currentJumpSpeed = 0;\n }\n }\n\n simulateForwardKey(): void {\n this._hasPressedForwardKey = true;\n }\n\n wasForwardKeyPressed(): boolean {\n return this._wasForwardKeyPressed;\n }\n\n simulateBackwardKey(): void {\n this._hasPressedBackwardKey = true;\n }\n\n wasBackwardKeyPressed(): boolean {\n return this._wasBackwardKeyPressed;\n }\n\n simulateRightKey(): void {\n this._hasPressedRightKey = true;\n }\n\n wasRightKeyPressed(): boolean {\n return this._wasRightKeyPressed;\n }\n\n simulateLeftKey(): void {\n this._hasPressedLeftKey = true;\n }\n\n wasLeftKeyPressed(): boolean {\n return this._wasLeftKeyPressed;\n }\n\n simulateJumpKey(): void {\n this._hasPressedJumpKey = true;\n }\n\n wasJumpKeyPressed(): boolean {\n return this._wasJumpKeyPressed;\n }\n\n simulateStick(stickAngle: float, stickForce: float) {\n this._hasUsedStick = true;\n this._stickAngle = stickAngle;\n this._stickForce = Math.max(0, Math.min(1, stickForce));\n }\n\n wasStickUsed(): boolean {\n return this._wasStickUsed;\n }\n\n getStickAngle(): float {\n return this._wasStickUsed ? this._stickAngle : 0;\n }\n\n getStickForce(): float {\n return this._wasStickUsed ? this._stickForce : 0;\n }\n\n // TODO Should we add a \"is sliding\" condition?\n /**\n * Check if the Character is on a floor.\n * @returns Returns true if on a floor and false if not.\n */\n isOnFloor(): boolean {\n return this.character\n ? this.character.IsSupported() &&\n // Ensure characters don't land on too step floor.\n this.character.GetGroundNormal().GetZ() >=\n this._slopeClimbingMinNormalZ &&\n // Ensure characters don't land on a platform corner while jumping.\n this._currentJumpSpeed <= this._currentFallSpeed\n : false;\n }\n\n /**\n * Check if the Character is on the given object.\n * @returns Returns true if on the object and false if not.\n */\n isOnFloorObject(physics3DBehavior: gdjs.Physics3DRuntimeBehavior): boolean {\n if (!physics3DBehavior._body || !this.character || !this.isOnFloor()) {\n return false;\n }\n return (\n this.character.GetGroundBodyID().GetIndexAndSequenceNumber() ===\n physics3DBehavior._body.GetID().GetIndexAndSequenceNumber()\n );\n }\n\n /**\n * Check if the Character is jumping.\n * @returns Returns true if jumping and false if not.\n */\n isJumping(): boolean {\n return this._currentJumpSpeed > 0;\n }\n\n /**\n * Check if the Character is in the falling state. This is false\n * if the object is jumping, even if the object is going down after reaching\n * the jump peak.\n * @returns Returns true if it is falling and false if not.\n */\n isFallingWithoutJumping(): boolean {\n return !this.isOnFloor() && this._currentJumpSpeed === 0;\n }\n\n /**\n * Check if the Character is \"going down\", either because it's in the\n * falling state *or* because it's jumping but reached the jump peak and\n * is now going down (because the jump speed can't compensate anymore the\n * falling speed).\n *\n * If you want to check if the object is falling outside of a jump (or because\n * the jump is entirely finished and there is no jump speed applied to the object\n * anymore), consider using `isFallingWithoutJumping`.\n *\n * @returns Returns true if it is \"going down\" and false if not.\n */\n isFalling(): boolean {\n return (\n !this.isOnFloor() && this._currentJumpSpeed < this._currentFallSpeed\n );\n }\n\n /**\n * Check if the Character is moving.\n * @returns Returns true if it is moving and false if not.\n */\n isMovingEvenALittle(): boolean {\n return (\n (this._hasReallyMoved && this._currentForwardSpeed !== 0) ||\n this._currentJumpSpeed !== 0 ||\n this._currentFallSpeed !== 0\n );\n }\n\n getJumpSpeedToReach(jumpHeight: float): float {\n // Formulas used in this extension were generated from a math model.\n // They are probably not understandable on their own.\n // If you need to modify them or need to write new feature,\n // please take a look at the platformer extension documentation:\n // https://github.com/4ian/GDevelop/tree/master/Extensions/PlatformBehavior#readme\n\n jumpHeight = -Math.abs(jumpHeight);\n\n const gravity = this._gravity;\n const maxFallingSpeed = this._maxFallingSpeed;\n const jumpSustainTime = this._jumpSustainTime;\n\n const maxFallingSpeedReachedTime = maxFallingSpeed / gravity;\n\n // The implementation jumps from one quadratic resolution to another\n // to find the right formula to use as the time is unknown.\n\n const sustainCase = (jumpHeight) => Math.sqrt(-jumpHeight * gravity * 2);\n const maxFallingCase = (jumpHeight) =>\n -gravity * jumpSustainTime +\n maxFallingSpeed +\n Math.sqrt(\n gravity * gravity * jumpSustainTime * jumpSustainTime -\n 2 * jumpHeight * gravity -\n maxFallingSpeed * maxFallingSpeed\n );\n\n let jumpSpeed = 0;\n let peakTime = 0;\n if (maxFallingSpeedReachedTime > jumpSustainTime) {\n // common case\n jumpSpeed =\n -gravity * jumpSustainTime +\n Math.sqrt(\n 2 * gravity * gravity * jumpSustainTime * jumpSustainTime -\n 4 * jumpHeight * gravity\n );\n peakTime = (gravity * jumpSustainTime + jumpSpeed) / (2 * gravity);\n if (peakTime < jumpSustainTime) {\n jumpSpeed = sustainCase(jumpHeight);\n } else if (peakTime > maxFallingSpeedReachedTime) {\n jumpSpeed = maxFallingCase(jumpHeight);\n }\n } else {\n // affine case can't have a maximum\n\n // sustain case\n jumpSpeed = sustainCase(jumpHeight);\n peakTime = jumpSpeed / gravity;\n if (peakTime > maxFallingSpeedReachedTime) {\n jumpSpeed = maxFallingCase(jumpHeight);\n }\n }\n return jumpSpeed;\n }\n }\n\n gdjs.registerBehavior(\n 'Physics3D::PhysicsCharacter3D',\n gdjs.PhysicsCharacter3DRuntimeBehavior\n );\n\n export namespace PhysicsCharacter3DRuntimeBehavior {\n export class CharacterBodyUpdater {\n characterBehavior: gdjs.PhysicsCharacter3DRuntimeBehavior;\n\n constructor(characterBehavior: gdjs.PhysicsCharacter3DRuntimeBehavior) {\n this.characterBehavior = characterBehavior;\n }\n\n createAndAddBody(): Jolt.Body {\n const { _slopeMaxAngle, owner3D, _sharedData } = this.characterBehavior;\n const { behavior } = this.characterBehavior.getPhysics3D();\n\n const shape = behavior.createShape();\n\n const settings = new Jolt.CharacterVirtualSettings();\n settings.mInnerBodyLayer = behavior.getBodyLayer();\n settings.mInnerBodyShape = shape;\n settings.mMass = shape.GetMassProperties().get_mMass();\n settings.mMaxSlopeAngle = gdjs.toRad(_slopeMaxAngle);\n settings.mShape = shape;\n settings.mUp = Jolt.Vec3.prototype.sAxisZ();\n settings.mBackFaceMode = Jolt.EBackFaceMode_CollideWithBackFaces;\n // TODO Should we make them configurable?\n //settings.mMaxStrength = maxStrength;\n //settings.mCharacterPadding = characterPadding;\n //settings.mPenetrationRecoverySpeed = penetrationRecoverySpeed;\n //settings.mPredictiveContactDistance = predictiveContactDistance;\n const depth = owner3D.getDepth() * _sharedData.worldInvScale;\n const width = owner3D.getWidth() * _sharedData.worldInvScale;\n const height = owner3D.getHeight() * _sharedData.worldInvScale;\n // Only the bottom of the capsule can make a contact with the floor.\n // It avoids characters from sticking to walls.\n const capsuleHalfLength = depth / 2;\n const capsuleRadius = Math.sqrt(width * height) / 2;\n settings.mSupportingVolume = new Jolt.Plane(\n Jolt.Vec3.prototype.sAxisZ(),\n // TODO It's strange that the value is positive.\n // Use a big safety margin as the ground normal will be checked anyway.\n // It only avoids to detect walls as ground.\n capsuleHalfLength -\n capsuleRadius *\n (1 - Math.cos(gdjs.toRad(Math.min(_slopeMaxAngle + 20, 70))))\n );\n const character = new Jolt.CharacterVirtual(\n settings,\n this.characterBehavior.getPhysicsPosition(\n _sharedData.getRVec3(0, 0, 0)\n ),\n behavior.getPhysicsRotation(_sharedData.getQuat(0, 0, 0, 1)),\n _sharedData.physicsSystem\n );\n const body = _sharedData.physicsSystem\n .GetBodyLockInterface()\n .TryGetBody(character.GetInnerBodyID());\n this.characterBehavior.character = character;\n // TODO This is not really reliable. We could choose to disable it and force user to use the \"is on platform\" condition.\n //body.SetCollideKinematicVsNonDynamic(true);\n return body;\n }\n\n updateObjectFromBody() {\n const { behavior } = this.characterBehavior.getPhysics3D();\n const { character } = this.characterBehavior;\n if (!character) {\n return;\n }\n // We can't rely on the body position because of mCharacterPadding.\n this.characterBehavior.moveObjectToPhysicsPosition(\n character.GetPosition()\n );\n // TODO No need to update the rotation for X and Y as CharacterVirtual doesn't change it.\n behavior.moveObjectToPhysicsRotation(character.GetRotation());\n }\n\n updateBodyFromObject() {\n const { behavior } = this.characterBehavior.getPhysics3D();\n const { character, owner3D, _sharedData } = this.characterBehavior;\n if (!character) {\n return;\n }\n if (\n behavior._objectOldX !== owner3D.getX() ||\n behavior._objectOldY !== owner3D.getY() ||\n behavior._objectOldZ !== owner3D.getZ()\n ) {\n this.updateCharacterPosition();\n }\n if (\n behavior._objectOldRotationX !== owner3D.getRotationX() ||\n behavior._objectOldRotationY !== owner3D.getRotationY() ||\n behavior._objectOldRotationZ !== owner3D.getAngle()\n ) {\n // TODO No need to update the rotation for X and Y as CharacterVirtual doesn't change it.\n character.SetRotation(\n behavior.getPhysicsRotation(_sharedData.getQuat(0, 0, 0, 1))\n );\n }\n }\n\n updateCharacterPosition() {\n const { character, _sharedData } = this.characterBehavior;\n if (!character) {\n return;\n }\n character.SetPosition(\n this.characterBehavior.getPhysicsPosition(\n _sharedData.getRVec3(0, 0, 0)\n )\n );\n }\n\n recreateShape() {\n const {\n behavior,\n broadPhaseLayerFilter,\n objectLayerFilter,\n bodyFilter,\n shapeFilter,\n } = this.characterBehavior.getPhysics3D();\n const { character, _sharedData } = this.characterBehavior;\n if (!character) {\n return;\n }\n const shape = behavior.createShape();\n const isShapeValid = character.SetShape(\n shape,\n Number.MAX_VALUE,\n broadPhaseLayerFilter,\n objectLayerFilter,\n bodyFilter,\n shapeFilter,\n _sharedData.jolt.GetTempAllocator()\n );\n if (!isShapeValid) {\n return;\n }\n character.SetInnerBodyShape(shape);\n character.SetMass(shape.GetMassProperties().get_mMass());\n\n // shapeHalfDepth may have changed, update the character position accordingly.\n this.updateCharacterPosition();\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|