@hology/core 0.0.200 → 0.0.201
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/effects/sequence/sequence-action.d.ts +1 -0
- package/dist/effects/sequence/sequence-actor.d.ts +5 -0
- package/dist/effects/sequence/sequence-actor.js +1 -1
- package/dist/effects/sequence/sequence-player.d.ts +6 -0
- package/dist/effects/sequence/sequence-player.js +1 -1
- package/dist/effects/vfx/trail-renderer.js +1 -1
- package/dist/effects/vfx/vfx-renderers.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +8 -1
- package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
- package/dist/shader/graph/compiler.d.ts +1 -0
- package/dist/shader/graph/compiler.js +1 -1
- package/dist/shader/graph/model.d.ts +2 -0
- package/dist/shader/graph/registry.d.ts +6 -1
- package/dist/shader/graph/registry.js +1 -1
- package/dist/test/shader-graph.test.js +1 -1
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as t}from"tslib";import{ActorComponent as e,Component as o}from"../../../component.js";import{RootMotionClip as i}from"../../../../animation/root-motion.js";import{inject as s}from"../../../../inject.js";import{ViewController as r}from"../../../../services/render.js";import{AnimationMixer as n,Bone as l,Object3D as a,LoopOnce as h,Raycaster as c,Vector3 as d,SkinnedMesh as p,Skeleton as u,Quaternion as f,Matrix4 as g,MathUtils as y,ArrowHelper as m,Group as k}from"three";import{CharacterMovementComponent as S}from"./character-movement.js";import{CCDIKSolver as w}from"three/addons/animation/CCDIKSolver.js";import{World as b}from"../../../../services/world.js";import{PhysicsSystem as L,RayTestResult as v}from"../../../../services/physics/physics-system.js";const I=new d(0,-1,0),B=new d(0,1,0),x=new d(1,1,1),D=new f,F=new d,P=new d,R=new d,A=new d,M=new d,T=new f,W=new f,O=new f,V=new f,C=new g,q=new g,H=new d(1,0,0),E=new d(0,1,0),z=new d(0,0,1);function N(){return{point:new d,normal:new d,hasNormal:!1}}const U=["mixamorigHips","Hips","hips","Pelvis","pelvis"],j={upper:["LeftUpLeg","leftUpLeg","left_up_leg"],lower:["LeftLeg","leftLeg","left_leg"],foot:["LeftFoot","leftFoot","left_foot"]},Q={upper:["RightUpLeg","rightUpLeg","right_up_leg"],lower:["RightLeg","rightLeg","right_leg"],foot:["RightFoot","rightFoot","right_foot"]},G=["left","right"];let _=class extends e{constructor(){super(...arguments),this.viewController=s(r),this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.externalControlActive=!1,this.world=s(b),this.physicsSystem=s(L),this.footIkEnabled=!1,this.footIkMoving=!1,this.footIkRayStartHeight=.5,this.footIkRayLength=1.5,this.footIkRaycastMode="physics",this.footIkFootOffset=.08,this.footIkAutoContactOffset=!1,this.footIkPositionLerpSpeed=28,this.footIkRotationLerpSpeed=14,this.footIkWeightInSpeed=34,this.footIkWeightOutSpeed=30,this.footIkMaxSlopeAngleDeg=40,this.footIkForwardSampleDistance=.14,this.footIkSideSampleDistance=.08,this.footIkMaxHorizontalOffset=.22,this.footIkMaxVerticalOffsetDown=.75,this.footIkMaxVerticalOffsetUp=.2,this.footIkPelvisEnabled=!0,this.footIkPelvisBone="mixamorigHips",this.footIkPelvisLerpSpeed=24,this.footIkPelvisMaxOffsetDown=.4,this.footIkPelvisMaxOffsetUp=.08,this.footIkRequireGrounded=!0,this.footIkSimpleTiltOnly=!1,this.footIkDebug=!1,this.footIkDebugNormalLength=.25,this.footIkDebugAxisLength=.2,this.footIkExtraClearance=.01,this.footIkPlantReleaseUpSpeed=.08,this.footIkPlantReleaseExtension=.9,this.footIkPlantAttachExtension=.96,this.footIkPlantReleaseLift=.055,this.footIkPlantAttachLift=.02,this.leftLegIkBones={upperLeg:"mixamorigLeftUpLeg",lowerLeg:"mixamorigLeftLeg",foot:"mixamorigLeftFoot"},this.rightLegIkBones={upperLeg:"mixamorigRightUpLeg",lowerLeg:"mixamorigRightLeg",foot:"mixamorigRightFoot"},this.ikPelvisOffsetY=0,this.ikLegState={left:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1},right:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1}},this.ikWarnedMissingBones=!1,this.raycaster=new c,this.raycastIntersections=[],this.footIkRayTo=new d,this.footIkRayTestResult=new v,this.footIkRayTestOptions={excludeTriggers:!0,resolveActor:!1,collisionFilter:-2},this.footIkHits={center:N(),toe:N(),heel:N(),side:N()},this.footIkAxesScratch={up:new d,forward:new d,right:new d},this.footIkSampleAxesScratch={forward:new d,right:new d},this.footIkScratch={footWorldPos:new d,centerRayStart:new d,toeRayStart:new d,heelRayStart:new d,sideRayStart:new d,desiredTargetPos:new d,desiredNormal:new d,desiredForward:new d,debugRayEndA:new d,debugRayEndB:new d,debugRayEndC:new d,debugRayEndD:new d,debugRayEndE:new d,debugRayEndF:new d},this.ikPreSolve={left:{upper:new f,lower:new f,foot:new f},right:{upper:new f,lower:new f,foot:new f}},this.getFullBodyClip=J(t=>t.uuid,t=>K(this.fullBodyMask,t)),this.getUpperBodyClip=J(t=>t.uuid,t=>K(this.upperBodyMask,t))}onInit(){this.viewController.onUpdate(this.actor).subscribe(t=>this.updateInternal(t)),this.characterMovement=this.actor.getComponent(S),this.footIkRayTestOptions.excludeActor=this.actor}onEndPlay(){this.disposeFootIkDebug()}raycastDownFirstValid(t,e,o){const i=this.world.scene;this.raycaster.set(t,I),this.raycaster.near=0,this.raycaster.far=e,this.raycastIntersections.length=0,this.raycaster.intersectObject(i,!0,this.raycastIntersections);for(const t of this.raycastIntersections)if(!(this.isFootIkDebugObject(t.object)||this.isRelatedToActorHierarchy(t.object)||this.isSkinnedMeshObject(t.object)))return o.point.copy(t.point),null!=t.face?(o.normal.copy(t.face.normal).transformDirection(t.object.matrixWorld).normalize(),o.hasNormal=!0):o.hasNormal=!1,this.raycastIntersections.length=0,!0;return this.raycastIntersections.length=0,!1}rayTestDown(t,e,o){const i=this.footIkRayTo.copy(t).addScaledVector(I,e),s=this.physicsSystem.rayTest(t,i,this.footIkRayTestResult,this.footIkRayTestOptions);return!!s.hasHit&&(o.point.copy(s.hitPoint),o.normal.copy(s.hitNormal),o.normal.lengthSq()>1e-8?(o.normal.normalize(),o.hasNormal=!0):o.hasNormal=!1,!0)}isRelatedToActorHierarchy(t){const e=this.actor?.object;return null!=e&&null!=t&&(Z(t,e)||Z(e,t))}isFootIkDebugObject(t){let e=t;for(;null!=e;){if(!0===e.userData?.footIkDebug)return!0;e=e.parent}return!1}isSkinnedMeshObject(t){let e=t;for(;null!=e;){if(e instanceof p||!0===e.isSkinnedMesh)return!0;e=e.parent}return!1}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof i)return this.fullBodyAction}getFullBodyAction(){return this.fullBodyAction}setup(t,e,o){null!=e&&(this.upperBodyMask=Y(e),this.fullBodyMask=function(t,e){const o=new Set(Y(e).map(t=>t.uuid)),i=[];return t.traverse(t=>{(t instanceof l||t.isBone)&&!o.has(t.uuid)&&i.push(t)}),i}(X(t),e)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t),this.ikRoot=t,this.disposeFootIkDebug(),this.initializeFootIk(t,o),this.syncFootIkDebug()}updateStateMachines(t){this.stateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o&&this.play(o,{priority:0,loop:e.current.options.loop??!0})}),this.upperStateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o?this.playUpper(o,{priority:0,loop:e.current.options.loop??!0}):this.play(this.fullBodyClip)})}updateInternal(t){null!=this.mixer&&(this.externalControlActive||(this.upperBodyTimer+=t*(this.upperBodyAction?.timeScale??1),this.fullBodyTimer+=t*(this.fullBodyAction?.timeScale??1),this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*(this.overrideFadeTimeUpper??this.fadeTime)<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip)),this.upperBodyAction=null,this.overrideFadeTimeUpper=null),this.fullBodyAction&&this.fullBodyAction.loop===h&&this.fullBodyAction.getClip().duration-2*(this.overrideFadeTime??this.fadeTime)<this.fullBodyTimer&&(this.currentFullBodyPriority=-1,this.overrideFadeTime=null),null!=this.characterMovement&&(this.movementSpeed=this.characterMovement.horizontalSpeed),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.mixer.update(t),this.updateFootIk(t)))}initializeFootIk(t,e){if(this.ikSolver=null,this.ikSkinnedMesh=null,this.ikBoneRefs=null,this.ikLegLengths=null,this.ikPelvisBone=null,this.ikPelvisOffsetY=0,this.ikFootAxes=null,this.ikTargetBones=null,this.ikWarnedMissingBones=!1,this.ikLegState.left.weight=0,this.ikLegState.right.weight=0,!this.footIkEnabled)return;const o=this.findFirstSkinnedMesh(t);if(null==o||null==o.skeleton)return;this.ikSkinnedMesh=o,t.updateWorldMatrix(!0,!0);const i=o.skeleton,s=this.resolveLegBoneRefs(i,this.leftLegIkBones,j),r=this.resolveLegBoneRefs(i,this.rightLegIkBones,Q);if(null==s||null==r)return void(this.ikWarnedMissingBones||(this.ikWarnedMissingBones=!0,console.warn(`[CharacterAnimationComponent] Foot IK disabled: missing leg bones. Left=${this.leftLegIkBones.upperLeg}/${this.leftLegIkBones.lowerLeg}/${this.leftLegIkBones.foot}, Right=${this.rightLegIkBones.upperLeg}/${this.rightLegIkBones.lowerLeg}/${this.rightLegIkBones.foot}`)));this.ikBoneRefs={left:s,right:r},this.ikLegLengths={left:this.computeLegLengths(s),right:this.computeLegLengths(r)},this.ikFootAxes={left:this.detectFootAxisBasis(s.foot),right:this.detectFootAxisBasis(r.foot)},this.ikPelvisBone=this.resolvePelvisBone(i,s,r),this.ikLegState.left.targetPosition.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.targetPosition.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.normal.set(0,1,0),this.ikLegState.right.normal.set(0,1,0),this.ikLegState.left.pitch=0,this.ikLegState.right.pitch=0,this.ikLegState.left.contactOffset=this.estimateFootContactOffset(i,"left",s.foot),this.ikLegState.right.contactOffset=this.estimateFootContactOffset(i,"right",r.foot),this.ikLegState.left.planted=!0,this.ikLegState.right.planted=!0,this.ikLegState.left.lastFootWorldPos.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.lastFootWorldPos.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.hasLastFootSample=!0,this.ikLegState.right.hasLastFootSample=!0;const n=this.resolveFootAxes("left",s.foot),a=this.resolveFootAxes("right",r.foot);this.ikLegState.left.forward.copy(n.forward),this.ikLegState.right.forward.copy(a.forward);const h=e??X(t);if(null==h)return;let c=i.getBoneByName("_IKTargetLeftFoot"),d=i.getBoneByName("_IKTargetRightFoot"),p=!1;if(null==c&&(c=new l,c.name="_IKTargetLeftFoot",h.add(c),p=!0),null==d&&(d=new l,d.name="_IKTargetRightFoot",h.add(d),p=!0),this.setBoneWorldPosition(c,s.foot.getWorldPosition(F)),this.setBoneWorldPosition(d,r.foot.getWorldPosition(F)),p||i.bones.indexOf(c)<0||i.bones.indexOf(d)<0){const t=i.bones.slice(),e=i.boneInverses.map(t=>t.clone());t.indexOf(c)<0&&(t.push(c),e.push((new g).copy(c.matrixWorld).invert())),t.indexOf(d)<0&&(t.push(d),e.push((new g).copy(d.matrixWorld).invert())),o.bind(new u(t,e),o.bindMatrix)}this.ikTargetBones={left:c,right:d};const f=o.skeleton.bones,y={target:f.indexOf(c),effector:f.indexOf(s.foot),links:[{index:f.indexOf(s.lower)},{index:f.indexOf(s.upper)}],iteration:8},m={target:f.indexOf(d),effector:f.indexOf(r.foot),links:[{index:f.indexOf(r.lower)},{index:f.indexOf(r.upper)}],iteration:8};if(y.target<0||y.effector<0||y.links.some(t=>t.index<0)||m.target<0||m.effector<0||m.links.some(t=>t.index<0))return console.warn("[CharacterAnimationComponent] Foot IK disabled: failed to resolve IK indexes in skeleton."),void(this.ikSolver=null);this.ikSolver=new w(o,[y,m])}findFirstSkinnedMesh(t){let e;return t.traverse(t=>{null==e&&(t instanceof p||!0===t.isSkinnedMesh)&&(e=t)}),e}resolveLegBoneRefs(t,e,o){const i=this.findBoneByNames(t,[e.upperLeg,...o.upper]),s=this.findBoneByNames(t,[e.lowerLeg,...o.lower]),r=this.findBoneByNames(t,[e.foot,...o.foot]);if(null!=i&&null!=s&&null!=r)return{upper:i,lower:s,foot:r}}findBoneByNames(t,e){for(const o of e){const e=t.getBoneByName(o);if(null!=e)return e}}resolvePelvisBone(t,e,o){const i=this.findBoneByNames(t,[this.footIkPelvisBone,...U]);if(null!=i)return i;const s=e.upper.parent,r=o.upper.parent;return null!=s&&s===r&&(s instanceof l||!0===s.isBone)||null!=s&&(s instanceof l||!0===s.isBone)?s:void 0}computeLegLengths(t){const e=t.upper.getWorldPosition(F),o=t.lower.getWorldPosition(P),i=t.foot.getWorldPosition(R),s=e.distanceTo(o),r=o.distanceTo(i);return{upper:s,lower:r,total:s+r}}setBoneWorldPosition(t,e){const o=t.parent;null==o?t.position.copy(e):t.position.copy(o.worldToLocal(F.copy(e))),t.quaternion.copy(D),t.scale.copy(x),t.updateMatrixWorld(!0)}syncFootIkDebug(){this.footIkDebug&&null!=this.ikRoot?(null!=this.ikDebugRoot&&null!=this.ikDebugLegs||(this.ikDebugRoot=new k,this.ikDebugRoot.name="FootIKDebug",this.ikDebugRoot.userData.footIkDebug=!0,this.ikDebugLegs={left:this.createDebugLeg("LeftFootIK",53503),right:this.createDebugLeg("RightFootIK",16755200)},this.ikDebugRoot.add(this.ikDebugLegs.left.root,this.ikDebugLegs.right.root),this.world.scene.add(this.ikDebugRoot)),this.ikDebugRoot.visible=!0):null!=this.ikDebugRoot&&(this.ikDebugRoot.visible=!1)}disposeFootIkDebug(){null!=this.ikDebugRoot&&(this.ikDebugRoot.removeFromParent(),this.ikDebugRoot.clear()),this.ikDebugRoot=null,this.ikDebugLegs=null}createDebugLeg(t,e){const o=new k;o.name=t,o.userData.footIkDebug=!0;const i=this.createDebugArrow(e),s=this.createDebugArrow(e),r=this.createDebugArrow(e),n=this.createDebugArrow(e),l=this.createDebugArrow(65280),a=this.createDebugArrow(6750054),h=this.createDebugArrow(16711935),c=this.createDebugArrow(16776960),d=this.createDebugArrow(16737792);return o.add(i,s,r,n,l,a,h,c,d),{root:o,rayCenter:i,rayToe:s,rayHeel:r,raySide:n,hitNormal:l,footUp:a,footToTarget:h,solveUpper:c,solveLower:d}}createDebugArrow(t){const e=new m(B,new d,.001,t);return e.userData.footIkDebug=!0,e.traverse(t=>{t.userData.footIkDebug=!0,t.raycast=()=>{}}),e.visible=!1,e}setDebugArrow(t,e,o){F.subVectors(o,e);const i=F.length();i<1e-6?t.visible=!1:(t.visible=!0,t.position.copy(e),t.setDirection(F.multiplyScalar(1/i)),t.setLength(i,Math.min(.08,.25*i),Math.min(.05,.2*i)))}resetDebugVisibility(){null!=this.ikDebugLegs&&(this.ikDebugLegs.left.rayCenter.visible=!1,this.ikDebugLegs.left.rayToe.visible=!1,this.ikDebugLegs.left.rayHeel.visible=!1,this.ikDebugLegs.left.raySide.visible=!1,this.ikDebugLegs.left.hitNormal.visible=!1,this.ikDebugLegs.left.footUp.visible=!1,this.ikDebugLegs.left.footToTarget.visible=!1,this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.rayCenter.visible=!1,this.ikDebugLegs.right.rayToe.visible=!1,this.ikDebugLegs.right.rayHeel.visible=!1,this.ikDebugLegs.right.raySide.visible=!1,this.ikDebugLegs.right.hitNormal.visible=!1,this.ikDebugLegs.right.footUp.visible=!1,this.ikDebugLegs.right.footToTarget.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1)}updateFootIk(t){if(this.syncFootIkDebug(),!this.footIkEnabled||null==this.ikBoneRefs||null==this.ikRoot)return void this.resetDebugVisibility();if(!this.footIkMoving&&(this.movementSpeed??0)>.01)return this.resetFootIkState(),void this.resetDebugVisibility();this.ikRoot.updateWorldMatrix(!0,!0);const e=this.characterMovement?.isGrounded??!0;return this.footIkSimpleTiltOnly?(this.updatePelvisOffset(t,!1),this.updateLegTiltSimple("left",this.ikBoneRefs.left.foot,this.ikLegState.left,e,t),void this.updateLegTiltSimple("right",this.ikBoneRefs.right.foot,this.ikLegState.right,e,t)):null==this.ikLegLengths||null==this.ikTargetBones||null==this.ikSkinnedMesh||null==this.ikSolver?(this.updatePelvisOffset(t,!1),void this.resetDebugVisibility()):(this.updateLegIkTarget("left",this.ikBoneRefs.left,this.ikLegLengths.left,this.ikTargetBones.left,this.ikLegState.left,e,t),this.updateLegIkTarget("right",this.ikBoneRefs.right,this.ikLegLengths.right,this.ikTargetBones.right,this.ikLegState.right,e,t),this.updatePelvisOffset(t,!0),this.setBoneWorldPosition(this.ikTargetBones.left,this.ikLegState.left.targetPosition),this.setBoneWorldPosition(this.ikTargetBones.right,this.ikLegState.right.targetPosition),this.ikPreSolve.left.upper.copy(this.ikBoneRefs.left.upper.quaternion),this.ikPreSolve.left.lower.copy(this.ikBoneRefs.left.lower.quaternion),this.ikPreSolve.left.foot.copy(this.ikBoneRefs.left.foot.quaternion),this.ikPreSolve.right.upper.copy(this.ikBoneRefs.right.upper.quaternion),this.ikPreSolve.right.lower.copy(this.ikBoneRefs.right.lower.quaternion),this.ikPreSolve.right.foot.copy(this.ikBoneRefs.right.foot.quaternion),null!=this.ikDebugLegs&&(this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1),this.ikSolver.update(),this.blendLegAfterSolve(this.ikBoneRefs.left,this.ikPreSolve.left,this.ikLegState.left.weight),this.blendLegAfterSolve(this.ikBoneRefs.right,this.ikPreSolve.right,this.ikLegState.right.weight),this.applySimpleFootPitch("left",this.ikBoneRefs.left.foot,this.ikLegState.left),void this.applySimpleFootPitch("right",this.ikBoneRefs.right.foot,this.ikLegState.right))}resetFootIkState(){if(null!=this.ikBoneRefs){for(const t of G){const e=this.ikBoneRefs[t],o=this.ikLegState[t],i=e.foot.getWorldPosition(F);o.targetPosition.copy(i),o.lastFootWorldPos.copy(i),o.hasLastFootSample=!0,o.weight=0,o.normal.set(0,1,0);const s=this.resolveFootAxes(t,e.foot,this.footIkAxesScratch);o.forward.copy(s.forward),o.pitch=0,this.footIkAutoContactOffset?o.contactOffset=Math.max(o.contactOffset,this.footIkFootOffset+this.footIkExtraClearance):o.contactOffset=this.footIkFootOffset+this.footIkExtraClearance,o.planted=!1}this.ikPelvisOffsetY=0}}updatePelvisOffset(t,e){if(null==this.ikPelvisBone)return;let o=0;if(e&&this.footIkPelvisEnabled&&null!=this.ikBoneRefs&&null!=this.ikLegLengths){this.ikLegState.left.top=!1,this.ikLegState.right.top=!1;for(const t of G){const e=this.ikBoneRefs[t],i=this.ikLegLengths[t],s=this.ikLegState[t];if(!s.planted)continue;const r=e.upper.getWorldPosition(F),n=.998*i.total,l=this.computeRequiredPelvisDrop(r,s.targetPosition,n);if(l>0){const e="left"===t?"right":"left";this.ikLegState[e].top=!0}o=Math.min(o,-l)}o=y.clamp(o,-this.footIkPelvisMaxOffsetDown,this.footIkPelvisMaxOffsetUp)}const i=1-Math.exp(-this.footIkPelvisLerpSpeed*t);this.ikPelvisOffsetY=y.lerp(this.ikPelvisOffsetY,o,i);const s=this.ikPelvisBone.getWorldPosition(P),r=R.copy(s).addScaledVector(B,this.ikPelvisOffsetY);null==this.ikPelvisBone.parent?this.ikPelvisBone.position.copy(r):this.ikPelvisBone.position.copy(this.ikPelvisBone.parent.worldToLocal(r)),this.ikPelvisBone.updateMatrixWorld(!0)}computeFootVerticalSpeed(t,e,o){return!t.hasLastFootSample||o<=1e-6?0:(e.y-t.lastFootWorldPos.y)/o}updateFootSample(t,e){t.lastFootWorldPos.copy(e),t.hasLastFootSample=!0}estimateFootContactOffset(t,e,o){const i=this.footIkFootOffset+this.footIkExtraClearance;if(!this.footIkAutoContactOffset)return i;const s=t.bones.indexOf(o);if(s<0)return i;const r=t.boneInverses[s];if(null==r)return i;const n=this.ikFootAxes?.[e]??this.detectFootAxisBasis(o),a=o.getWorldPosition(P),h=R.copy(n.upLocal).applyQuaternion(o.getWorldQuaternion(T)).normalize();let c=0;return o.traverse(e=>{if(!(e instanceof l)||e===o)return;const i=t.bones.indexOf(e);if(i<0)return;const s=C.copy(t.boneInverses[i]).invert(),n=q.copy(r).multiply(s),d=F.setFromMatrixPosition(n),p=A.copy(d).applyMatrix4(o.matrixWorld).sub(a);c=Math.min(c,p.dot(h))}),Math.max(i,-c+this.footIkExtraClearance)}shouldPlantFoot(t,e,o,i,s,r){if(!e||!o)return!1;const n=this.footIkPlantReleaseExtension,l=this.footIkPlantAttachExtension,a=this.footIkPlantReleaseLift,h=this.footIkPlantAttachLift;return t.planted?!(i>this.footIkPlantReleaseUpSpeed&&(s<n||r>a)):s>=l&&r<=h||i<=0&&s>=n}computeLegExtensionRatio(t,e){const o=t.upper.getWorldPosition(F),i=t.foot.getWorldPosition(P),s=o.distanceTo(i);return e.total<=1e-6?1:y.clamp(s/e.total,0,1.2)}computeRequiredPelvisDrop(t,e,o){const i=A.subVectors(t,e),s=i.length();if(s<=o+1e-6)return 0;const r=i.dot(B),n=o*o-Math.max(s*s-r*r,0);if(n<=0)return s-o;const l=Math.sqrt(n),a=r-l,h=r+l;return a>=0?a:h>=0?h:0}updateLegTiltSimple(t,e,o,i,s){const r=this.footIkScratch,n=this.footIkHits,l=e.getWorldPosition(r.footWorldPos),a=this.computeFootVerticalSpeed(o,l,s),h=this.resolveFootAxes(t,e,this.footIkAxesScratch),c=this.resolveGroundSampleAxes(t,e,h,this.footIkSampleAxesScratch),d=r.centerRayStart.copy(l).addScaledVector(B,this.footIkRayStartHeight),p=r.toeRayStart.copy(d).addScaledVector(c.forward,this.footIkForwardSampleDistance),u=r.heelRayStart.copy(d).addScaledVector(c.forward,-this.footIkForwardSampleDistance),f=r.sideRayStart.copy(d).addScaledVector(c.right,this.footIkSideSampleDistance),g=this.getFirstGroundHit(d,n.center),m=this.getFirstGroundHit(p,n.toe),k=this.getFirstGroundHit(u,n.heel),S=this.getFirstGroundHit(f,n.side),w=r.desiredNormal.set(0,1,0),b=r.desiredForward.copy(c.forward);let L=0,v=0,I=this.footIkWeightOutSpeed;const x=null!=g||null!=m||null!=k;let D=l.y;null!=g?D=g.point.y:null!=m&&null!=k?D=.5*(m.point.y+k.point.y):null!=m?D=m.point.y:null!=k&&(D=k.point.y);const F=this.ikBoneRefs?.[t],P=this.ikLegLengths?.[t],R=null!=F&&null!=P?this.computeLegExtensionRatio(F,P):1,A=Math.max(0,l.y-D,l.y-o.targetPosition.y),M=this.shouldPlantFoot(o,!this.footIkRequireGrounded||i,x,a,R,A);M?this.computeDesiredGroundNormal(c,g,m,k,S,w)&&(this.computeDesiredFootForward(c.forward,c.right,w,m,k,b),L=this.computeDesiredPitchAngle(m,k,c.forward),v=1,I=this.footIkWeightInSpeed):this.computeDesiredFootForward(c.forward,c.right,w,null,null,b);const T=1-Math.exp(-this.footIkPositionLerpSpeed*s),W=1-Math.exp(-I*s);o.normal.lerp(w,T).normalize(),o.forward.lerp(b,T).normalize(),o.pitch=y.lerp(o.pitch,L,T),o.weight=y.lerp(o.weight,v,W),o.planted=M&&v>.001,this.updateFootSample(o,l),this.applySimpleFootPitch(t,e,o),this.updateLegDebug(t,{footWorldPos:l,centerRayStart:d,toeRayStart:p,heelRayStart:u,sideRayStart:f,centerHit:g,toeHit:m,heelHit:k,sideHit:S,desiredNormal:o.normal,desiredTargetPos:r.footWorldPos,weight:o.weight})}updateLegIkTarget(t,e,o,i,s,r,n){const l=this.footIkScratch,a=this.footIkHits,h=e.foot,c=h.getWorldPosition(l.footWorldPos),d=this.computeFootVerticalSpeed(s,c,n),p=this.resolveFootAxes(t,h,this.footIkAxesScratch),u=this.resolveGroundSampleAxes(t,h,p,this.footIkSampleAxesScratch),f=l.centerRayStart.copy(c).addScaledVector(B,this.footIkRayStartHeight),g=l.toeRayStart.copy(f).addScaledVector(u.forward,this.footIkForwardSampleDistance),m=l.heelRayStart.copy(f).addScaledVector(u.forward,-this.footIkForwardSampleDistance),k=l.sideRayStart.copy(f).addScaledVector(u.right,this.footIkSideSampleDistance),S=this.getFirstGroundHit(f,a.center),w=this.getFirstGroundHit(g,a.toe),b=this.getFirstGroundHit(m,a.heel),L=this.getFirstGroundHit(k,a.side),v=l.desiredTargetPos.copy(c),I=l.desiredNormal.set(0,1,0),x=l.desiredForward.copy(u.forward);let D=0,F=0,P=this.footIkWeightOutSpeed;const R=null!=S||null!=w||null!=b;let A=c.y;null!=S?A=S.point.y:null!=w&&null!=b?A=.5*(w.point.y+b.point.y):null!=w?A=w.point.y:null!=b&&(A=b.point.y);const M=this.computeLegExtensionRatio(e,o),T=Math.max(0,c.y-A,c.y-s.targetPosition.y),W=this.shouldPlantFoot(s,!this.footIkRequireGrounded||r,R,d,M,T);if(W){if(v.copy(c),this.computeDesiredGroundNormal(u,S,w,b,L,I)){this.computeDesiredFootForward(u.forward,u.right,I,w,b,x),D=this.computeDesiredPitchAngle(w,b,u.forward);const t=Math.max(0,Math.sin(D))*this.footIkForwardSampleDistance*.45,e=Math.max(this.footIkFootOffset+this.footIkExtraClearance,s.contactOffset);v.y=A+e+t,s.top&&(v.y-=this.ikPelvisOffsetY/2),F=1,P=this.footIkWeightInSpeed}}else this.computeDesiredFootForward(u.forward,u.right,I,null,null,x),v.copy(c),v.y+=this.footIkFootOffset;this.clampDesiredFootTarget(e,o,c,v);const O=1-Math.exp(-this.footIkPositionLerpSpeed*n),V=1-Math.exp(-P*n);s.targetPosition.lerp(v,O),s.normal.lerp(I,O).normalize(),s.forward.lerp(x,O).normalize(),s.pitch=y.lerp(s.pitch,D,O),s.weight=y.lerp(s.weight,F,V),s.planted=W&&F>.001,this.updateFootSample(s,c),this.setBoneWorldPosition(i,s.targetPosition),this.updateLegDebug(t,{footWorldPos:c,centerRayStart:f,toeRayStart:g,heelRayStart:m,sideRayStart:k,centerHit:S,toeHit:w,heelHit:b,sideHit:L,desiredNormal:I,desiredTargetPos:s.targetPosition,weight:s.weight})}updateLegDebug(t,e){if(!this.footIkDebug||null==this.ikDebugLegs||null==this.ikBoneRefs)return;const o=this.ikDebugLegs[t],i=this.ikBoneRefs[t],s=this.resolveFootAxes(t,i.foot,this.footIkAxesScratch),r=this.footIkScratch,n=e.centerHit?.point??r.debugRayEndA.copy(e.centerRayStart).addScaledVector(I,this.footIkRayLength),l=e.toeHit?.point??r.debugRayEndB.copy(e.toeRayStart).addScaledVector(I,this.footIkRayLength),a=e.heelHit?.point??r.debugRayEndC.copy(e.heelRayStart).addScaledVector(I,this.footIkRayLength),h=e.sideHit?.point??r.debugRayEndD.copy(e.sideRayStart).addScaledVector(I,this.footIkRayLength);this.setDebugArrow(o.rayCenter,e.centerRayStart,n),this.setDebugArrow(o.rayToe,e.toeRayStart,l),this.setDebugArrow(o.rayHeel,e.heelRayStart,a),this.setDebugArrow(o.raySide,e.sideRayStart,h);const c=e.centerHit?.point??e.toeHit?.point??e.heelHit?.point??e.sideHit?.point??e.footWorldPos;this.setDebugArrow(o.hitNormal,c,r.debugRayEndE.copy(c).addScaledVector(e.desiredNormal,this.footIkDebugNormalLength)),this.setDebugArrow(o.footUp,e.footWorldPos,r.debugRayEndF.copy(e.footWorldPos).addScaledVector(s.up,this.footIkDebugAxisLength*(.15+e.weight))),this.setDebugArrow(o.footToTarget,e.footWorldPos,e.desiredTargetPos)}getFirstGroundHit(t,e){return"physics"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)?e:null:"physicsThenRender"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)||this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null:this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null}resolveGroundSampleAxes(t,e,o,i){const s=o??this.resolveFootAxes(t,e),r=i??{forward:new d,right:new d},n=this.actor.object.getWorldDirection(A);n.addScaledVector(B,-n.dot(B)),n.lengthSq()<1e-8&&n.copy(s.forward).addScaledVector(B,-s.forward.dot(B)),n.lengthSq()<1e-8&&n.set(0,0,1),n.normalize();const l=M.crossVectors(B,n);return l.lengthSq()<1e-8?l.copy(s.right):l.normalize(),l.dot(s.right)<0&&l.multiplyScalar(-1),r.forward.copy(n),r.right.copy(l),r}computeDesiredGroundNormal(t,e,o,i,s,r){const n=this.computeAverageHitNormal(e,o,i,s,A);let l=!1,a=0,h=0;if(null!=o&&null!=i){const e=P.subVectors(o.point,i.point).dot(t.forward);Math.abs(e)>1e-5&&(a=(o.point.y-i.point.y)/e,l=!0)}if(null!=s&&null!=e){const o=R.subVectors(s.point,e.point).dot(t.right);Math.abs(o)>1e-5&&(h=(s.point.y-e.point.y)/o,l=!0)}if(l&&(r.copy(B),r.addScaledVector(t.forward,-a),r.addScaledVector(t.right,-h),r.lengthSq()>1e-8?r.normalize():l=!1),l)null!=n&&r.dot(n)<0&&r.multiplyScalar(-1);else{if(null==n)return!1;r.copy(n),l=!0}return r.dot(B)<0&&r.multiplyScalar(-1),this.clampSlopeNormal(r),!0}computeAverageHitNormal(t,e,o,i,s){s.set(0,0,0);let r=0;return null!=t&&t.hasNormal&&(s.add(t.normal),r++),null!=e&&e.hasNormal&&(s.add(e.normal),r++),null!=o&&o.hasNormal&&(s.add(o.normal),r++),null!=i&&i.hasNormal&&(s.add(i.normal),r++),0===r||s.lengthSq()<1e-8?null:(s.multiplyScalar(1/r).normalize(),s)}computeDesiredFootForward(t,e,o,i,s,r){null!=i&&null!=s?r.subVectors(i.point,s.point):r.copy(t),r.addScaledVector(o,-r.dot(o)),r.lengthSq()<1e-8&&(r.copy(this.actor.object.getWorldDirection(A)),r.addScaledVector(o,-r.dot(o))),r.lengthSq()<1e-8&&r.crossVectors(o,e),r.lengthSq()<1e-8&&r.set(0,0,1),r.normalize();const n=A.copy(this.actor.object.getWorldDirection(A));n.addScaledVector(o,-n.dot(o)),n.lengthSq()<1e-8&&(n.copy(t),n.addScaledVector(o,-n.dot(o))),n.lengthSq()>1e-8&&n.normalize(),r.dot(n)<0&&r.multiplyScalar(-1)}computeDesiredPitchAngle(t,e,o){if(null==t||null==e)return 0;const i=P.subVectors(t.point,e.point),s=Math.abs(i.dot(o));if(s<1e-5)return 0;const r=t.point.y-e.point.y,n=y.degToRad(this.footIkMaxSlopeAngleDeg);return y.clamp(-Math.atan2(r,s),-n,n)}applySimpleFootPitch(t,e,o){if(null==e.parent||o.weight<=.001)return;const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o.pitch*o.weight;if(Math.abs(s)<=1e-5)return;const r=this.resolveLocalPitchSign(i),n=T.copy(e.quaternion),l=W.setFromAxisAngle(i.rightLocal,s*r);e.quaternion.copy(n.multiply(l))}resolveLocalPitchSign(t){const e=O.setFromAxisAngle(t.rightLocal,.15);return R.copy(t.upLocal).applyQuaternion(e).sub(t.upLocal).dot(t.forwardLocal)>=0?1:-1}clampDesiredFootTarget(t,e,o,i){const s=P.subVectors(i,o),r=s.dot(B),n=R.copy(s).addScaledVector(B,-r),l=n.length();l>this.footIkMaxHorizontalOffset&&l>1e-6&&n.multiplyScalar(this.footIkMaxHorizontalOffset/l);const a=y.clamp(r,-this.footIkMaxVerticalOffsetDown,this.footIkMaxVerticalOffsetUp);if(i.copy(o),i.add(n),i.addScaledVector(B,a),this.footIkPelvisEnabled)return;const h=t.upper.getWorldPosition(F).clone(),c=P.subVectors(i,h),d=c.length(),p=.995*e.total;d>p&&d>1e-6&&i.copy(h).addScaledVector(c,p/d)}solveTwoBoneLeg(t,e,o){const i=e.upper.getWorldPosition(F).clone(),s=e.lower.getWorldPosition(P).clone(),r=e.foot.getWorldPosition(R).clone(),n=i.distanceTo(s),l=s.distanceTo(r);if(n<1e-5||l<1e-5)return;const a=(new d).subVectors(o,i),h=a.length();if(h<1e-5)return;const c=Math.abs(n-l)+1e-4,p=n+l-1e-4,u=y.clamp(h,c,p),f=a.multiplyScalar(1/h),g=(new d).subVectors(s,i).normalize(),m=(new d).subVectors(r,s).normalize(),k=(new d).crossVectors(g,m);k.lengthSq()<1e-8&&(k.copy(this.actor.object.getWorldDirection(F).cross(B)),k.lengthSq()<1e-8&&k.set(1,0,0)),k.normalize();const S=(u*u+n*n-l*l)/(2*u),w=Math.max(n*n-S*S,0),b=Math.sqrt(w),L=(new d).copy(i).addScaledVector(f,S);let v=(new d).crossVectors(k,f);v.lengthSq()<1e-8&&(v=(new d).crossVectors(f,B),v.lengthSq()<1e-8&&(v=new d(1,0,0))),v.normalize();const I=(new d).copy(L).addScaledVector(v,b),x=(new d).copy(L).addScaledVector(v,-b),D=(new d).subVectors(s,L).dot(v)>=0?I:x;this.rotateBoneToward(e.upper,i,s,D),e.upper.updateMatrixWorld(!0);const A=e.lower.getWorldPosition(P),M=e.foot.getWorldPosition(R);this.rotateBoneToward(e.lower,A,M,o),e.lower.updateMatrixWorld(!0),this.updateSolveDebug(t,i,D,o)}updateSolveDebug(t,e,o,i){if(!this.footIkDebug||null==this.ikDebugLegs)return;const s=this.ikDebugLegs[t];this.setDebugArrow(s.solveUpper,e,o),this.setDebugArrow(s.solveLower,o,i)}rotateBoneToward(t,e,o,i){const s=(new d).subVectors(o,e),r=(new d).subVectors(i,e);if(s.lengthSq()<1e-10||r.lengthSq()<1e-10)return;if(s.normalize(),r.normalize(),s.dot(r)>.9999)return;const n=(new f).setFromUnitVectors(s,r),l=t.getWorldQuaternion(T),a=W.copy(n).multiply(l);if(null==t.parent)return void t.quaternion.copy(a);const h=t.parent.getWorldQuaternion(O),c=V.copy(h).invert().multiply(a);t.quaternion.copy(c)}detectFootAxisBasis(t){const e=t.getWorldQuaternion(T),o=this.actor.object.getWorldDirection(F);o.lengthSq()<1e-6&&o.set(0,0,1),o.normalize();const i=[{local:H.clone(),world:H.clone().applyQuaternion(e)},{local:E.clone(),world:E.clone().applyQuaternion(e)},{local:z.clone(),world:z.clone().applyQuaternion(e)}];i.push({local:H.clone().multiplyScalar(-1),world:H.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:E.clone().multiplyScalar(-1),world:E.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:z.clone().multiplyScalar(-1),world:z.clone().multiplyScalar(-1).applyQuaternion(e)});let s=i[0],r=-1/0;for(const t of i){const e=t.world.dot(B);e>r&&(r=e,s=t)}let n=i[0],l=-1/0;for(const t of i){if(Math.abs(t.world.dot(s.world))>.6)continue;const e=Math.abs(t.world.dot(o));e>l&&(l=e,n=t)}n.world.dot(o)<0&&(n={local:n.local.clone().multiplyScalar(-1),world:n.world.clone().multiplyScalar(-1)});const a=s.local.clone().normalize(),h=n.local.clone().normalize(),c=a.clone().cross(h).normalize();return{upLocal:a,forwardLocal:c.clone().cross(a).normalize(),rightLocal:c}}resolveFootAxes(t,e,o){const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o??{up:new d,forward:new d,right:new d},r=e.getWorldQuaternion(T);return s.up.copy(i.upLocal).applyQuaternion(r).normalize(),s.forward.copy(i.forwardLocal).applyQuaternion(r).normalize(),s.right.copy(i.rightLocal).applyQuaternion(r).normalize(),s}clampSlopeNormal(t){const e=y.clamp(t.dot(B),-1,1),o=Math.acos(e),i=y.degToRad(this.footIkMaxSlopeAngleDeg);if(o<=i||o<1e-5)return;const s=i/o;t.lerpVectors(B,t,s).normalize()}blendLegAfterSolve(t,e,o){if(!(o>=.999)){if(o<=.001)return t.upper.quaternion.copy(e.upper),t.lower.quaternion.copy(e.lower),void t.foot.quaternion.copy(e.foot);this.blendBoneQuaternion(t.upper,e.upper,o),this.blendBoneQuaternion(t.lower,e.lower,o),this.blendBoneQuaternion(t.foot,e.foot,o)}}blendBoneQuaternion(t,e,o){T.copy(t.quaternion),t.quaternion.copy(e).slerp(T,o)}alignFootToGroundNormal(t,e,o,i){if(o.weight<=.001||null==e.parent)return;const s=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),r=F.copy(o.normal).normalize(),n=P.copy(o.forward);if(n.addScaledVector(r,-n.dot(r)),n.lengthSq()<1e-8){const o=this.resolveFootAxes(t,e);n.copy(o.forward).addScaledVector(r,-o.forward.dot(r))}if(n.lengthSq()<1e-8)return;n.normalize();const l=R.crossVectors(r,n);if(l.lengthSq()<1e-8)return;l.normalize(),n.copy(A.crossVectors(l,r)).normalize(),C.makeBasis(s.rightLocal,s.upLocal,s.forwardLocal),T.setFromRotationMatrix(C),q.makeBasis(l,r,n),W.setFromRotationMatrix(q);const a=O.copy(W).multiply(V.copy(T).invert()),h=e.parent.getWorldQuaternion(V),c=W.copy(h).invert().multiply(a),d=(1-Math.exp(-this.footIkRotationLerpSpeed*i))*o.weight;e.quaternion.slerp(c,y.clamp(d,0,1))}getMixer(){return this.mixer}beginExternalControl(){this.externalControlActive=!0}endExternalControl(){this.externalControlActive=!1}stopSequenceAnimation(){this.currentFullBodyPriority=-1,this.externalControlActive=!1,this.fullBodyTimer=0}beginExternalAnimationControl(t,e={}){$(null!=this.mixer,"Can't begin external control before setup is called"),this.mixer.stopAllAction(),this.currentFullBodyPriority=99,this.fullBodyTimer=0;const o=this.mixer.clipAction(t);return o.setLoop(h,1),o.clampWhenFinished=!0,o.timeScale=e.timeScale??1,o.reset(),o.play(),this.fullBodyAction=o,this.externalControlActive=!0,o}syncMovementSpeed(t){if(null!=t){const e=t.getClip();if(e instanceof i&&e.fixedInPlace&&null!=this.movementSpeed){t.timeScale=e.duration/e.displacement*this.movementSpeed;const o=this.mixer.getRoot();o instanceof a&&(t.timeScale/=o.scale.x)}}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const e=this.stateMachines.indexOf(t);e>=0&&this.stateMachines.splice(e,1)}removeUpperStateMachine(t){const e=this.upperStateMachines.indexOf(t);e>=0&&this.upperStateMachines.splice(e,1)}playUpper(t,e={}){const o=e?.priority??1;o<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=o,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1,this.upperBodyTimer=0,this.upperBodyOverride=!0,this.overrideFadeTimeUpper=e.fadeTime)}play(t,e={}){$(null!=this.mixer,"Can't play animation before setup is called");const o=e.priority??1;o<this.currentFullBodyPriority||(this.currentFullBodyPriority=o,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),e),this.fullBodyAction.timeScale=e?.timeScale??1,this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction),this.overrideFadeTime=e.fadeTime)}onActionDone(t){return new Promise(e=>{const o=i=>{i.action===t&&(e(i.action),this.mixer.removeEventListener("finished",o))};this.mixer.addEventListener("finished",o)})}transition(t,e,o={}){if(null!=t&&t.getClip().uuid===e.uuid)return t;const i=o?.fadeTime??this.fadeTime;if(t){const s=t,r=this.mixer.clipAction(e);r.reset(),null!=o.offset&&(r.time=o.offset),r.play(),r.enabled=!0,r.setEffectiveTimeScale(1),r.weight=1,s.crossFadeTo(r,i,!0),t=r}else(t=this.mixer.clipAction(e)).reset(),null!=o.offset&&(t.time=o.offset),t.fadeIn(i),t.play();return!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0),t}};_=t([o({inEditor:!0})],_);export{_ as CharacterAnimationComponent};function K(t,e){if(null==t)return e;const o=e.clone(),i=new Set(t.map(t=>t.name));return o.tracks=o.tracks.filter(t=>i.has(t.name.split(".")[0])),o}function Y(t){return t.flatMap(t=>function(t){const e=[];return t.traverse(t=>{e.push(t)}),e}(t)).filter(t=>t instanceof l)}function $(t,e){if(!1===t||"function"==typeof t&&!1===t())throw new Error(e)}function J(t,e){const o=new Map;return(i,...s)=>{const r=t(i);return o.has(r)||o.set(r,e(i,...s)),o.get(r)}}function X(t){let e;return t.traverse(t=>{(t instanceof l||t.isBone)&&null==e&&(e=t)}),e}function Z(t,e){let o=e;for(;null!=o;){if(o===t)return!0;o=o.parent}return!1}/*
|
|
1
|
+
import{__decorate as t}from"tslib";import{ActorComponent as e,Component as o}from"../../../component.js";import{RootMotionClip as i}from"../../../../animation/root-motion.js";import{inject as s}from"../../../../inject.js";import{ViewController as r}from"../../../../services/render.js";import{AnimationMixer as n,Bone as l,Object3D as a,LoopOnce as h,Raycaster as c,Vector3 as d,SkinnedMesh as p,Skeleton as u,Quaternion as f,Matrix4 as g,MathUtils as y,ArrowHelper as m,Group as k}from"three";import{CharacterMovementComponent as S}from"./character-movement.js";import{CCDIKSolver as w}from"three/addons/animation/CCDIKSolver.js";import{World as b}from"../../../../services/world.js";import{PhysicsSystem as L,RayTestResult as v}from"../../../../services/physics/physics-system.js";const B=new d(0,-1,0),I=new d(0,1,0),x=new d(1,1,1),D=new f,F=new d,P=new d,R=new d,A=new d,M=new d,T=new f,W=new f,O=new f,V=new f,C=new g,E=new g,q=new d(1,0,0),H=new d(0,1,0),z=new d(0,0,1);function N(){return{point:new d,normal:new d,hasNormal:!1}}const U=["mixamorigHips","Hips","hips","Pelvis","pelvis"],j={upper:["LeftUpLeg","leftUpLeg","left_up_leg"],lower:["LeftLeg","leftLeg","left_leg"],foot:["LeftFoot","leftFoot","left_foot"]},Q={upper:["RightUpLeg","rightUpLeg","right_up_leg"],lower:["RightLeg","rightLeg","right_leg"],foot:["RightFoot","rightFoot","right_foot"]},G=["left","right"];let _=class extends e{constructor(){super(...arguments),this.viewController=s(r),this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.externalControlActive=!1,this.world=s(b),this.physicsSystem=s(L),this.footIkEnabled=!1,this.footIkMoving=!1,this.footIkRayStartHeight=.5,this.footIkRayLength=1.5,this.footIkRaycastMode="physics",this.footIkFootOffset=.08,this.footIkAutoContactOffset=!1,this.footIkPositionLerpSpeed=28,this.footIkRotationLerpSpeed=14,this.footIkWeightInSpeed=34,this.footIkWeightOutSpeed=30,this.footIkMaxSlopeAngleDeg=40,this.footIkForwardSampleDistance=.14,this.footIkSideSampleDistance=.08,this.footIkMaxHorizontalOffset=.22,this.footIkMaxVerticalOffsetDown=.75,this.footIkMaxVerticalOffsetUp=.2,this.footIkPelvisEnabled=!0,this.footIkPelvisBone="mixamorigHips",this.footIkPelvisLerpSpeed=24,this.footIkPelvisMaxOffsetDown=.4,this.footIkPelvisMaxOffsetUp=.08,this.footIkRequireGrounded=!0,this.footIkSimpleTiltOnly=!1,this.footIkDebug=!1,this.footIkDebugNormalLength=.25,this.footIkDebugAxisLength=.2,this.footIkExtraClearance=.01,this.footIkPlantReleaseUpSpeed=.08,this.footIkPlantReleaseExtension=.9,this.footIkPlantAttachExtension=.96,this.footIkPlantReleaseLift=.055,this.footIkPlantAttachLift=.02,this.leftLegIkBones={upperLeg:"mixamorigLeftUpLeg",lowerLeg:"mixamorigLeftLeg",foot:"mixamorigLeftFoot"},this.rightLegIkBones={upperLeg:"mixamorigRightUpLeg",lowerLeg:"mixamorigRightLeg",foot:"mixamorigRightFoot"},this.ikPelvisOffsetY=0,this.ikLegState={left:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1},right:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1}},this.ikWarnedMissingBones=!1,this.raycaster=new c,this.raycastIntersections=[],this.footIkRayTo=new d,this.footIkRayTestResult=new v,this.footIkRayTestOptions={excludeTriggers:!0,resolveActor:!1,collisionFilter:-2},this.footIkHits={center:N(),toe:N(),heel:N(),side:N()},this.footIkAxesScratch={up:new d,forward:new d,right:new d},this.footIkSampleAxesScratch={forward:new d,right:new d},this.footIkScratch={footWorldPos:new d,centerRayStart:new d,toeRayStart:new d,heelRayStart:new d,sideRayStart:new d,desiredTargetPos:new d,desiredNormal:new d,desiredForward:new d,debugRayEndA:new d,debugRayEndB:new d,debugRayEndC:new d,debugRayEndD:new d,debugRayEndE:new d,debugRayEndF:new d},this.ikPreSolve={left:{upper:new f,lower:new f,foot:new f},right:{upper:new f,lower:new f,foot:new f}},this.getFullBodyClip=J(t=>t.uuid,t=>K(this.fullBodyMask,t)),this.getUpperBodyClip=J(t=>t.uuid,t=>K(this.upperBodyMask,t))}onInit(){this.viewController.onUpdate(this.actor).subscribe(t=>this.updateInternal(t)),this.characterMovement=this.actor.getComponent(S),this.footIkRayTestOptions.excludeActor=this.actor}onEndPlay(){this.disposeFootIkDebug()}raycastDownFirstValid(t,e,o){const i=this.world.scene;this.raycaster.set(t,B),this.raycaster.near=0,this.raycaster.far=e,this.raycastIntersections.length=0,this.raycaster.intersectObject(i,!0,this.raycastIntersections);for(const t of this.raycastIntersections)if(!(this.isFootIkDebugObject(t.object)||this.isRelatedToActorHierarchy(t.object)||this.isSkinnedMeshObject(t.object)))return o.point.copy(t.point),null!=t.face?(o.normal.copy(t.face.normal).transformDirection(t.object.matrixWorld).normalize(),o.hasNormal=!0):o.hasNormal=!1,this.raycastIntersections.length=0,!0;return this.raycastIntersections.length=0,!1}rayTestDown(t,e,o){const i=this.footIkRayTo.copy(t).addScaledVector(B,e),s=this.physicsSystem.rayTest(t,i,this.footIkRayTestResult,this.footIkRayTestOptions);return!!s.hasHit&&(o.point.copy(s.hitPoint),o.normal.copy(s.hitNormal),o.normal.lengthSq()>1e-8?(o.normal.normalize(),o.hasNormal=!0):o.hasNormal=!1,!0)}isRelatedToActorHierarchy(t){const e=this.actor?.object;return null!=e&&null!=t&&(Z(t,e)||Z(e,t))}isFootIkDebugObject(t){let e=t;for(;null!=e;){if(!0===e.userData?.footIkDebug)return!0;e=e.parent}return!1}isSkinnedMeshObject(t){let e=t;for(;null!=e;){if(e instanceof p||!0===e.isSkinnedMesh)return!0;e=e.parent}return!1}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof i)return this.fullBodyAction}getFullBodyAction(){return this.fullBodyAction}setup(t,e,o){null!=e&&(this.upperBodyMask=Y(e),this.fullBodyMask=function(t,e){const o=new Set(Y(e).map(t=>t.uuid)),i=[];return t.traverse(t=>{(t instanceof l||t.isBone)&&!o.has(t.uuid)&&i.push(t)}),i}(X(t),e)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t),this.ikRoot=t,this.disposeFootIkDebug(),this.initializeFootIk(t,o),this.syncFootIkDebug()}updateStateMachines(t){this.stateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o&&this.play(o,{priority:0,loop:e.current.options.loop??!0})}),this.upperStateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o?this.playUpper(o,{priority:0,loop:e.current.options.loop??!0}):this.play(this.fullBodyClip)})}updateInternal(t){null!=this.mixer&&(this.externalControlActive||(this.upperBodyTimer+=t*(this.upperBodyAction?.timeScale??1),this.fullBodyTimer+=t*(this.fullBodyAction?.timeScale??1),this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*(this.overrideFadeTimeUpper??this.fadeTime)<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip)),this.upperBodyAction=null,this.overrideFadeTimeUpper=null),this.fullBodyAction&&this.fullBodyAction.loop===h&&this.fullBodyAction.getClip().duration-2*(this.overrideFadeTime??this.fadeTime)<this.fullBodyTimer&&(this.currentFullBodyPriority=-1,this.overrideFadeTime=null),null!=this.characterMovement&&(this.movementSpeed=this.characterMovement.horizontalSpeed),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.mixer.update(t),this.updateFootIk(t)))}initializeFootIk(t,e){if(this.ikSolver=null,this.ikSkinnedMesh=null,this.ikBoneRefs=null,this.ikLegLengths=null,this.ikPelvisBone=null,this.ikPelvisOffsetY=0,this.ikFootAxes=null,this.ikTargetBones=null,this.ikWarnedMissingBones=!1,this.ikLegState.left.weight=0,this.ikLegState.right.weight=0,!this.footIkEnabled)return;const o=this.findFirstSkinnedMesh(t);if(null==o||null==o.skeleton)return;this.ikSkinnedMesh=o,t.updateWorldMatrix(!0,!0);const i=o.skeleton,s=this.resolveLegBoneRefs(i,this.leftLegIkBones,j),r=this.resolveLegBoneRefs(i,this.rightLegIkBones,Q);if(null==s||null==r)return void(this.ikWarnedMissingBones||(this.ikWarnedMissingBones=!0,console.warn(`[CharacterAnimationComponent] Foot IK disabled: missing leg bones. Left=${this.leftLegIkBones.upperLeg}/${this.leftLegIkBones.lowerLeg}/${this.leftLegIkBones.foot}, Right=${this.rightLegIkBones.upperLeg}/${this.rightLegIkBones.lowerLeg}/${this.rightLegIkBones.foot}`)));this.ikBoneRefs={left:s,right:r},this.ikLegLengths={left:this.computeLegLengths(s),right:this.computeLegLengths(r)},this.ikFootAxes={left:this.detectFootAxisBasis(s.foot),right:this.detectFootAxisBasis(r.foot)},this.ikPelvisBone=this.resolvePelvisBone(i,s,r),this.ikLegState.left.targetPosition.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.targetPosition.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.normal.set(0,1,0),this.ikLegState.right.normal.set(0,1,0),this.ikLegState.left.pitch=0,this.ikLegState.right.pitch=0,this.ikLegState.left.contactOffset=this.estimateFootContactOffset(i,"left",s.foot),this.ikLegState.right.contactOffset=this.estimateFootContactOffset(i,"right",r.foot),this.ikLegState.left.planted=!0,this.ikLegState.right.planted=!0,this.ikLegState.left.lastFootWorldPos.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.lastFootWorldPos.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.hasLastFootSample=!0,this.ikLegState.right.hasLastFootSample=!0;const n=this.resolveFootAxes("left",s.foot),a=this.resolveFootAxes("right",r.foot);this.ikLegState.left.forward.copy(n.forward),this.ikLegState.right.forward.copy(a.forward);const h=e??X(t);if(null==h)return;let c=i.getBoneByName("_IKTargetLeftFoot"),d=i.getBoneByName("_IKTargetRightFoot"),p=!1;if(null==c&&(c=new l,c.name="_IKTargetLeftFoot",h.add(c),p=!0),null==d&&(d=new l,d.name="_IKTargetRightFoot",h.add(d),p=!0),this.setBoneWorldPosition(c,s.foot.getWorldPosition(F)),this.setBoneWorldPosition(d,r.foot.getWorldPosition(F)),p||i.bones.indexOf(c)<0||i.bones.indexOf(d)<0){const t=i.bones.slice(),e=i.boneInverses.map(t=>t.clone());t.indexOf(c)<0&&(t.push(c),e.push((new g).copy(c.matrixWorld).invert())),t.indexOf(d)<0&&(t.push(d),e.push((new g).copy(d.matrixWorld).invert())),o.bind(new u(t,e),o.bindMatrix)}this.ikTargetBones={left:c,right:d};const f=o.skeleton.bones,y={target:f.indexOf(c),effector:f.indexOf(s.foot),links:[{index:f.indexOf(s.lower)},{index:f.indexOf(s.upper)}],iteration:8},m={target:f.indexOf(d),effector:f.indexOf(r.foot),links:[{index:f.indexOf(r.lower)},{index:f.indexOf(r.upper)}],iteration:8};if(y.target<0||y.effector<0||y.links.some(t=>t.index<0)||m.target<0||m.effector<0||m.links.some(t=>t.index<0))return console.warn("[CharacterAnimationComponent] Foot IK disabled: failed to resolve IK indexes in skeleton."),void(this.ikSolver=null);this.ikSolver=new w(o,[y,m])}findFirstSkinnedMesh(t){let e;return t.traverse(t=>{null==e&&(t instanceof p||!0===t.isSkinnedMesh)&&(e=t)}),e}resolveLegBoneRefs(t,e,o){const i=this.findBoneByNames(t,[e.upperLeg,...o.upper]),s=this.findBoneByNames(t,[e.lowerLeg,...o.lower]),r=this.findBoneByNames(t,[e.foot,...o.foot]);if(null!=i&&null!=s&&null!=r)return{upper:i,lower:s,foot:r}}findBoneByNames(t,e){for(const o of e){const e=t.getBoneByName(o);if(null!=e)return e}}resolvePelvisBone(t,e,o){const i=this.findBoneByNames(t,[this.footIkPelvisBone,...U]);if(null!=i)return i;const s=e.upper.parent,r=o.upper.parent;return null!=s&&s===r&&(s instanceof l||!0===s.isBone)||null!=s&&(s instanceof l||!0===s.isBone)?s:void 0}computeLegLengths(t){const e=t.upper.getWorldPosition(F),o=t.lower.getWorldPosition(P),i=t.foot.getWorldPosition(R),s=e.distanceTo(o),r=o.distanceTo(i);return{upper:s,lower:r,total:s+r}}setBoneWorldPosition(t,e){const o=t.parent;null==o?t.position.copy(e):t.position.copy(o.worldToLocal(F.copy(e))),t.quaternion.copy(D),t.scale.copy(x),t.updateMatrixWorld(!0)}syncFootIkDebug(){this.footIkDebug&&null!=this.ikRoot?(null!=this.ikDebugRoot&&null!=this.ikDebugLegs||(this.ikDebugRoot=new k,this.ikDebugRoot.name="FootIKDebug",this.ikDebugRoot.userData.footIkDebug=!0,this.ikDebugLegs={left:this.createDebugLeg("LeftFootIK",53503),right:this.createDebugLeg("RightFootIK",16755200)},this.ikDebugRoot.add(this.ikDebugLegs.left.root,this.ikDebugLegs.right.root),this.world.scene.add(this.ikDebugRoot)),this.ikDebugRoot.visible=!0):null!=this.ikDebugRoot&&(this.ikDebugRoot.visible=!1)}disposeFootIkDebug(){null!=this.ikDebugRoot&&(this.ikDebugRoot.removeFromParent(),this.ikDebugRoot.clear()),this.ikDebugRoot=null,this.ikDebugLegs=null}createDebugLeg(t,e){const o=new k;o.name=t,o.userData.footIkDebug=!0;const i=this.createDebugArrow(e),s=this.createDebugArrow(e),r=this.createDebugArrow(e),n=this.createDebugArrow(e),l=this.createDebugArrow(65280),a=this.createDebugArrow(6750054),h=this.createDebugArrow(16711935),c=this.createDebugArrow(16776960),d=this.createDebugArrow(16737792);return o.add(i,s,r,n,l,a,h,c,d),{root:o,rayCenter:i,rayToe:s,rayHeel:r,raySide:n,hitNormal:l,footUp:a,footToTarget:h,solveUpper:c,solveLower:d}}createDebugArrow(t){const e=new m(I,new d,.001,t);return e.userData.footIkDebug=!0,e.traverse(t=>{t.userData.footIkDebug=!0,t.raycast=()=>{}}),e.visible=!1,e}setDebugArrow(t,e,o){F.subVectors(o,e);const i=F.length();i<1e-6?t.visible=!1:(t.visible=!0,t.position.copy(e),t.setDirection(F.multiplyScalar(1/i)),t.setLength(i,Math.min(.08,.25*i),Math.min(.05,.2*i)))}resetDebugVisibility(){null!=this.ikDebugLegs&&(this.ikDebugLegs.left.rayCenter.visible=!1,this.ikDebugLegs.left.rayToe.visible=!1,this.ikDebugLegs.left.rayHeel.visible=!1,this.ikDebugLegs.left.raySide.visible=!1,this.ikDebugLegs.left.hitNormal.visible=!1,this.ikDebugLegs.left.footUp.visible=!1,this.ikDebugLegs.left.footToTarget.visible=!1,this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.rayCenter.visible=!1,this.ikDebugLegs.right.rayToe.visible=!1,this.ikDebugLegs.right.rayHeel.visible=!1,this.ikDebugLegs.right.raySide.visible=!1,this.ikDebugLegs.right.hitNormal.visible=!1,this.ikDebugLegs.right.footUp.visible=!1,this.ikDebugLegs.right.footToTarget.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1)}updateFootIk(t){if(this.syncFootIkDebug(),!this.footIkEnabled||null==this.ikBoneRefs||null==this.ikRoot)return void this.resetDebugVisibility();if(!this.footIkMoving&&(this.movementSpeed??0)>.01)return this.resetFootIkState(),void this.resetDebugVisibility();this.ikRoot.updateWorldMatrix(!0,!0);const e=this.characterMovement?.isGrounded??!0;return this.footIkSimpleTiltOnly?(this.updatePelvisOffset(t,!1),this.updateLegTiltSimple("left",this.ikBoneRefs.left.foot,this.ikLegState.left,e,t),void this.updateLegTiltSimple("right",this.ikBoneRefs.right.foot,this.ikLegState.right,e,t)):null==this.ikLegLengths||null==this.ikTargetBones||null==this.ikSkinnedMesh||null==this.ikSolver?(this.updatePelvisOffset(t,!1),void this.resetDebugVisibility()):(this.updateLegIkTarget("left",this.ikBoneRefs.left,this.ikLegLengths.left,this.ikTargetBones.left,this.ikLegState.left,e,t),this.updateLegIkTarget("right",this.ikBoneRefs.right,this.ikLegLengths.right,this.ikTargetBones.right,this.ikLegState.right,e,t),this.updatePelvisOffset(t,!0),this.setBoneWorldPosition(this.ikTargetBones.left,this.ikLegState.left.targetPosition),this.setBoneWorldPosition(this.ikTargetBones.right,this.ikLegState.right.targetPosition),this.ikPreSolve.left.upper.copy(this.ikBoneRefs.left.upper.quaternion),this.ikPreSolve.left.lower.copy(this.ikBoneRefs.left.lower.quaternion),this.ikPreSolve.left.foot.copy(this.ikBoneRefs.left.foot.quaternion),this.ikPreSolve.right.upper.copy(this.ikBoneRefs.right.upper.quaternion),this.ikPreSolve.right.lower.copy(this.ikBoneRefs.right.lower.quaternion),this.ikPreSolve.right.foot.copy(this.ikBoneRefs.right.foot.quaternion),null!=this.ikDebugLegs&&(this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1),this.ikSolver.update(),this.blendLegAfterSolve(this.ikBoneRefs.left,this.ikPreSolve.left,this.ikLegState.left.weight),this.blendLegAfterSolve(this.ikBoneRefs.right,this.ikPreSolve.right,this.ikLegState.right.weight),this.applySimpleFootPitch("left",this.ikBoneRefs.left.foot,this.ikLegState.left),void this.applySimpleFootPitch("right",this.ikBoneRefs.right.foot,this.ikLegState.right))}resetFootIkState(){if(null!=this.ikBoneRefs){for(const t of G){const e=this.ikBoneRefs[t],o=this.ikLegState[t],i=e.foot.getWorldPosition(F);o.targetPosition.copy(i),o.lastFootWorldPos.copy(i),o.hasLastFootSample=!0,o.weight=0,o.normal.set(0,1,0);const s=this.resolveFootAxes(t,e.foot,this.footIkAxesScratch);o.forward.copy(s.forward),o.pitch=0,this.footIkAutoContactOffset?o.contactOffset=Math.max(o.contactOffset,this.footIkFootOffset+this.footIkExtraClearance):o.contactOffset=this.footIkFootOffset+this.footIkExtraClearance,o.planted=!1}this.ikPelvisOffsetY=0}}updatePelvisOffset(t,e){if(null==this.ikPelvisBone)return;let o=0;if(e&&this.footIkPelvisEnabled&&null!=this.ikBoneRefs&&null!=this.ikLegLengths){this.ikLegState.left.top=!1,this.ikLegState.right.top=!1;for(const t of G){const e=this.ikBoneRefs[t],i=this.ikLegLengths[t],s=this.ikLegState[t];if(!s.planted)continue;const r=e.upper.getWorldPosition(F),n=.998*i.total,l=this.computeRequiredPelvisDrop(r,s.targetPosition,n);if(l>0){const e="left"===t?"right":"left";this.ikLegState[e].top=!0}o=Math.min(o,-l)}o=y.clamp(o,-this.footIkPelvisMaxOffsetDown,this.footIkPelvisMaxOffsetUp)}const i=1-Math.exp(-this.footIkPelvisLerpSpeed*t);this.ikPelvisOffsetY=y.lerp(this.ikPelvisOffsetY,o,i);const s=this.ikPelvisBone.getWorldPosition(P),r=R.copy(s).addScaledVector(I,this.ikPelvisOffsetY);null==this.ikPelvisBone.parent?this.ikPelvisBone.position.copy(r):this.ikPelvisBone.position.copy(this.ikPelvisBone.parent.worldToLocal(r)),this.ikPelvisBone.updateMatrixWorld(!0)}computeFootVerticalSpeed(t,e,o){return!t.hasLastFootSample||o<=1e-6?0:(e.y-t.lastFootWorldPos.y)/o}updateFootSample(t,e){t.lastFootWorldPos.copy(e),t.hasLastFootSample=!0}estimateFootContactOffset(t,e,o){const i=this.footIkFootOffset+this.footIkExtraClearance;if(!this.footIkAutoContactOffset)return i;const s=t.bones.indexOf(o);if(s<0)return i;const r=t.boneInverses[s];if(null==r)return i;const n=this.ikFootAxes?.[e]??this.detectFootAxisBasis(o),a=o.getWorldPosition(P),h=R.copy(n.upLocal).applyQuaternion(o.getWorldQuaternion(T)).normalize();let c=0;return o.traverse(e=>{if(!(e instanceof l)||e===o)return;const i=t.bones.indexOf(e);if(i<0)return;const s=C.copy(t.boneInverses[i]).invert(),n=E.copy(r).multiply(s),d=F.setFromMatrixPosition(n),p=A.copy(d).applyMatrix4(o.matrixWorld).sub(a);c=Math.min(c,p.dot(h))}),Math.max(i,-c+this.footIkExtraClearance)}shouldPlantFoot(t,e,o,i,s,r){if(!e||!o)return!1;const n=this.footIkPlantReleaseExtension,l=this.footIkPlantAttachExtension,a=this.footIkPlantReleaseLift,h=this.footIkPlantAttachLift;return t.planted?!(i>this.footIkPlantReleaseUpSpeed&&(s<n||r>a)):s>=l&&r<=h||i<=0&&s>=n}computeLegExtensionRatio(t,e){const o=t.upper.getWorldPosition(F),i=t.foot.getWorldPosition(P),s=o.distanceTo(i);return e.total<=1e-6?1:y.clamp(s/e.total,0,1.2)}computeRequiredPelvisDrop(t,e,o){const i=A.subVectors(t,e),s=i.length();if(s<=o+1e-6)return 0;const r=i.dot(I),n=o*o-Math.max(s*s-r*r,0);if(n<=0)return s-o;const l=Math.sqrt(n),a=r-l,h=r+l;return a>=0?a:h>=0?h:0}updateLegTiltSimple(t,e,o,i,s){const r=this.footIkScratch,n=this.footIkHits,l=e.getWorldPosition(r.footWorldPos),a=this.computeFootVerticalSpeed(o,l,s),h=this.resolveFootAxes(t,e,this.footIkAxesScratch),c=this.resolveGroundSampleAxes(t,e,h,this.footIkSampleAxesScratch),d=r.centerRayStart.copy(l).addScaledVector(I,this.footIkRayStartHeight),p=r.toeRayStart.copy(d).addScaledVector(c.forward,this.footIkForwardSampleDistance),u=r.heelRayStart.copy(d).addScaledVector(c.forward,-this.footIkForwardSampleDistance),f=r.sideRayStart.copy(d).addScaledVector(c.right,this.footIkSideSampleDistance),g=this.getFirstGroundHit(d,n.center),m=this.getFirstGroundHit(p,n.toe),k=this.getFirstGroundHit(u,n.heel),S=this.getFirstGroundHit(f,n.side),w=r.desiredNormal.set(0,1,0),b=r.desiredForward.copy(c.forward);let L=0,v=0,B=this.footIkWeightOutSpeed;const x=null!=g||null!=m||null!=k;let D=l.y;null!=g?D=g.point.y:null!=m&&null!=k?D=.5*(m.point.y+k.point.y):null!=m?D=m.point.y:null!=k&&(D=k.point.y);const F=this.ikBoneRefs?.[t],P=this.ikLegLengths?.[t],R=null!=F&&null!=P?this.computeLegExtensionRatio(F,P):1,A=Math.max(0,l.y-D,l.y-o.targetPosition.y),M=this.shouldPlantFoot(o,!this.footIkRequireGrounded||i,x,a,R,A);M?this.computeDesiredGroundNormal(c,g,m,k,S,w)&&(this.computeDesiredFootForward(c.forward,c.right,w,m,k,b),L=this.computeDesiredPitchAngle(m,k,c.forward),v=1,B=this.footIkWeightInSpeed):this.computeDesiredFootForward(c.forward,c.right,w,null,null,b);const T=1-Math.exp(-this.footIkPositionLerpSpeed*s),W=1-Math.exp(-B*s);o.normal.lerp(w,T).normalize(),o.forward.lerp(b,T).normalize(),o.pitch=y.lerp(o.pitch,L,T),o.weight=y.lerp(o.weight,v,W),o.planted=M&&v>.001,this.updateFootSample(o,l),this.applySimpleFootPitch(t,e,o),this.updateLegDebug(t,{footWorldPos:l,centerRayStart:d,toeRayStart:p,heelRayStart:u,sideRayStart:f,centerHit:g,toeHit:m,heelHit:k,sideHit:S,desiredNormal:o.normal,desiredTargetPos:r.footWorldPos,weight:o.weight})}updateLegIkTarget(t,e,o,i,s,r,n){const l=this.footIkScratch,a=this.footIkHits,h=e.foot,c=h.getWorldPosition(l.footWorldPos),d=this.computeFootVerticalSpeed(s,c,n),p=this.resolveFootAxes(t,h,this.footIkAxesScratch),u=this.resolveGroundSampleAxes(t,h,p,this.footIkSampleAxesScratch),f=l.centerRayStart.copy(c).addScaledVector(I,this.footIkRayStartHeight),g=l.toeRayStart.copy(f).addScaledVector(u.forward,this.footIkForwardSampleDistance),m=l.heelRayStart.copy(f).addScaledVector(u.forward,-this.footIkForwardSampleDistance),k=l.sideRayStart.copy(f).addScaledVector(u.right,this.footIkSideSampleDistance),S=this.getFirstGroundHit(f,a.center),w=this.getFirstGroundHit(g,a.toe),b=this.getFirstGroundHit(m,a.heel),L=this.getFirstGroundHit(k,a.side),v=l.desiredTargetPos.copy(c),B=l.desiredNormal.set(0,1,0),x=l.desiredForward.copy(u.forward);let D=0,F=0,P=this.footIkWeightOutSpeed;const R=null!=S||null!=w||null!=b;let A=c.y;null!=S?A=S.point.y:null!=w&&null!=b?A=.5*(w.point.y+b.point.y):null!=w?A=w.point.y:null!=b&&(A=b.point.y);const M=this.computeLegExtensionRatio(e,o),T=Math.max(0,c.y-A,c.y-s.targetPosition.y),W=this.shouldPlantFoot(s,!this.footIkRequireGrounded||r,R,d,M,T);if(W){if(v.copy(c),this.computeDesiredGroundNormal(u,S,w,b,L,B)){this.computeDesiredFootForward(u.forward,u.right,B,w,b,x),D=this.computeDesiredPitchAngle(w,b,u.forward);const t=Math.max(0,Math.sin(D))*this.footIkForwardSampleDistance*.45,e=Math.max(this.footIkFootOffset+this.footIkExtraClearance,s.contactOffset);v.y=A+e+t,s.top&&(v.y-=this.ikPelvisOffsetY/2),F=1,P=this.footIkWeightInSpeed}}else this.computeDesiredFootForward(u.forward,u.right,B,null,null,x),v.copy(c),v.y+=this.footIkFootOffset;this.clampDesiredFootTarget(e,o,c,v);const O=1-Math.exp(-this.footIkPositionLerpSpeed*n),V=1-Math.exp(-P*n);s.targetPosition.lerp(v,O),s.normal.lerp(B,O).normalize(),s.forward.lerp(x,O).normalize(),s.pitch=y.lerp(s.pitch,D,O),s.weight=y.lerp(s.weight,F,V),s.planted=W&&F>.001,this.updateFootSample(s,c),this.setBoneWorldPosition(i,s.targetPosition),this.updateLegDebug(t,{footWorldPos:c,centerRayStart:f,toeRayStart:g,heelRayStart:m,sideRayStart:k,centerHit:S,toeHit:w,heelHit:b,sideHit:L,desiredNormal:B,desiredTargetPos:s.targetPosition,weight:s.weight})}updateLegDebug(t,e){if(!this.footIkDebug||null==this.ikDebugLegs||null==this.ikBoneRefs)return;const o=this.ikDebugLegs[t],i=this.ikBoneRefs[t],s=this.resolveFootAxes(t,i.foot,this.footIkAxesScratch),r=this.footIkScratch,n=e.centerHit?.point??r.debugRayEndA.copy(e.centerRayStart).addScaledVector(B,this.footIkRayLength),l=e.toeHit?.point??r.debugRayEndB.copy(e.toeRayStart).addScaledVector(B,this.footIkRayLength),a=e.heelHit?.point??r.debugRayEndC.copy(e.heelRayStart).addScaledVector(B,this.footIkRayLength),h=e.sideHit?.point??r.debugRayEndD.copy(e.sideRayStart).addScaledVector(B,this.footIkRayLength);this.setDebugArrow(o.rayCenter,e.centerRayStart,n),this.setDebugArrow(o.rayToe,e.toeRayStart,l),this.setDebugArrow(o.rayHeel,e.heelRayStart,a),this.setDebugArrow(o.raySide,e.sideRayStart,h);const c=e.centerHit?.point??e.toeHit?.point??e.heelHit?.point??e.sideHit?.point??e.footWorldPos;this.setDebugArrow(o.hitNormal,c,r.debugRayEndE.copy(c).addScaledVector(e.desiredNormal,this.footIkDebugNormalLength)),this.setDebugArrow(o.footUp,e.footWorldPos,r.debugRayEndF.copy(e.footWorldPos).addScaledVector(s.up,this.footIkDebugAxisLength*(.15+e.weight))),this.setDebugArrow(o.footToTarget,e.footWorldPos,e.desiredTargetPos)}getFirstGroundHit(t,e){return"physics"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)?e:null:"physicsThenRender"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)||this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null:this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null}resolveGroundSampleAxes(t,e,o,i){const s=o??this.resolveFootAxes(t,e),r=i??{forward:new d,right:new d},n=this.actor.object.getWorldDirection(A);n.addScaledVector(I,-n.dot(I)),n.lengthSq()<1e-8&&n.copy(s.forward).addScaledVector(I,-s.forward.dot(I)),n.lengthSq()<1e-8&&n.set(0,0,1),n.normalize();const l=M.crossVectors(I,n);return l.lengthSq()<1e-8?l.copy(s.right):l.normalize(),l.dot(s.right)<0&&l.multiplyScalar(-1),r.forward.copy(n),r.right.copy(l),r}computeDesiredGroundNormal(t,e,o,i,s,r){const n=this.computeAverageHitNormal(e,o,i,s,A);let l=!1,a=0,h=0;if(null!=o&&null!=i){const e=P.subVectors(o.point,i.point).dot(t.forward);Math.abs(e)>1e-5&&(a=(o.point.y-i.point.y)/e,l=!0)}if(null!=s&&null!=e){const o=R.subVectors(s.point,e.point).dot(t.right);Math.abs(o)>1e-5&&(h=(s.point.y-e.point.y)/o,l=!0)}if(l&&(r.copy(I),r.addScaledVector(t.forward,-a),r.addScaledVector(t.right,-h),r.lengthSq()>1e-8?r.normalize():l=!1),l)null!=n&&r.dot(n)<0&&r.multiplyScalar(-1);else{if(null==n)return!1;r.copy(n),l=!0}return r.dot(I)<0&&r.multiplyScalar(-1),this.clampSlopeNormal(r),!0}computeAverageHitNormal(t,e,o,i,s){s.set(0,0,0);let r=0;return null!=t&&t.hasNormal&&(s.add(t.normal),r++),null!=e&&e.hasNormal&&(s.add(e.normal),r++),null!=o&&o.hasNormal&&(s.add(o.normal),r++),null!=i&&i.hasNormal&&(s.add(i.normal),r++),0===r||s.lengthSq()<1e-8?null:(s.multiplyScalar(1/r).normalize(),s)}computeDesiredFootForward(t,e,o,i,s,r){null!=i&&null!=s?r.subVectors(i.point,s.point):r.copy(t),r.addScaledVector(o,-r.dot(o)),r.lengthSq()<1e-8&&(r.copy(this.actor.object.getWorldDirection(A)),r.addScaledVector(o,-r.dot(o))),r.lengthSq()<1e-8&&r.crossVectors(o,e),r.lengthSq()<1e-8&&r.set(0,0,1),r.normalize();const n=A.copy(this.actor.object.getWorldDirection(A));n.addScaledVector(o,-n.dot(o)),n.lengthSq()<1e-8&&(n.copy(t),n.addScaledVector(o,-n.dot(o))),n.lengthSq()>1e-8&&n.normalize(),r.dot(n)<0&&r.multiplyScalar(-1)}computeDesiredPitchAngle(t,e,o){if(null==t||null==e)return 0;const i=P.subVectors(t.point,e.point),s=Math.abs(i.dot(o));if(s<1e-5)return 0;const r=t.point.y-e.point.y,n=y.degToRad(this.footIkMaxSlopeAngleDeg);return y.clamp(-Math.atan2(r,s),-n,n)}applySimpleFootPitch(t,e,o){if(null==e.parent||o.weight<=.001)return;const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o.pitch*o.weight;if(Math.abs(s)<=1e-5)return;const r=this.resolveLocalPitchSign(i),n=T.copy(e.quaternion),l=W.setFromAxisAngle(i.rightLocal,s*r);e.quaternion.copy(n.multiply(l))}resolveLocalPitchSign(t){const e=O.setFromAxisAngle(t.rightLocal,.15);return R.copy(t.upLocal).applyQuaternion(e).sub(t.upLocal).dot(t.forwardLocal)>=0?1:-1}clampDesiredFootTarget(t,e,o,i){const s=P.subVectors(i,o),r=s.dot(I),n=R.copy(s).addScaledVector(I,-r),l=n.length();l>this.footIkMaxHorizontalOffset&&l>1e-6&&n.multiplyScalar(this.footIkMaxHorizontalOffset/l);const a=y.clamp(r,-this.footIkMaxVerticalOffsetDown,this.footIkMaxVerticalOffsetUp);if(i.copy(o),i.add(n),i.addScaledVector(I,a),this.footIkPelvisEnabled)return;const h=t.upper.getWorldPosition(F).clone(),c=P.subVectors(i,h),d=c.length(),p=.995*e.total;d>p&&d>1e-6&&i.copy(h).addScaledVector(c,p/d)}solveTwoBoneLeg(t,e,o){const i=e.upper.getWorldPosition(F).clone(),s=e.lower.getWorldPosition(P).clone(),r=e.foot.getWorldPosition(R).clone(),n=i.distanceTo(s),l=s.distanceTo(r);if(n<1e-5||l<1e-5)return;const a=(new d).subVectors(o,i),h=a.length();if(h<1e-5)return;const c=Math.abs(n-l)+1e-4,p=n+l-1e-4,u=y.clamp(h,c,p),f=a.multiplyScalar(1/h),g=(new d).subVectors(s,i).normalize(),m=(new d).subVectors(r,s).normalize(),k=(new d).crossVectors(g,m);k.lengthSq()<1e-8&&(k.copy(this.actor.object.getWorldDirection(F).cross(I)),k.lengthSq()<1e-8&&k.set(1,0,0)),k.normalize();const S=(u*u+n*n-l*l)/(2*u),w=Math.max(n*n-S*S,0),b=Math.sqrt(w),L=(new d).copy(i).addScaledVector(f,S);let v=(new d).crossVectors(k,f);v.lengthSq()<1e-8&&(v=(new d).crossVectors(f,I),v.lengthSq()<1e-8&&(v=new d(1,0,0))),v.normalize();const B=(new d).copy(L).addScaledVector(v,b),x=(new d).copy(L).addScaledVector(v,-b),D=(new d).subVectors(s,L).dot(v)>=0?B:x;this.rotateBoneToward(e.upper,i,s,D),e.upper.updateMatrixWorld(!0);const A=e.lower.getWorldPosition(P),M=e.foot.getWorldPosition(R);this.rotateBoneToward(e.lower,A,M,o),e.lower.updateMatrixWorld(!0),this.updateSolveDebug(t,i,D,o)}updateSolveDebug(t,e,o,i){if(!this.footIkDebug||null==this.ikDebugLegs)return;const s=this.ikDebugLegs[t];this.setDebugArrow(s.solveUpper,e,o),this.setDebugArrow(s.solveLower,o,i)}rotateBoneToward(t,e,o,i){const s=(new d).subVectors(o,e),r=(new d).subVectors(i,e);if(s.lengthSq()<1e-10||r.lengthSq()<1e-10)return;if(s.normalize(),r.normalize(),s.dot(r)>.9999)return;const n=(new f).setFromUnitVectors(s,r),l=t.getWorldQuaternion(T),a=W.copy(n).multiply(l);if(null==t.parent)return void t.quaternion.copy(a);const h=t.parent.getWorldQuaternion(O),c=V.copy(h).invert().multiply(a);t.quaternion.copy(c)}detectFootAxisBasis(t){const e=t.getWorldQuaternion(T),o=this.actor.object.getWorldDirection(F);o.lengthSq()<1e-6&&o.set(0,0,1),o.normalize();const i=[{local:q.clone(),world:q.clone().applyQuaternion(e)},{local:H.clone(),world:H.clone().applyQuaternion(e)},{local:z.clone(),world:z.clone().applyQuaternion(e)}];i.push({local:q.clone().multiplyScalar(-1),world:q.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:H.clone().multiplyScalar(-1),world:H.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:z.clone().multiplyScalar(-1),world:z.clone().multiplyScalar(-1).applyQuaternion(e)});let s=i[0],r=-1/0;for(const t of i){const e=t.world.dot(I);e>r&&(r=e,s=t)}let n=i[0],l=-1/0;for(const t of i){if(Math.abs(t.world.dot(s.world))>.6)continue;const e=Math.abs(t.world.dot(o));e>l&&(l=e,n=t)}n.world.dot(o)<0&&(n={local:n.local.clone().multiplyScalar(-1),world:n.world.clone().multiplyScalar(-1)});const a=s.local.clone().normalize(),h=n.local.clone().normalize(),c=a.clone().cross(h).normalize();return{upLocal:a,forwardLocal:c.clone().cross(a).normalize(),rightLocal:c}}resolveFootAxes(t,e,o){const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o??{up:new d,forward:new d,right:new d},r=e.getWorldQuaternion(T);return s.up.copy(i.upLocal).applyQuaternion(r).normalize(),s.forward.copy(i.forwardLocal).applyQuaternion(r).normalize(),s.right.copy(i.rightLocal).applyQuaternion(r).normalize(),s}clampSlopeNormal(t){const e=y.clamp(t.dot(I),-1,1),o=Math.acos(e),i=y.degToRad(this.footIkMaxSlopeAngleDeg);if(o<=i||o<1e-5)return;const s=i/o;t.lerpVectors(I,t,s).normalize()}blendLegAfterSolve(t,e,o){if(!(o>=.999)){if(o<=.001)return t.upper.quaternion.copy(e.upper),t.lower.quaternion.copy(e.lower),void t.foot.quaternion.copy(e.foot);this.blendBoneQuaternion(t.upper,e.upper,o),this.blendBoneQuaternion(t.lower,e.lower,o),this.blendBoneQuaternion(t.foot,e.foot,o)}}blendBoneQuaternion(t,e,o){T.copy(t.quaternion),t.quaternion.copy(e).slerp(T,o)}alignFootToGroundNormal(t,e,o,i){if(o.weight<=.001||null==e.parent)return;const s=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),r=F.copy(o.normal).normalize(),n=P.copy(o.forward);if(n.addScaledVector(r,-n.dot(r)),n.lengthSq()<1e-8){const o=this.resolveFootAxes(t,e);n.copy(o.forward).addScaledVector(r,-o.forward.dot(r))}if(n.lengthSq()<1e-8)return;n.normalize();const l=R.crossVectors(r,n);if(l.lengthSq()<1e-8)return;l.normalize(),n.copy(A.crossVectors(l,r)).normalize(),C.makeBasis(s.rightLocal,s.upLocal,s.forwardLocal),T.setFromRotationMatrix(C),E.makeBasis(l,r,n),W.setFromRotationMatrix(E);const a=O.copy(W).multiply(V.copy(T).invert()),h=e.parent.getWorldQuaternion(V),c=W.copy(h).invert().multiply(a),d=(1-Math.exp(-this.footIkRotationLerpSpeed*i))*o.weight;e.quaternion.slerp(c,y.clamp(d,0,1))}getMixer(){return this.mixer}beginExternalControl(){this.externalControlActive=!0}endExternalControl(){this.externalControlActive=!1}stopSequenceAnimation(){this.currentFullBodyPriority=-1,this.externalControlActive=!1,null==this.fullBodyAction||this.fullBodyAction.isRunning()||(this.fullBodyAction=null),null==this.upperBodyAction||this.upperBodyAction.isRunning()||(this.upperBodyAction=null),this.fullBodyTimer=0}cancelRootMotionAction(t){null!=t&&this.fullBodyAction!==t||(this.currentFullBodyPriority=-1,this.externalControlActive=!1,this.fullBodyAction?.stop(),this.fullBodyAction=null,this.fullBodyTimer=0)}beginExternalAnimationControl(t,e={}){$(null!=this.mixer,"Can't begin external control before setup is called"),this.mixer.stopAllAction(),this.currentFullBodyPriority=99,this.fullBodyTimer=0;const o=this.mixer.clipAction(t);return o.setLoop(h,1),o.clampWhenFinished=!0,o.timeScale=e.timeScale??1,o.reset(),o.play(),this.fullBodyAction=o,this.externalControlActive=!0,o}syncMovementSpeed(t){if(null!=t){const e=t.getClip();if(e instanceof i&&e.fixedInPlace&&null!=this.movementSpeed){t.timeScale=e.duration/e.displacement*this.movementSpeed;const o=this.mixer.getRoot();o instanceof a&&(t.timeScale/=o.scale.x)}}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const e=this.stateMachines.indexOf(t);e>=0&&this.stateMachines.splice(e,1)}removeUpperStateMachine(t){const e=this.upperStateMachines.indexOf(t);e>=0&&this.upperStateMachines.splice(e,1)}playUpper(t,e={}){const o=e?.priority??1;o<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=o,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1,this.upperBodyTimer=0,this.upperBodyOverride=!0,this.overrideFadeTimeUpper=e.fadeTime)}play(t,e={}){$(null!=this.mixer,"Can't play animation before setup is called");const o=e.priority??1;o<this.currentFullBodyPriority||(this.currentFullBodyPriority=o,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),e),this.fullBodyAction.timeScale=e?.timeScale??1,this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction),this.overrideFadeTime=e.fadeTime)}onActionDone(t){return new Promise(e=>{const o=i=>{i.action===t&&(e(i.action),this.mixer.removeEventListener("finished",o))};this.mixer.addEventListener("finished",o)})}transition(t,e,o={}){const i=o?.fadeTime??this.fadeTime;if(null!=t&&t.getClip().uuid===e.uuid)return t.isRunning()||(t.reset(),null!=o.offset&&(t.time=o.offset),t.enabled=!0,t.weight=1,t.setEffectiveWeight(1),t.setEffectiveTimeScale(1),t.play(),!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0)),t;if(t&&t.isRunning()){const s=t,r=this.mixer.clipAction(e);r.reset(),null!=o.offset&&(r.time=o.offset),r.play(),r.enabled=!0,r.setEffectiveTimeScale(1),r.weight=1,s.crossFadeTo(r,i,!0),t=r}else(t=this.mixer.clipAction(e)).reset(),null!=o.offset&&(t.time=o.offset),t.enabled=!0,t.weight=1,t.setEffectiveWeight(1),t.setEffectiveTimeScale(1),t.play();return!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0),t}};_=t([o({inEditor:!0})],_);export{_ as CharacterAnimationComponent};function K(t,e){if(null==t)return e;const o=e.clone(),i=new Set(t.map(t=>t.name));return o.tracks=o.tracks.filter(t=>i.has(t.name.split(".")[0])),o}function Y(t){return t.flatMap(t=>function(t){const e=[];return t.traverse(t=>{e.push(t)}),e}(t)).filter(t=>t instanceof l)}function $(t,e){if(!1===t||"function"==typeof t&&!1===t())throw new Error(e)}function J(t,e){const o=new Map;return(i,...s)=>{const r=t(i);return o.has(r)||o.set(r,e(i,...s)),o.get(r)}}function X(t){let e;return t.traverse(t=>{(t instanceof l||t.isBone)&&null==e&&(e=t)}),e}function Z(t,e){let o=e;for(;null!=o;){if(o===t)return!0;o=o.parent}return!1}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -27,6 +27,7 @@ export declare class CharacterMovementComponent extends ActorComponent {
|
|
|
27
27
|
normalizedDirection: boolean;
|
|
28
28
|
/** Collide with other characters */
|
|
29
29
|
characterCollision: boolean;
|
|
30
|
+
allowRootMotionJumpCancel: boolean;
|
|
30
31
|
get autoStepMinWidth(): number;
|
|
31
32
|
set autoStepMinWidth(minWidth: number);
|
|
32
33
|
get autoStepDynamicObjects(): boolean;
|
|
@@ -56,6 +57,7 @@ export declare class CharacterMovementComponent extends ActorComponent {
|
|
|
56
57
|
private resetRootMotion;
|
|
57
58
|
private rootMotionInterpolant;
|
|
58
59
|
private rootMotionRootBone;
|
|
60
|
+
private rootMotionOptions;
|
|
59
61
|
/**
|
|
60
62
|
* Makes the character rotate to the direction of movement input instead
|
|
61
63
|
* of strafing or walking backwards
|
|
@@ -79,7 +81,8 @@ export declare class CharacterMovementComponent extends ActorComponent {
|
|
|
79
81
|
applyImpulse(impulse: Vector3): void;
|
|
80
82
|
private debugDirection;
|
|
81
83
|
private rootMotionAction;
|
|
82
|
-
setRootMotionAction(action: AnimationAction): void;
|
|
84
|
+
setRootMotionAction(action: AnimationAction, options?: RootMotionActionOptions): void;
|
|
85
|
+
private clearRootMotionAction;
|
|
83
86
|
private getWallDirection;
|
|
84
87
|
private moveTo;
|
|
85
88
|
getEffectiveGravity(): number;
|
|
@@ -90,4 +93,8 @@ export declare class CharacterMovementComponent extends ActorComponent {
|
|
|
90
93
|
private performMovement;
|
|
91
94
|
private arrowHelper;
|
|
92
95
|
}
|
|
96
|
+
export type RootMotionActionOptions = {
|
|
97
|
+
cancelWithJump?: boolean;
|
|
98
|
+
onJumpCancel?: () => void;
|
|
99
|
+
};
|
|
93
100
|
//# sourceMappingURL=character-movement.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as t,__metadata as e}from"tslib";import i from"@dimforge/rapier3d-compat";import{takeUntil as o}from"rxjs";import*as s from"three";import{ArrowHelper as n,MathUtils as r,Vector3 as a}from"three";import{RootMotionClip as c}from"../../../../../gameplay/animation/root-motion.js";import{ActionInput as h,AxisInput as l,RotationInput as p}from"../../../../../gameplay/input/index.js";import{PhysicsSystem as m,RayTestResult as u}from"../../../../../gameplay/services/physics/physics-system.js";import{CapsuleCollisionShape as d}from"../../../../../scene/collision/collision-shape.js";import{PhysicsBodyType as y}from"../../../../services/physics/physics-system.js";import{ActorComponent as g,Component as f}from"../../../component.js";import{CharacterMovementMode as S}from"./modes.js";import{inject as M}from"../../../../../gameplay/inject.js";const w=new a,v=new a,x=1/30,b=131070;let I=class extends g{get autoStepMinWidth(){return this.cc.autostepMinWidth()}set autoStepMinWidth(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),t,this.cc.autostepIncludesDynamicBodies())}get autoStepDynamicObjects(){return this.cc.autostepIncludesDynamicBodies()}set autoStepDynamicObjects(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),this.cc.autostepMinWidth(),t)}get autoStepMaxHeight(){return this.cc.autostepMaxHeight()}set autoStepMaxHeight(t){this.cc.enableAutostep(t,this.cc.autostepMinWidth(),this.cc.autostepIncludesDynamicBodies())}get snapToGround(){return this.cc.snapToGroundDistance()}set snapToGround(t){this.cc.enableSnapToGround(t)}set offset(t){this.cc.setOffset(t)}get offset(){return this.cc.offset()}set normalNudgeFactor(t){this.cc.setNormalNudgeFactor(t)}get normalNudgeFactor(){return this.cc.normalNudgeFactor()}constructor(){super(),this.directionInput=new l,this.jumpInput=new h,this.sprintInput=new h,this.rotationInput=new p,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.jumpInAir=!1,this.mass=50,this.allowSliding=!0,this.minSlopeSlideAngle=r.degToRad(70),this.maxSlopeClimbAngle=r.degToRad(70),this.applyImpulsesToDynamicBodies=!0,this.normalizedDirection=!0,this.characterCollision=!1,this.enabled=!0,this.velocity=new a,this.mode=S.walking,this.isSprinting=!1,this.pressedJump=!1,this.rayTestResult=new u,this.physicsSystem=M(m),this.resetRootMotion=!1,this.rotateToMovementDirection=!1,this.smoothRotation=!0,this.rotationSpeed=40,this.maxRotationSpeed=100,this.impulse=new a,this.impulseDamping=2;const t=this.cc=this.physicsSystem.getCharacterController(.1);t.enableSnapToGround(.1),t.enableAutostep(0,.1,!1)}onInit(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:y.kinematic,continousCollisionDetection:!1,friction:0,restitution:.5,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation);let e=this.rotationInput.rotation.y;const i=new a,n=new a,h=new a,l=new a,p=new a,m=new a,u=new a;let d=0,g=null;const f=new a,M=new a,I=new a,A=new a,R=new a,z=new a,C=new a,k=this.characterCollision?null:b;let E=this.rotateToMovementDirection;this.physicsSystem.beforeStep.pipe(o(this.disposed)).subscribe(o=>{if(this.checkGrounded(o),!this.enabled)return;if(M.set(0,0,0),null!=this.rootMotionAction){if(this.rootMotionAction.getClip()instanceof c){const t=this.rootMotionInterpolant;this.resetRootMotion&&(f.fromArray(t.evaluate(0)),this.resetRootMotion=!1),z.fromArray(t.evaluate(this.rootMotionAction.time)),M.subVectors(z,f),f.copy(z);(this.rootMotionRootBone??this.rootMotionAction.getRoot()).getWorldScale(R),M.multiply(R)}}o>x&&(o=x);const y=null!=this.rootMotionAction&&this.rootMotionAction.enabled,b=y&&0!==M.lengthSq();this.pressedJump=!y&&this.jumpInput.activated,this.isSprinting=!y&&this.sprintInput.activated;const B=E!==this.rotateToMovementDirection;let H=r.euclideanModulo(this.rotationInput.rotation.y-e+Math.PI,2*Math.PI)-Math.PI;B&&(this.actor.object.quaternion.setFromEuler(q.set(0,this.rotationInput.rotation.y,0)),E?this.actor.object.quaternion.setFromEuler(q.set(0,this.rotationInput.rotation.y,0)):(H=0,e=this.rotationInput.rotation.y),E=this.rotateToMovementDirection),h.copy(this.actor.position),l.set(-this.directionInput.vector.x,0,this.directionInput.vector.y).normalize();const N=!this.rotateToMovementDirection&&l.z<0?this.maxSpeedBackwards:(this.isSprinting?this.maxSpeedSprint:this.maxSpeed)*(this.normalizedDirection?1:Math.min(1,this.directionInput.vector.length()));if(u.set(0,0,0),y)e=this.rotationInput.rotation.y;else if(this.rotateToMovementDirection&&!y){if(l.lengthSq()>0&&this.mode!=S.falling){const t=this.smoothRotation,i=q.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,s=Math.atan2(l.x,l.z),n=.99*this.rotationInput.rotation.y+s;if(t){r.clamp(.5*l.dot(p)+.5,.001,1);const t=r.euclideanModulo(n-i+Math.PI,2*Math.PI)-Math.PI;let e=r.clamp(t*this.rotationSpeed*o,-this.maxRotationSpeed*o,this.maxRotationSpeed*o);Math.abs(e)>Math.abs(t)&&(e=t),this.actor.object.quaternion.setFromEuler(q.set(0,i+e,0))}else this.actor.object.quaternion.setFromEuler(q.set(0,n,0));p.lerp(l,o*this.rotationSpeed),e+=H,u.copy(this.actor.object.getWorldDirection(F).normalize())}}else b||(e+=H,this.actor.object.quaternion.multiply(G.setFromEuler(q.set(0,H,0))),l.lengthSq()>0&&u.copy(l).applyQuaternion(this.actor.object.quaternion).normalize());if(C.set(0,0,0),this.rayTestResult.hasHit&&null!=this.rayTestResult.actor&&this.physicsSystem.getLinearVelocity(this.rayTestResult.actor,C),this.mode===S.walking?(0!==u.lengthSq()?(d=Math.min(N,d),d=r.lerp(d,N,4*o)):d=0,m.copy(u).multiplyScalar(d),this.pressedJump&&(this.mode=S.falling,this.velocity.copy(m),this.velocity.y=this.jumpVelocity),m.y=o*this.getEffectiveGravity(),m.add(C)):this.mode===S.falling&&(this.pressedJump&&this.jumpInAir&&(this.mode=S.falling,this.velocity.copy(m),this.velocity.y=this.jumpVelocity),this.velocity.y+=o*this.getEffectiveGravity(),m.copy(this.velocity),m.addScaledVector(u,this.fallingMovementControl),this.fallingReorientation&&m.applyAxisAngle(new a(0,1,0),H)),b&&(I.copy(M).applyQuaternion(this.actor.quaternion),A.copy(I).divideScalar(o),this.mode===S.walking?(m.x=A.x+C.x,m.z=A.z+C.z):(m.x=A.x,m.z=A.z),l.lengthSq()>0)){const t=Math.sqrt(A.x*A.x+A.z*A.z);t>.4&&(d=t)}if(this.impulse.lengthSq()>.1){const t=Math.min(1,this.impulse.length()/5);m.x=r.lerp(m.x,this.impulse.x,t),m.z=r.lerp(m.z,this.impulse.z,t),m.y+=this.impulse.y;const e=Math.exp(-this.impulseDamping*o);this.impulse.x*=e,this.impulse.y>0?this.impulse.y+=o*this.getEffectiveGravity():this.impulse.y*=e,this.impulse.z*=e}else this.impulse.set(0,0,0);if(n.copy(m).normalize(),i.copy(m),m.length()>0||!this.isGrounded){if(w.copy(m).multiplyScalar(o),this.isGrounded&&this.mode===S.walking&&(this.rayTestResult.distance>t.offset()||(w.y=Math.max(0,C.y*o)),this.physicsSystem.getActorComputedMovement(this.actor,t,w,k),t.computedCollision(0,D),null!=D&&null!=D.normal1)){const e=(new s.Vector3).copy(D.normal1);Math.acos(e.dot(T))>t.maxSlopeClimbAngle()&&(w.y=.016*this.getEffectiveGravity()*.5)}v.copy(this.physicsSystem.getActorComputedMovement(this.actor,t,w,k))}else v.set(0,0,0);this.physicsSystem.setNextKinematicTranslation(this.actor,v);let P=function(t){if(t.numComputedCollisions()>0){const e=t.computedCollision(0);j.x=e.normal2.x,j.y=e.normal2.y,j.z=e.normal2.z;const i=j.angleTo(T);j.x=e.normal1.x,j.y=e.normal1.y,j.z=e.normal1.z;const o=j.angleTo(T);return!(i<100)&&o>t.minSlopeSlideAngle()}return!1}(t);this.isGrounded&&!P||this.mode!==S.falling&&(null==g?g=performance.now():performance.now()-g>100&&(this.mode=S.falling,this.velocity.copy(i))),this.isGrounded&&this.velocity.y<=0&&(this.mode,S.falling,this.mode=S.walking,this.velocity.y=0,g=null),this.mode,S.walking,this.horizontalSpeed=d})}applyImpulse(t){this.impulse.add(t)}debugDirection(){const t=new n(w,this.actor.position,1,65280);this.actor.object.parent.add(t),setTimeout(()=>{t.removeFromParent()},30);const e=new n(v,this.actor.position,1,16711680);this.actor.object.parent.add(e),setTimeout(()=>{e.removeFromParent()},30)}setRootMotionAction(t){const e=t?.getClip();if(e instanceof c){this.rootMotionAction=t,this.resetRootMotion=!0;const i=[];this.rootMotionInterpolant=e.motionTrack.InterpolantFactoryMethodSmooth(i);const o=s.PropertyBinding.parseTrackName(e.motionTrack.name);this.rootMotionRootBone=this.actor.object.getObjectByName(o.nodeName)}}getWallDirection(t,e){const i=t.clone().negate().cross(T);return i.dot(e)<0?i.negate():i}moveTo(t){this.actor.position.copy(t),this.physicsSystem.updateActorTransform(this.actor)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}checkGrounded(t){this.colliderHeight,this.colliderRadius;C.y=-.05,this.physicsSystem.rayTest(A.addVectors(this.actor.position,z.set(0,this.offset,0)),R.addVectors(this.actor.position,C),this.rayTestResult,{excludeActor:this.actor,excludeTriggers:!0})}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}createCollisionShape(){const t=new d(this.colliderHeight,this.colliderRadius);return t.offset.y=this.colliderRadius+this.colliderHeight/2+this.offset,t.collisionGroup=b,t}step(t){}performMovement(t){}arrowHelper(t,e,i){const o=new n(t.clone().normalize(),e,1,i);this.actor.object.parent.add(o),setTimeout(()=>{o.removeFromParent()},30)}};I=t([f({inEditor:!1}),e("design:paramtypes",[])],I);export{I as CharacterMovementComponent};const T=new a(0,1,0),j=new a;const A=new a,R=new a,z=new a(0,1,0),C=new a(0,-.1,0),D=(new a(0,-1,0),new i.CharacterCollision),G=new s.Quaternion,q=new s.Euler,F=new s.Vector3;/*
|
|
1
|
+
import{__decorate as t,__metadata as o}from"tslib";import i from"@dimforge/rapier3d-compat";import{takeUntil as e}from"rxjs";import*as s from"three";import{ArrowHelper as n,MathUtils as r,Vector3 as a}from"three";import{RootMotionClip as c}from"../../../../../gameplay/animation/root-motion.js";import{ActionInput as h,AxisInput as l,RotationInput as p}from"../../../../../gameplay/input/index.js";import{PhysicsSystem as m,RayTestResult as u}from"../../../../../gameplay/services/physics/physics-system.js";import{CapsuleCollisionShape as d}from"../../../../../scene/collision/collision-shape.js";import{PhysicsBodyType as y}from"../../../../services/physics/physics-system.js";import{ActorComponent as g,Component as M}from"../../../component.js";import{CharacterMovementMode as f}from"./modes.js";import{inject as S}from"../../../../../gameplay/inject.js";const w=new a,v=new a,x=1/30,A=131070;let I=class extends g{get autoStepMinWidth(){return this.cc.autostepMinWidth()}set autoStepMinWidth(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),t,this.cc.autostepIncludesDynamicBodies())}get autoStepDynamicObjects(){return this.cc.autostepIncludesDynamicBodies()}set autoStepDynamicObjects(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),this.cc.autostepMinWidth(),t)}get autoStepMaxHeight(){return this.cc.autostepMaxHeight()}set autoStepMaxHeight(t){this.cc.enableAutostep(t,this.cc.autostepMinWidth(),this.cc.autostepIncludesDynamicBodies())}get snapToGround(){return this.cc.snapToGroundDistance()}set snapToGround(t){this.cc.enableSnapToGround(t)}set offset(t){this.cc.setOffset(t)}get offset(){return this.cc.offset()}set normalNudgeFactor(t){this.cc.setNormalNudgeFactor(t)}get normalNudgeFactor(){return this.cc.normalNudgeFactor()}constructor(){super(),this.directionInput=new l,this.jumpInput=new h,this.sprintInput=new h,this.rotationInput=new p,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.jumpInAir=!1,this.mass=50,this.allowSliding=!0,this.minSlopeSlideAngle=r.degToRad(70),this.maxSlopeClimbAngle=r.degToRad(70),this.applyImpulsesToDynamicBodies=!0,this.normalizedDirection=!0,this.characterCollision=!1,this.allowRootMotionJumpCancel=!1,this.enabled=!0,this.velocity=new a,this.mode=f.walking,this.isSprinting=!1,this.pressedJump=!1,this.rayTestResult=new u,this.physicsSystem=S(m),this.resetRootMotion=!1,this.rootMotionOptions={},this.rotateToMovementDirection=!1,this.smoothRotation=!0,this.rotationSpeed=40,this.maxRotationSpeed=100,this.impulse=new a,this.impulseDamping=2;const t=this.cc=this.physicsSystem.getCharacterController(.1);t.enableSnapToGround(.1),t.enableAutostep(0,.1,!1)}onInit(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:y.kinematic,continousCollisionDetection:!1,friction:0,restitution:.5,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation);let o=this.rotationInput.rotation.y;const i=new a,n=new a,h=new a,l=new a,p=new a,m=new a,u=new a;let d=0,g=null;const M=new a,S=new a,I=new a,j=new a,R=new a,z=new a,C=new a,k=this.characterCollision?null:A;let E=this.rotateToMovementDirection;this.physicsSystem.beforeStep.pipe(e(this.disposed)).subscribe(e=>{if(this.checkGrounded(e),!this.enabled)return;if(S.set(0,0,0),null==this.rootMotionAction||this.rootMotionAction.isRunning()||this.clearRootMotionAction(this.rootMotionAction),null!=this.rootMotionAction&&this.rootMotionOptions.cancelWithJump&&this.jumpInput.activated&&(this.isGrounded||this.jumpInAir)){const t=this.rootMotionAction,o=this.rootMotionOptions.onJumpCancel;this.clearRootMotionAction(t),t.stop(),o?.()}if(null!=this.rootMotionAction){if(this.rootMotionAction.getClip()instanceof c){const t=this.rootMotionInterpolant;this.resetRootMotion&&(M.fromArray(t.evaluate(0)),this.resetRootMotion=!1),z.fromArray(t.evaluate(this.rootMotionAction.time)),S.subVectors(z,M),M.copy(z);(this.rootMotionRootBone??this.rootMotionAction.getRoot()).getWorldScale(R),S.multiply(R)}}e>x&&(e=x);const y=null!=this.rootMotionAction&&this.rootMotionAction.enabled,A=y&&0!==S.lengthSq();this.pressedJump=!y&&this.jumpInput.activated,this.isSprinting=!y&&this.sprintInput.activated;const B=E!==this.rotateToMovementDirection;let H=r.euclideanModulo(this.rotationInput.rotation.y-o+Math.PI,2*Math.PI)-Math.PI;B&&(this.actor.object.quaternion.setFromEuler(q.set(0,this.rotationInput.rotation.y,0)),E?this.actor.object.quaternion.setFromEuler(q.set(0,this.rotationInput.rotation.y,0)):(H=0,o=this.rotationInput.rotation.y),E=this.rotateToMovementDirection),h.copy(this.actor.position),l.set(-this.directionInput.vector.x,0,this.directionInput.vector.y).normalize();const O=!this.rotateToMovementDirection&&l.z<0?this.maxSpeedBackwards:(this.isSprinting?this.maxSpeedSprint:this.maxSpeed)*(this.normalizedDirection?1:Math.min(1,this.directionInput.vector.length()));if(u.set(0,0,0),y)o=this.rotationInput.rotation.y;else if(this.rotateToMovementDirection&&!y){if(l.lengthSq()>0&&this.mode!=f.falling){const t=this.smoothRotation,i=q.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,s=Math.atan2(l.x,l.z),n=.99*this.rotationInput.rotation.y+s;if(t){r.clamp(.5*l.dot(p)+.5,.001,1);const t=r.euclideanModulo(n-i+Math.PI,2*Math.PI)-Math.PI;let o=r.clamp(t*this.rotationSpeed*e,-this.maxRotationSpeed*e,this.maxRotationSpeed*e);Math.abs(o)>Math.abs(t)&&(o=t),this.actor.object.quaternion.setFromEuler(q.set(0,i+o,0))}else this.actor.object.quaternion.setFromEuler(q.set(0,n,0));p.lerp(l,e*this.rotationSpeed),o+=H,u.copy(this.actor.object.getWorldDirection(F).normalize())}}else A||(o+=H,this.actor.object.quaternion.multiply(G.setFromEuler(q.set(0,H,0))),l.lengthSq()>0&&u.copy(l).applyQuaternion(this.actor.object.quaternion).normalize());if(C.set(0,0,0),this.rayTestResult.hasHit&&null!=this.rayTestResult.actor&&this.physicsSystem.getLinearVelocity(this.rayTestResult.actor,C),this.mode===f.walking?(0!==u.lengthSq()?(d=Math.min(O,d),d=r.lerp(d,O,4*e)):d=0,m.copy(u).multiplyScalar(d),this.pressedJump&&(this.mode=f.falling,this.velocity.copy(m),this.velocity.y=this.jumpVelocity),m.y=e*this.getEffectiveGravity(),m.add(C)):this.mode===f.falling&&(this.pressedJump&&this.jumpInAir&&(this.mode=f.falling,this.velocity.copy(m),this.velocity.y=this.jumpVelocity),this.velocity.y+=e*this.getEffectiveGravity(),m.copy(this.velocity),m.addScaledVector(u,this.fallingMovementControl),this.fallingReorientation&&m.applyAxisAngle(new a(0,1,0),H)),A&&(I.copy(S).applyQuaternion(this.actor.quaternion),j.copy(I).divideScalar(e),this.mode===f.walking?(m.x=j.x+C.x,m.z=j.z+C.z):(m.x=j.x,m.z=j.z),l.lengthSq()>0)){const t=Math.sqrt(j.x*j.x+j.z*j.z);t>.4&&(d=t)}if(this.impulse.lengthSq()>.1){const t=Math.min(1,this.impulse.length()/5);m.x=r.lerp(m.x,this.impulse.x,t),m.z=r.lerp(m.z,this.impulse.z,t),m.y+=this.impulse.y;const o=Math.exp(-this.impulseDamping*e);this.impulse.x*=o,this.impulse.y>0?this.impulse.y+=e*this.getEffectiveGravity():this.impulse.y*=o,this.impulse.z*=o}else this.impulse.set(0,0,0);if(n.copy(m).normalize(),i.copy(m),m.length()>0||!this.isGrounded){if(w.copy(m).multiplyScalar(e),this.isGrounded&&this.mode===f.walking&&(this.rayTestResult.distance>t.offset()||(w.y=Math.max(0,C.y*e)),this.physicsSystem.getActorComputedMovement(this.actor,t,w,k),t.computedCollision(0,D),null!=D&&null!=D.normal1)){const o=(new s.Vector3).copy(D.normal1);Math.acos(o.dot(b))>t.maxSlopeClimbAngle()&&(w.y=.016*this.getEffectiveGravity()*.5)}v.copy(this.physicsSystem.getActorComputedMovement(this.actor,t,w,k))}else v.set(0,0,0);this.physicsSystem.setNextKinematicTranslation(this.actor,v);let N=function(t){if(t.numComputedCollisions()>0){const o=t.computedCollision(0);T.x=o.normal2.x,T.y=o.normal2.y,T.z=o.normal2.z;const i=T.angleTo(b);T.x=o.normal1.x,T.y=o.normal1.y,T.z=o.normal1.z;const e=T.angleTo(b);return!(i<100)&&e>t.minSlopeSlideAngle()}return!1}(t);this.isGrounded&&!N||this.mode!==f.falling&&(null==g?g=performance.now():performance.now()-g>100&&(this.mode=f.falling,this.velocity.copy(i))),this.isGrounded&&this.velocity.y<=0&&(this.mode,f.falling,this.mode=f.walking,this.velocity.y=0,g=null),this.mode,f.walking,this.horizontalSpeed=d})}applyImpulse(t){this.impulse.add(t)}debugDirection(){const t=new n(w,this.actor.position,1,65280);this.actor.object.parent.add(t),setTimeout(()=>{t.removeFromParent()},30);const o=new n(v,this.actor.position,1,16711680);this.actor.object.parent.add(o),setTimeout(()=>{o.removeFromParent()},30)}setRootMotionAction(t,o={}){const i=t?.getClip();if(i instanceof c){this.rootMotionAction=t,this.rootMotionOptions=o,this.resetRootMotion=!0;const e=[];this.rootMotionInterpolant=i.motionTrack.InterpolantFactoryMethodSmooth(e);const n=s.PropertyBinding.parseTrackName(i.motionTrack.name);this.rootMotionRootBone=this.actor.object.getObjectByName(n.nodeName)}}clearRootMotionAction(t){null!=t&&this.rootMotionAction!==t||(this.rootMotionAction=null,this.rootMotionOptions={},this.resetRootMotion=!1)}getWallDirection(t,o){const i=t.clone().negate().cross(b);return i.dot(o)<0?i.negate():i}moveTo(t){this.actor.position.copy(t),this.physicsSystem.updateActorTransform(this.actor)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}checkGrounded(t){this.colliderHeight,this.colliderRadius;C.y=-.05,this.physicsSystem.rayTest(j.addVectors(this.actor.position,z.set(0,this.offset,0)),R.addVectors(this.actor.position,C),this.rayTestResult,{excludeActor:this.actor,excludeTriggers:!0})}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}createCollisionShape(){const t=new d(this.colliderHeight,this.colliderRadius);return t.offset.y=this.colliderRadius+this.colliderHeight/2+this.offset,t.collisionGroup=A,t}step(t){}performMovement(t){}arrowHelper(t,o,i){const e=new n(t.clone().normalize(),o,1,i);this.actor.object.parent.add(e),setTimeout(()=>{e.removeFromParent()},30)}};I=t([M({inEditor:!1}),o("design:paramtypes",[])],I);export{I as CharacterMovementComponent};const b=new a(0,1,0),T=new a;const j=new a,R=new a,z=new a(0,1,0),C=new a(0,-.1,0),D=(new a(0,-1,0),new i.CharacterCollision),G=new s.Quaternion,q=new s.Euler,F=new s.Vector3;/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{BackSide as t,Color as e,DoubleSide as a,FrontSide as r,Matrix4 as u,Texture as i,Vector2 as o,Vector3 as n,Vector4 as s}from"three";import{BooleanNode as l,FloatNode as p,Mat4Node as c,NodeShaderMaterial as h,RgbNode as v,RgbaNode as y,Sampler2DNode as d,Texture2dLookupNode as m,UniformFloatNode as f,Vec2Node as g,Vec3Node as b,Vec4Node as x,abs as w,acos as I,asin as S,attributes as T,atan as O,autoVarying as M,bulge as C,bool as N,ceil as E,clamp as U,cos as G,cross as B,degrees as $,distance as z,dot as A,exp as k,exp2 as V,float as j,floor as D,fract as q,inversesqrt as L,colorGradientSampler as P,length as F,LayerMixMode as R,log as W,log2 as Y,mat4 as H,max as J,min as K,mix as Q,mixColorsByLayer as X,particleUniforms as Z,mod as _,normalize as tt,pow as et,radians as at,rgba as rt,rgb as ut,saturate as it,select as ot,sign as nt,sin as st,smoothstep as lt,sqrt as pt,standardMaterial as ct,scaleTransform as ht,step as vt,tan as yt,textureSampler2d as dt,timeUniforms as mt,toonMaterial as ft,translate as gt,transformed as bt,triplanarMapping as xt,twirl as wt,uniformFloat as It,uniforms as St,varyingAttributes as Tt,vec2 as Ot,vec3 as Mt,vec4 as Ct,getPaintedMaterialLayerWeight as Nt}from"../../shader-nodes/index.js";import{SpriteNodeShaderMaterial as Et,getSpritePosition as Ut}from"../sprite-shader.js";import{oneMinus as Gt}from"../../shader-nodes/index.js";import{vectorToRadial as Bt,remap as $t,hueShift as zt,blendColor as At,desaturateColor as kt}from"../../shader-nodes/math.js";import{rectangleFloat as Vt,roundedRectangleFloat as jt}from"../../shader-nodes/shapes.js";import{edgeDepthEffect as Dt,fresnelEffect as qt,depthFadeEffect as Lt}from"../../shader-nodes/effects.js";import{fragmentLinearEyeDepth as Pt,sampleSceneDepth as Ft,sampleSceneLinearEyeDepth as Rt,screenUV as Wt,nearUniformName as Yt,farUniformName as Ht}from"../../shader-nodes/depth.js";import{sampleSceneColor as Jt}from"../../shader-nodes/scene-sample.js";import{decalDiscard as Kt,decalUV as Qt}from"../../shader-nodes/decal.js";import{Trail as Xt,trailUV as Zt}from"../../effects/vfx/trail-renderer.js";import{SimplexNoiseNode as _t,Voronoi2d as te,rotateAxis as ee}from"../../shader-nodes/index.js";import{flipbookUv as ae}from"../../shader-nodes/texture-sequence.js";import{parallaxOcclusionMapping as re}from"../../shader-nodes/pom.js";import{SHADER_GRAPH_NODE_DEFINITIONS as ue}from"./registry.js";import{shaderGraphParameterTypeToValueType as ie}from"./parameters.js";import{varying as oe,reflect as ne,refract as se,dFdx as le,dFdy as pe,fwidth as ce}from"three-shader-graph";import{decalNormal as he}from"../../shader-nodes/decal.js";export class ShaderGraphCompileError extends Error{constructor(t,e,a){super(t),this.nodeId=e,this.port=a,this.name="ShaderGraphCompileError"}}export class ShaderGraphCompiler{constructor(t,e={}){this.graph=t,this.options=e,this.compiled=new Map,this.nodesById=new Map((t.nodes??[]).map(t=>[t.id,t]))}validate(){this.compile()}compile(){if(1!==this.graph.version)throw new ShaderGraphCompileError(`Unsupported shader graph version ${this.graph.version}`);return this.validateEdges(),{output:this.compileOutput(),nodes:this.compiled}}validateEdges(){for(const t of this.graph.edges??[]){if(!this.nodesById.has(t.from.nodeId))throw new ShaderGraphCompileError(`Edge references missing source node "${t.from.nodeId}"`,t.from.nodeId,t.from.port);if(!this.nodesById.has(t.to.nodeId))throw new ShaderGraphCompileError(`Edge references missing target node "${t.to.nodeId}"`,t.to.nodeId,t.to.port)}}compileOutput(){const t=this.graph.outputs?.color,e={color:null!=t?this.toColorOutput(this.resolveOutputBinding(t,"color")):rt("#ffffff",1),transparent:ve(this.graph)},a=this.graph.outputs?.opacity;null!=a&&(e.opacity=this.expectType(this.resolveOutputBinding(a,"opacity"),["float"],"opacity").value);const r=this.graph.outputs?.roughness;null!=r&&(e.roughness=this.expectType(this.resolveOutputBinding(r,"roughness"),["float"],"roughness").value);const u=this.graph.outputs?.metalness;null!=u&&(e.metalness=this.floatOutput(u,"metalness"));const i=this.graph.outputs?.normal;null!=i&&(e.normal=this.toVec3Output(this.resolveOutputBinding(i,"normal"),"normal"));const o=this.graph.outputs?.emissive;null!=o&&(e.emissive=this.toVec3Output(this.resolveOutputBinding(o,"emissive"),"emissive"));const n=this.graph.outputs?.ambientOcclusion;null!=n&&(e.ambientOcclusion=this.floatOutput(n,"ambientOcclusion"));const s=this.graph.outputs?.ambientOcclusionIntensity;null!=s&&(e.ambientOcclusionIntensity=this.floatOutput(s,"ambientOcclusionIntensity"));const l=this.graph.outputs?.sheenColor;null!=l&&(e.sheenColor=this.toVec3Output(this.resolveOutputBinding(l,"sheenColor"),"sheenColor"));const p=this.graph.outputs?.sheenRoughness;null!=p&&(e.sheenRoughness=this.floatOutput(p,"sheenRoughness"));const c=this.graph.outputs?.anisotropy;null!=c&&(e.anisotropy=this.floatOutput(c,"anisotropy"));const h=this.graph.outputs?.anisotropyDirection;null!=h&&(e.anisotropyDirection=this.expectType(this.resolveOutputBinding(h,"anisotropyDirection"),["vec2"],"anisotropyDirection").value);const v=this.graph.outputs?.bakedLight;null!=v&&(e.bakedLight=this.toVec3Output(this.resolveOutputBinding(v,"bakedLight"),"bakedLight"));const y=this.graph.outputs?.transform;null!=y&&"decal"!==this.graph.target&&(e.transform=this.toMat4Output(this.resolveOutputBinding(y,"transform"),"transform"));const d=this.graph.outputs?.discard;null!=d&&(e.discard=this.expectType(this.resolveOutputBinding(d,"discard"),["boolean"],"discard").value);const m=this.graph.outputs?.transparent;null!=m&&null!=m.value&&(e.transparent=Boolean(m.value));const f=this.graph.outputs?.alphaTest;return null!=f&&null!=f.value&&(e.alphaTest=Number(f.value)),this.applyShadingModel(e)}applyShadingModel(t){const e=null!=t.opacity?function(t,e){if(t instanceof p)return rt(Mt(t,t,t),e);if(t instanceof g)return rt(Mt(t.x,t.y,0),e);if(t instanceof x)return rt(t.rgb,t.w.multiply(e));return rt(t,e)}(t.color,t.opacity):t.color;switch(this.graph.shadingModel??"standard"){case"standard":{const a={color:fe(e),roughness:t.roughness??j(.5),...null!=t.metalness?{metalness:t.metalness}:{},..."decal"===this.graph.target?{normal:tt(oe(St.normalMatrix).multiplyVec(he))}:{},...null!=t.normal?{normal:t.normal}:{},...null!=t.emissive?{emissive:ge(t.emissive)}:{},...null!=t.ambientOcclusion?{ambientOcclusion:t.ambientOcclusion}:{},...null!=t.ambientOcclusionIntensity?{ambientOcclusionIntensity:t.ambientOcclusionIntensity}:{},...null!=t.sheenColor?{sheenColor:t.sheenColor.rgb}:{},...null!=t.sheenRoughness?{sheenRoughness:t.sheenRoughness}:{},...null!=t.anisotropy?{anisotropy:t.anisotropy}:{},...null!=t.anisotropyDirection?{anisotropyDirection:t.anisotropyDirection}:{},...null!=t.bakedLight?{bakedLight:t.bakedLight}:{}};return{...t,color:ct(a)}}case"toon":{const a={color:fe(e),...null!=t.normal?{normal:t.normal}:{},...null!=t.emissive?{emissive:ge(t.emissive)}:{},...null!=t.ambientOcclusion?{ambientOcclusion:t.ambientOcclusion}:{},...null!=t.ambientOcclusionIntensity?{ambientOcclusionIntensity:t.ambientOcclusionIntensity}:{},...null!=t.bakedLight?{bakedLight:t.bakedLight}:{}};return{...t,color:ft(a)}}case"unlit":return{...t,color:e}}}compileNode(t){const e=this.compiled.get(t);if(null!=e)return e;const a=this.nodesById.get(t);if(null==a)throw new ShaderGraphCompileError(`Missing shader graph node "${t}"`,t);if(null==ue[a.kind])throw new ShaderGraphCompileError(`Unsupported shader graph node "${a.kind}"`,a.id);const r=this.compileNodeInternal(a);return this.compiled.set(t,r),r}compileNodeInternal(t){switch(t.kind){case"input.parameter":return this.output(t,this.compileParameterNode(t));case"input.slider":return this.output(t,{value:{type:"float",value:j(Ne(xe(t,"value",.5)))}});case"constant.boolean":return this.output(t,{value:{type:"boolean",value:N(Boolean(be(t,"value",!1)))}});case"constant.float":return this.output(t,{value:{type:"float",value:j(xe(t,"value",0))}});case"constant.vec2":return this.output(t,{value:{type:"vec2",value:Ge(be(t,"value",[0,0]))}});case"constant.vec3":return this.output(t,{value:{type:"vec3",value:Be(be(t,"value",[0,0,0]))}});case"constant.rgba":return this.output(t,{value:{type:"rgba",value:$e(be(t,"value","#ffffff"),xe(t,"alpha",1))}});case"builtin.uv":{const e=this.defaultUV();return this.output(t,{value:{type:"vec2",value:!0===be(t,"flipY",!1)?Ot(e.x,Gt(e.y)):e},u:{type:"float",value:e.x},v:{type:"float",value:e.y}})}case"builtin.screenUv":return this.output(t,{value:{type:"vec2",value:Wt}});case"builtin.color":{const e=M(T.color);return this.output(t,{value:{type:"rgba",value:e},rgb:{type:"rgb",value:e.rgb},r:{type:"float",value:e.r},g:{type:"float",value:e.g},b:{type:"float",value:e.b},a:{type:"float",value:e.a}})}case"builtin.position":{const e=M(T.position);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.worldPosition":{const e=M(bt.worldPosition);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.viewDir":{const e=M(bt.viewDir);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.normal":{const e=M(T.normal);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.time":return this.output(t,{value:{type:"float",value:mt.elapsed}});case"builtin.camera":{const e=It(Yt),a=It(Ht),r=St.cameraPosition;return this.output(t,{position:{type:"vec3",value:r},x:{type:"float",value:r.x},y:{type:"float",value:r.y},z:{type:"float",value:r.z},near:{type:"float",value:e},far:{type:"float",value:a}})}case"builtin.particle":return this.output(t,{energy:{type:"float",value:Z.energy},color:{type:"rgb",value:Z.color},opacity:{type:"float",value:Z.opacity},time:{type:"float",value:Z.time}});case"math.add":case"math.subtract":case"math.multiply":case"math.divide":return this.output(t,{value:this.compileBinaryMath(t)});case"math.oneMinus":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:e.type,value:Gt(e.value)}})}case"math.abs":return this.output(t,{value:this.compileUnaryMath(t,w)});case"math.sign":return this.output(t,{value:this.compileUnaryMath(t,nt)});case"math.floor":return this.output(t,{value:this.compileUnaryMath(t,D)});case"math.ceil":return this.output(t,{value:this.compileUnaryMath(t,E)});case"math.fract":return this.output(t,{value:this.compileUnaryMath(t,q)});case"math.sin":return this.output(t,{value:this.compileUnaryMath(t,st)});case"math.cos":return this.output(t,{value:this.compileUnaryMath(t,G)});case"math.tan":return this.output(t,{value:this.compileUnaryMath(t,yt)});case"math.asin":return this.output(t,{value:this.compileUnaryMath(t,S)});case"math.acos":return this.output(t,{value:this.compileUnaryMath(t,I)});case"math.atan":return this.output(t,{value:this.compileUnaryMath(t,O)});case"math.radians":return this.output(t,{value:this.compileUnaryMath(t,at)});case"math.degrees":return this.output(t,{value:this.compileUnaryMath(t,$)});case"math.sqrt":return this.output(t,{value:this.compileUnaryMath(t,pt)});case"math.inverseSqrt":return this.output(t,{value:this.compileUnaryMath(t,L)});case"math.exp":return this.output(t,{value:this.compileUnaryMath(t,k)});case"math.exp2":return this.output(t,{value:this.compileUnaryMath(t,V)});case"math.log":return this.output(t,{value:this.compileUnaryMath(t,W)});case"math.log2":return this.output(t,{value:this.compileUnaryMath(t,Y)});case"math.saturate":return this.output(t,{value:this.compileUnaryMath(t,it)});case"math.length":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:"float",value:F(e.value)}})}case"math.normalize":return this.output(t,{value:this.compileUnaryMath(t,tt)});case"math.clamp":{const e=this.expectNumeric(this.input(t,"value")),a=this.expectNumeric(this.input(t,"min",{type:"float",value:j(0)})),r=this.expectNumeric(this.input(t,"max",{type:"float",value:j(1)}));return this.output(t,{value:{type:e.type,value:U(e.value,a.value,r.value)}})}case"math.min":return this.output(t,{value:this.compileBinaryFunction(t,K)});case"math.max":return this.output(t,{value:this.compileBinaryFunction(t,J)});case"math.pow":return this.output(t,{value:this.compileBinaryFunction(t,et)});case"math.mod":return this.output(t,{value:this.compileBinaryFunction(t,_)});case"math.step":return this.output(t,{value:this.compileBinaryFunction(t,vt,!0)});case"math.smoothstep":{const e=this.expectNumeric(this.input(t,"edge0",{type:"float",value:j(0)})),a=this.expectNumeric(this.input(t,"edge1",{type:"float",value:j(1)})),r=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:r.type,value:lt(e.value,a.value,r.value)}})}case"math.mix":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b")),r=this.expectNumeric(this.input(t,"t",{type:"float",value:j(.5)})),u=Te(e.type,a.type,t.id);return this.output(t,{value:{type:u,value:Q(e.value,a.value,r.value)}})}case"math.remap":{const e=this.expectType(this.input(t,"value"),["float"],t.id,"value").value,a=this.floatInput(t,"inMin",-1),r=this.floatInput(t,"inMax",1),u=this.floatInput(t,"outMin",0),i=this.floatInput(t,"outMax",1);return this.output(t,{value:{type:"float",value:$t(e,a,r,u,i)}})}case"math.select":{const e=this.boolInput(t,"condition",!1),a=this.expectNumeric(this.input(t,"a")),r=this.expectNumeric(this.input(t,"b")),u=Te(a.type,r.type,t.id);return this.output(t,{value:{type:u,value:ot(e,a.value,r.value)}})}case"math.reflect":{const e=this.expectType(this.input(t,"incident"),["vec2","vec3","vec4","rgb","rgba"],t.id,"incident"),a=this.expectType(this.input(t,"normal"),["vec2","vec3","vec4","rgb","rgba"],t.id,"normal");return this.output(t,{value:{type:e.type,value:ne(e.value,a.value)}})}case"math.refract":{const e=this.expectType(this.input(t,"incident"),["vec2","vec3","vec4","rgb","rgba"],t.id,"incident"),a=this.expectType(this.input(t,"normal"),["vec2","vec3","vec4","rgb","rgba"],t.id,"normal"),r=this.floatInput(t,"ior",1.5);return this.output(t,{value:{type:e.type,value:se(e.value,a.value,r)}})}case"math.derivative":{const e=this.expectNumeric(this.input(t,"value")),a=String(be(t,"mode","fwidth"));let r;return r="dFdx"===a?le(e.value):"dFdy"===a?pe(e.value):ce(e.value),this.output(t,{value:{type:e.type,value:r}})}case"layer.mixPainted":return this.output(t,{value:this.compilePaintedLayerMix(t)});case"math.dot":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b"));return Te(e.type,a.type,t.id),this.output(t,{value:{type:"float",value:A(e.value,a.value)}})}case"math.distance":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b"));return Te(e.type,a.type,t.id),this.output(t,{value:{type:"float",value:z(e.value,a.value)}})}case"math.cross":{const e=this.expectType(this.input(t,"a"),["vec3","rgb"],t.id,"a"),a=this.expectType(this.input(t,"b"),["vec3","rgb"],t.id,"b");return this.output(t,{value:{type:"vec3",value:B(e.value,a.value)}})}case"compare.greaterThan":case"compare.greaterThanOrEqual":case"compare.lessThan":case"compare.lessThanOrEqual":case"compare.equal":case"compare.notEqual":return this.output(t,{value:{type:"boolean",value:this.compileComparison(t)}});case"boolean.not":{const e=this.boolInput(t,"value",!1);return this.output(t,{value:{type:"boolean",value:ot(e,N(!1),N(!0))}})}case"boolean.and":return this.output(t,{value:{type:"boolean",value:this.compileBooleanBinary(t,"and")}});case"boolean.or":return this.output(t,{value:{type:"boolean",value:this.compileBooleanBinary(t,"or")}});case"compose.vec2":return this.output(t,{value:{type:"vec2",value:Ot(this.floatInput(t,"x",0),this.floatInput(t,"y",0))}});case"compose.vec3":return this.output(t,{value:{type:"vec3",value:Mt(this.floatInput(t,"x",0),this.floatInput(t,"y",0),this.floatInput(t,"z",0))}});case"compose.rgba":return this.output(t,{value:{type:"rgba",value:Ct(this.floatInput(t,"r",1),this.floatInput(t,"g",1),this.floatInput(t,"b",1),this.floatInput(t,"a",1))}});case"decompose.component":{const e=this.expectNumeric(this.input(t,"value")),a=String(be(t,"component","x"));return this.output(t,{value:{type:"float",value:Me(e,a,t.id)}})}case"decompose.split":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,function(t,e){const a={},r=(r,u)=>{a[r]={type:"float",value:Me(t,u,e)}};switch(t.type){case"vec2":return r("x","x"),r("y","y"),r("u","x"),r("v","y"),a;case"vec3":return r("x","x"),r("y","y"),r("z","z"),a;case"rgb":return r("r","r"),r("g","g"),r("b","b"),r("x","x"),r("y","y"),r("z","z"),a;case"vec4":return r("x","x"),r("y","y"),r("z","z"),r("w","w"),a;case"rgba":return r("r","r"),r("g","g"),r("b","b"),r("a","a"),r("x","x"),r("y","y"),r("z","z"),r("w","w"),a;case"float":return a.x={type:"float",value:t.value},a}}(e,t.id))}case"color.gradient":{const e=this.expectType(this.input(t,"t",{type:"float",value:j(.5)}),["float"],t.id,"t"),a=P(function(t){const e=be(t,"stops",[]);if(!Array.isArray(e))return[];const a=e.map((t,a)=>{if(null==t||"object"!=typeof t||Array.isArray(t))return;const r=t,u="string"==typeof r.color?r.color:"#ffffff";return{position:Ee(r.position,ze(a,e.length)),color:u,alpha:Ee(r.alpha,1)}}).filter(t=>null!=t);return a.length>0?a:[]}(t)).sample(e.value);return this.output(t,{value:{type:"rgba",value:a}})}case"color.hueShift":{const e=this.expectType(this.input(t,"color"),["rgba","rgb","vec4","vec3"],t.id,"color"),a=e.value,r="rgba"===e.type||"vec4"===e.type?a.rgb??a.xyz:a,u=this.floatInput(t,"shift",0),i=zt(r,u);return"rgba"===e.type||"vec4"===e.type?this.output(t,{value:{type:e.type,value:Ct(i,a.a??a.w)}}):this.output(t,{value:{type:e.type,value:i}})}case"color.blend":{const e=this.expectType(this.input(t,"base"),["rgba","rgb","vec4","vec3"],t.id,"base"),a=this.expectType(this.input(t,"blend"),["rgba","rgb","vec4","vec3"],t.id,"blend"),r=String(be(t,"mode","multiply")),u=e.value,i=a.value,o="rgba"===e.type||"vec4"===e.type?u.rgb??u.xyz:u,n="rgba"===a.type||"vec4"===a.type?i.rgb??i.xyz:i;let s=At(o,n,r);if("rgba"===a.type||"vec4"===a.type){const t=i.a??i.w;s=Q(o,s,t)}if("rgba"===e.type||"vec4"===e.type){const a=u.a??u.w;return this.output(t,{value:{type:e.type,value:Ct(s,a)}})}return this.output(t,{value:{type:e.type,value:s}})}case"color.desaturate":{const e=this.expectType(this.input(t,"color"),["rgba","rgb","vec4","vec3"],t.id,"color"),a=e.value,r="rgba"===e.type||"vec4"===e.type?a.rgb??a.xyz:a,u=this.floatInput(t,"fraction",1),i=kt(r,u);return"rgba"===e.type||"vec4"===e.type?this.output(t,{value:{type:e.type,value:Ct(i,a.a??a.w)}}):this.output(t,{value:{type:e.type,value:i}})}case"texture.sampler2d":{const e=this.input(t,"texture");return this.output(t,{value:this.toSampler(e,t.id)})}case"texture.sample2d":{const e=this.toSampler(this.input(t,"sampler"),t.id),a=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv"),r=e.value.sample(a.value);return this.output(t,{rgba:{type:"rgba",value:r},rgb:{type:"rgb",value:r.rgb},r:{type:"float",value:r.r},g:{type:"float",value:r.g},b:{type:"float",value:r.b},a:{type:"float",value:r.a}})}case"texture.triplanarMapping":{const e=this.input(t,"sampler"),a=this.toSampler(e,t.id),r=this.expectType(this.input(t,"scale",{type:"float",value:j(1)}),["float"],t.id,"scale"),u=this.expectType(this.input(t,"normal",{type:"vec3",value:Tt.normal}),["vec3"],t.id,"normal"),i=this.expectType(this.input(t,"position",{type:"vec3",value:Tt.position}),["vec3"],t.id,"position"),o=xt(a.value,r.value,u.value,i.value);return this.output(t,{rgba:{type:"rgba",value:o},rgb:{type:"rgb",value:o.rgb},r:{type:"float",value:o.r},g:{type:"float",value:o.g},b:{type:"float",value:o.b},a:{type:"float",value:o.a}})}case"scene.sampleColor":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:Wt}),["vec2"],t.id,"uv"),a=Jt(e.value);return this.output(t,{rgba:{type:"rgba",value:a},rgb:{type:"rgb",value:a.rgb},r:{type:"float",value:a.r},g:{type:"float",value:a.g},b:{type:"float",value:a.b},a:{type:"float",value:a.a}})}case"scene.sampleDepth":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:Wt}),["vec2"],t.id,"uv");return this.output(t,{depth:{type:"float",value:Ft(e.value)},linearEyeDepth:{type:"float",value:Rt(e.value)}})}case"scene.fragmentDepth":return this.output(t,{linearEyeDepth:{type:"float",value:Pt}});case"transform.translate":{const e=this.expectType(this.input(t,"offset",{type:"vec3",value:Mt(0,0,0)}),["vec3","rgb"],t.id,"offset");return this.output(t,{value:{type:"mat4",value:gt(e.value)}})}case"transform.scale":{const e=this.expectType(this.input(t,"scale",{type:"vec3",value:Mt(1,1,1)}),["vec3","rgb"],t.id,"scale").value;return this.output(t,{value:{type:"mat4",value:ht(e.x,e.y,e.z)}})}case"transform.rotateAxis":{const e=this.expectType(this.input(t,"axis",{type:"vec3",value:Mt(0,1,0)}),["vec3","rgb"],t.id,"axis"),a=this.expectType(this.input(t,"angle",{type:"float",value:j(0)}),["float"],t.id,"angle");return this.output(t,{value:{type:"mat4",value:ee(e.value,a.value)}})}case"uv.rotate":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"angle",{type:"float",value:j(0)}),["float"],t.id,"angle").value,r=this.expectType(this.input(t,"center",{type:"vec2",value:Ot(.5,.5)}),["vec2"],t.id,"center").value;return this.output(t,{value:{type:"vec2",value:Oe(e,a,r)}})}case"uv.twirl":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"strength",{type:"float",value:j(1)}),["float"],t.id,"strength").value,r=this.expectType(this.input(t,"center",{type:"vec2",value:Ot(.5,.5)}),["vec2"],t.id,"center").value,u=this.expectType(this.input(t,"offset",{type:"vec2",value:Ot(0,0)}),["vec2"],t.id,"offset").value;return this.output(t,{value:{type:"vec2",value:wt(e,a,r,u)}})}case"uv.radial":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=Bt(e.subtractScalar(.5));return this.output(t,{coords:{type:"vec2",value:a.coords},radius:{type:"float",value:a.radius},angle:{type:"float",value:a.angle}})}case"uv.bulge":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"center",{type:"vec2",value:Ot(.5,.5)}),["vec2"],t.id,"center").value,r=this.expectType(this.input(t,"power",{type:"float",value:j(1)}),["float"],t.id,"power").value;return this.output(t,{value:{type:"vec2",value:C(e,a,r)}})}case"uv.flipbook":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"columns",xe(t,"columns",1)),r=this.floatInput(t,"rows",xe(t,"rows",1)),u=this.floatInput(t,"fps",xe(t,"fps",60)),i=this.expectType(this.input(t,"time",{type:"float",value:mt.elapsed}),["float"],t.id,"time").value,o=String(be(t,"mode","clamp"));return this.output(t,{value:{type:"vec2",value:ae(e,a,r,i,u,o)}})}case"uv.pom":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.input(t,"heightMap"),r=this.toSampler(a,t.id).value,u=this.floatInput(t,"heightScale",.05),i=xe(t,"minLayers",8),o=xe(t,"maxLayers",24);return this.output(t,{value:{type:"vec2",value:re(e,r,u,i,o)}})}case"shape.rectangle":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value;return this.output(t,{value:{type:"float",value:Vt(e,this.floatInput(t,"width",.5),this.floatInput(t,"height",.5))}})}case"shape.roundedRectangle":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value;return this.output(t,{value:{type:"float",value:jt(e,this.floatInput(t,"width",.5),this.floatInput(t,"height",.5),this.floatInput(t,"radius",.1))}})}case"noise.simplex":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"scale",8);return this.output(t,{value:{type:"float",value:new _t(e.multiplyScalar(a))}})}case"noise.voronoi2d":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"scale",8);return this.output(t,{value:{type:"float",value:new te(e.multiplyScalar(a))}})}case"effect.fresnel":return this.output(t,{value:{type:"float",value:M(qt(this.floatInput(t,"power",1)))}});case"effect.edgeDepth":{const e=this.floatInput(t,"power",1);return this.output(t,{value:{type:"float",value:Dt(e)}})}case"effect.depthFade":{const e=this.floatInput(t,"distance",1);return this.output(t,{value:{type:"float",value:Lt(e)}})}case"util.panner":{const e=this.expectType(this.input(t,"coord",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"coord"),a=this.expectType(this.input(t,"speed",{type:"vec2",value:Ot(0,0)}),["vec2"],t.id,"speed"),r=this.expectType(this.input(t,"tile",{type:"vec2",value:Ot(1,1)}),["vec2"],t.id,"tile"),u=this.expectType(this.input(t,"time",{type:"float",value:mt.elapsed}),["float"],t.id,"time");return this.output(t,{value:{type:"vec2",value:e.value.multiply(r.value).add(a.value.multiplyScalar(u.value))}})}}}compileParameterNode(t){const e=String(be(t,"parameter","")),a=this.graph.parameters?.find(t=>t.name===e||t.id===e);if(null==a)throw new ShaderGraphCompileError(`Parameter "${e}" does not exist`,t.id);const r=ie(a.type),u={type:r,value:Ie(this.options.parameters?.[a.name]??a.defaultValue,r,a.name)};if("sampler2d"!==r)return{value:u};const i=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv"),o=u.value.sample(i.value);return{value:{type:"rgba",value:o},rgb:{type:"rgb",value:o.rgb},r:{type:"float",value:o.r},g:{type:"float",value:o.g},b:{type:"float",value:o.b},a:{type:"float",value:o.a},sampler:u}}compileBinaryMath(t){const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b")),r=t.kind.split(".")[1];if(e.type===a.type)return{type:e.type,value:Se(e.value,a.value,r,t.id)};if("float"===e.type&&"float"!==a.type&&"multiply"===r)return{type:a.type,value:Se(a.value,e.value,r,t.id)};if("float"!==e.type&&"float"===a.type)return{type:e.type,value:Se(e.value,a.value,r,t.id)};throw new ShaderGraphCompileError(`Cannot ${r} ${e.type} and ${a.type}`,t.id)}compileUnaryMath(t,e){const a=this.expectNumeric(this.input(t,"value"));return{type:a.type,value:e(a.value)}}compileBinaryFunction(t,e,a=!1){const r=this.expectNumeric(this.input(t,"a")),u=this.expectNumeric(this.input(t,"b"));return{type:a&&"float"===u.type?r.type:Te(r.type,u.type,t.id),value:e(r.value,u.value)}}compilePaintedLayerMix(t){const e=this.expectNumeric(this.input(t,"base")),a=[e.value],r=[Nt(0)];let u=e.type;for(let e=1;e<=8;e++){const i=this.optionalInput(t,`layer${e}`);if(null==i)continue;const o=this.expectNumeric(i);u=Te(u,o.type,t.id),a.push(o.value),r.push(Nt(e))}return 1===a.length?e:{type:u,value:X({layerColors:a,layerWeights:r,enableNoise:Boolean(be(t,"enableNoise",!0)),noiseScale:this.floatInput(t,"noiseScale",xe(t,"noiseScale",.1)),noiseAmount:this.floatInput(t,"noiseAmount",xe(t,"noiseAmount",.5)),decay:this.floatInput(t,"softness",xe(t,"softness",.3)),mode:"hard"===String(be(t,"mode","soft"))?R.hard:R.soft})}}defaultUV(){return"trail"===this.graph.target?Zt:"decal"===this.graph.target?Qt:M(T.uv)}input(t,e,a){const r=t.inputs?.[e];if(null!=r)return this.resolveInput(r,t.id,e);const u=(this.graph.edges??[]).find(a=>a.to.nodeId===t.id&&a.to.port===e);if(null!=u)return this.resolveSocket(u.from,t.id,e);if(null!=a)return a;throw new ShaderGraphCompileError(`Missing input "${e}"`,t.id,e)}optionalInput(t,e){const a=t.inputs?.[e];if(null!=a)return this.resolveInput(a,t.id,e);const r=(this.graph.edges??[]).find(a=>a.to.nodeId===t.id&&a.to.port===e);return null!=r?this.resolveSocket(r.from,t.id,e):void 0}floatInput(t,e,a){return this.expectType(this.input(t,e,{type:"float",value:j(a)}),["float"],t.id,e).value}boolInput(t,e,a){return this.expectType(this.input(t,e,{type:"boolean",value:N(a)}),["boolean"],t.id,e).value}compileComparison(t){const e=this.expectType(this.input(t,"a"),["float"],t.id,"a").value,a=this.expectType(this.input(t,"b"),["float"],t.id,"b").value;switch(t.kind){case"compare.greaterThan":return e.gt(a);case"compare.greaterThanOrEqual":return e.gte(a);case"compare.lessThan":return e.lt(a);case"compare.lessThanOrEqual":return e.lte(a);case"compare.equal":return e.equals(a);case"compare.notEqual":return e.notEquals(a)}throw new ShaderGraphCompileError(`Unsupported comparison node "${t.kind}"`,t.id)}compileBooleanBinary(t,e){const a=this.boolInput(t,"a",!1),r=this.boolInput(t,"b",!1);return"and"===e?a.and(r):a.or(r)}resolveOutputBinding(t,e){if(null!=t.input)return this.resolveSocket(t.input,void 0,e);if(void 0!==t.value)return we(t.value);throw new ShaderGraphCompileError(`Output "${e}" is missing an input or value`)}floatOutput(t,e){return this.expectType(this.resolveOutputBinding(t,e),["float"],e).value}resolveInput(t,e,a){return function(t){return null!=t.nodeId}(t)?this.resolveSocket(t,e,a):we(t.value,t.valueType)}resolveSocket(t,e,a){const r=this.compileNode(t.nodeId).outputs[t.port];if(null==r)throw new ShaderGraphCompileError(`Node "${t.nodeId}" does not have output "${t.port}"`,e??t.nodeId,a??t.port);return r}expectType(t,e,a,r){if(!e.includes(t.type))throw new ShaderGraphCompileError(`Expected ${e.join(" or ")} but got ${t.type}`,a,r);return t}expectNumeric(t){if(!Ce(t.type))throw new ShaderGraphCompileError(`Expected a numeric value but got ${t.type}`);return t}toSampler(t,e){if("sampler2d"===t.type)return t;if("texture2d"===t.type){const a=t.value;if(null==a)throw new ShaderGraphCompileError("Texture input is empty",e);return{type:"sampler2d",value:dt(a)}}throw new ShaderGraphCompileError(`Expected texture2d or sampler2d but got ${t.type}`,e)}toColorOutput(t){switch(t.type){case"float":case"vec2":case"vec3":case"vec4":case"rgb":case"rgba":return t.value;case"boolean":{const e=ot(t.value,j(1),j(0));return rt(Mt(e,e,e),1)}case"mat4":throw new ShaderGraphCompileError("mat4 values cannot be used as color");case"texture2d":case"sampler2d":throw new ShaderGraphCompileError(`${t.type} must be sampled before it can be used as color`)}}toVec3Output(t,e){if("vec3"===t.type||"rgb"===t.type)return t.value;if("vec4"===t.type||"rgba"===t.type)return t.value.xyz;throw new ShaderGraphCompileError(`Output "${e}" expects vec3/rgb but got ${t.type}`)}toMat4Output(t,e){if("mat4"===t.type)return t.value;throw new ShaderGraphCompileError(`Output "${e}" expects mat4 but got ${t.type}`)}output(t,e){return{node:t,outputs:e}}}export function compileShaderGraph(t,e={}){return new ShaderGraphCompiler(t,e).compile()}export function compileShaderGraphPreview(t,e,a={}){if(null==e)return compileShaderGraph(t,a).output;const r=new ShaderGraphCompiler(t,a).compileNode(e),u=Object.values(r.outputs)[0];if(null==u)throw new ShaderGraphCompileError(`Node "${e}" has no previewable output`,e);return{color:de(u),transparent:"rgba"===u.type||"vec4"===u.type}}export function buildShaderGraphMaterial(t,a={}){const r=null!=a.previewNodeId?compileShaderGraphPreview(t,a.previewNodeId,a):compileShaderGraph(t,a).output;if("sprite"===t.target)return new Et({color:r.color,discard:r.discard,transparent:r.transparent??!0,position:Ut(new f("rotation",0),new f("screenSpaceSize",0)),uniforms:{color:{value:new e(16777215)}}});if("trail"===t.target){const{position:e}=Xt.getTrailShaderNodes(a.trailBillboard??!1),u=new h({...r,position:e});return Xt.applyTrailShaderParameters(u),ye(u,t),console.log(u),u}if("decal"===t.target){const e=null!=r.discard?Kt.or(r.discard):Kt,a=new h({...r,transparent:!1,discard:e});return a.userData.isDecal=!0,ye(a,t),a}const u=new h({transparent:!1,...r});return ye(u,t),u}export function shaderGraphMaterialSideToThree(e){switch(e){case"back":return t;case"double":return a;default:return r}}function ve(t){return"decal"!==t.target&&(t.materialOptions?.transparent??"sprite"===t.target)}function ye(t,e){"surface"===e.target&&(t.side=shaderGraphMaterialSideToThree(e.materialOptions?.side)),null!=e.materialOptions?.transparent&&(t.transparent=e.materialOptions.transparent)}function de(t){switch(t.type){case"float":return me(t.value);case"vec2":{const e=t.value;return rt(Mt(e.x,e.y,0),1)}case"vec3":case"rgb":return rt(t.value,1);case"vec4":case"rgba":return t.value;case"boolean":return me(ot(t.value,j(1),j(0)));case"mat4":throw new ShaderGraphCompileError("mat4 values cannot be previewed as color");case"texture2d":case"sampler2d":throw new ShaderGraphCompileError(`${t.type} nodes require a sampled output to preview`)}}function me(t){return rt(Mt(t,t,t),1)}function fe(t){return t instanceof p?Mt(t,t,t).rgb:t instanceof g?Mt(t.x,t.y,0).rgb:t}function ge(t){return t.rgb}function be(t,e,a){const r=t.params?.[e];return void 0===r?a:r}function xe(t,e,a){const r=be(t,e,a);return"number"==typeof r?r:Number(r??a)}function we(t,e){if(null!=(a=t)&&"object"==typeof a&&!Array.isArray(a)&&"value"in a)return we(t.value,t.valueType??e);var a;const r=e??function(t){if("boolean"==typeof t)return"boolean";if("number"==typeof t)return"float";if(Array.isArray(t))return 2===t.length?"vec2":3===t.length?"vec3":16===t.length?"mat4":"vec4";return"string"==typeof t?"rgb":"float"}(t);return{type:r,value:Ie(t,r,"literal")}}function Ie(t,a,r){switch(a){case"boolean":return t instanceof l?t:N(Boolean(t));case"float":return t instanceof p?t:j(Ee(t,0));case"vec2":return t instanceof g?t:Ge(t);case"vec3":return t instanceof b?t:Be(t);case"vec4":return t instanceof x?t:function(t){const[e,a,r,u]=Ue(t,4,1);return Ct(e,a,r,u)}(t);case"mat4":return t instanceof c?t:function(t){if(t instanceof u)return H(t);const e=new u;Array.isArray(t)&&16===t.length&&e.fromArray(t.map(t=>Ee(t,0)));return H(e)}(t);case"rgb":return t instanceof v?t:function(t){if("string"==typeof t||"number"==typeof t||t instanceof e)return ut(t);const[a,r,u]=Ue(t,3);return Mt(a,r,u).rgb}(t);case"rgba":return t instanceof y||t instanceof x?t:$e(t);case"texture2d":return t;case"sampler2d":if(function(t){const e=t;return t instanceof d||t instanceof m||"function"==typeof e?.isSampler2D||!0===e?.isSampler2D}(t))return t;if(t instanceof i)return dt(t);throw new ShaderGraphCompileError(`Parameter "${r}" needs a texture value`)}}function Se(t,e,a,r){const u=`${a}Scalar`;if(e instanceof p&&"function"==typeof t[u])return t[u](e);if("function"==typeof t[a])return t[a](e);throw new ShaderGraphCompileError(`Node does not support ${a}`,r)}function Te(t,e,a){if(t===e)return t;if("rgb"===t&&"vec3"===e||"vec3"===t&&"rgb"===e)return"vec3";if("rgba"===t&&"vec4"===e||"vec4"===t&&"rgba"===e)return"vec4";if("float"===t&&Ce(e))return e;if("float"===e&&Ce(t))return t;throw new ShaderGraphCompileError(`Cannot mix ${t} and ${e}`,a)}function Oe(t,e,a){const r=t.subtract(a),u=st(e),i=G(e);return Ot(i.multiply(r.x).subtract(u.multiply(r.y)).add(a.x),u.multiply(r.x).add(i.multiply(r.y)).add(a.y))}function Me(t,e,a){const r=t.value["u"===e?"x":"v"===e?"y":e];if(r instanceof p)return r;throw new ShaderGraphCompileError(`Component "${e}" is not available on ${t.type}`,a)}function Ce(t){return"float"===t||"vec2"===t||"vec3"===t||"vec4"===t||"rgb"===t||"rgba"===t}function Ne(t){return Number.isFinite(t)?Math.min(1,Math.max(0,t)):0}function Ee(t,e){if("number"==typeof t)return t;if("string"==typeof t){const a=parseFloat(t);return Number.isFinite(a)?a:e}return"boolean"==typeof t?t?1:0:e}function Ue(t,a,r=0){if(Array.isArray(t))return Array.from({length:a},(e,a)=>Ee(t[a],r));if(t instanceof o||t instanceof n||t instanceof s)return Array.from({length:a},(e,a)=>t.toArray()[a]??r);if(t instanceof e){const e=t.toArray();return Array.from({length:a},(t,a)=>e[a]??(3===a?1:r))}if(null!=t&&"object"==typeof t){const e=t,u=["x","y","z","w"];if(u.some(t=>null!=e[t]))return Array.from({length:a},(t,a)=>Ee(e[u[a]],r));const i=["r","g","b","a"];if(i.some(t=>null!=e[t]))return Array.from({length:a},(t,a)=>Ee(e[i[a]],3===a?1:r))}return Array.from({length:a},()=>Ee(t,r))}function Ge(t){const[e,a]=Ue(t,2);return Ot(e,a)}function Be(t){const[e,a,r]=Ue(t,3);return Mt(e,a,r)}function $e(t,a=1){if("string"==typeof t||"number"==typeof t||t instanceof e)return rt(t,a);if(t instanceof b)return rt(t,a);const[r,u,i,o]=Ue(t,4,a);return Ct(r,u,i,o)}function ze(t,e){return e<=1?0:t/(e-1)}/*
|
|
1
|
+
import{BackSide as t,Color as e,DoubleSide as a,FrontSide as r,Matrix4 as u,Texture as i,Vector2 as n,Vector3 as o,Vector4 as s}from"three";import{BooleanNode as l,FloatNode as p,Mat4Node as c,NodeShaderMaterial as h,RgbNode as v,RgbaNode as y,Sampler2DNode as d,Texture2dLookupNode as m,UniformFloatNode as f,Vec2Node as g,Vec3Node as b,Vec4Node as x,abs as w,acos as T,asin as I,attributes as S,atan as O,autoVarying as M,bulge as C,bool as N,ceil as E,clamp as U,cos as G,cross as B,degrees as $,distance as k,dot as z,exp as A,exp2 as V,float as j,floor as D,fract as L,inversesqrt as q,colorGradientSampler as F,length as P,LayerMixMode as R,log as W,log2 as Y,mat4 as H,max as J,min as K,mix as Q,mixColorsByLayer as X,particleUniforms as Z,mod as _,normalize as tt,pow as et,radians as at,rgba as rt,rgb as ut,saturate as it,select as nt,sign as ot,sin as st,smoothstep as lt,sqrt as pt,standardMaterial as ct,scaleTransform as ht,step as vt,tan as yt,textureSampler2d as dt,timeUniforms as mt,toonMaterial as ft,translate as gt,transformed as bt,triplanarMapping as xt,twirl as wt,uniformFloat as Tt,uniforms as It,varyingAttributes as St,vec2 as Ot,vec3 as Mt,vec4 as Ct,getPaintedMaterialLayerWeight as Nt}from"../../shader-nodes/index.js";import{SpriteNodeShaderMaterial as Et,getSpritePosition as Ut}from"../sprite-shader.js";import{oneMinus as Gt}from"../../shader-nodes/index.js";import{vectorToRadial as Bt,remap as $t,hueShift as kt,blendColor as zt,desaturateColor as At}from"../../shader-nodes/math.js";import{rectangleFloat as Vt,roundedRectangleFloat as jt}from"../../shader-nodes/shapes.js";import{edgeDepthEffect as Dt,fresnelEffect as Lt,depthFadeEffect as qt}from"../../shader-nodes/effects.js";import{fragmentLinearEyeDepth as Ft,sampleSceneDepth as Pt,sampleSceneLinearEyeDepth as Rt,screenUV as Wt,nearUniformName as Yt,farUniformName as Ht}from"../../shader-nodes/depth.js";import{sampleSceneColor as Jt}from"../../shader-nodes/scene-sample.js";import{decalDiscard as Kt,decalUV as Qt}from"../../shader-nodes/decal.js";import{Trail as Xt,trailUV as Zt}from"../../effects/vfx/trail-renderer.js";import{SimplexNoiseNode as _t,Voronoi2d as te,rotateAxis as ee}from"../../shader-nodes/index.js";import{flipbookUv as ae}from"../../shader-nodes/texture-sequence.js";import{parallaxOcclusionMapping as re}from"../../shader-nodes/pom.js";import{defaultInlineLiteralValueForPort as ue,inlineLiteralTypeForPort as ie,SHADER_GRAPH_NODE_DEFINITIONS as ne}from"./registry.js";import{shaderGraphParameterTypeToValueType as oe}from"./parameters.js";import{varying as se,reflect as le,refract as pe,dFdx as ce,dFdy as he,fwidth as ve}from"three-shader-graph";import{decalNormal as ye}from"../../shader-nodes/decal.js";export class ShaderGraphCompileError extends Error{constructor(t,e,a){super(t),this.nodeId=e,this.port=a,this.name="ShaderGraphCompileError"}}export class ShaderGraphCompiler{constructor(t,e={}){this.graph=t,this.options=e,this.compiled=new Map,this.nodesById=new Map((t.nodes??[]).map(t=>[t.id,t]))}validate(){this.compile()}compile(){if(1!==this.graph.version)throw new ShaderGraphCompileError(`Unsupported shader graph version ${this.graph.version}`);return this.validateEdges(),{output:this.compileOutput(),nodes:this.compiled}}validateEdges(){for(const t of this.graph.edges??[]){if(!this.nodesById.has(t.from.nodeId))throw new ShaderGraphCompileError(`Edge references missing source node "${t.from.nodeId}"`,t.from.nodeId,t.from.port);if(!this.nodesById.has(t.to.nodeId))throw new ShaderGraphCompileError(`Edge references missing target node "${t.to.nodeId}"`,t.to.nodeId,t.to.port)}}compileOutput(){const t=this.graph.outputs?.color,e={color:null!=t?this.toColorOutput(this.resolveOutputBinding(t,"color")):rt("#ffffff",1),transparent:de(this.graph)},a=this.graph.outputs?.opacity;null!=a&&(e.opacity=this.expectType(this.resolveOutputBinding(a,"opacity"),["float"],"opacity").value);const r=this.graph.outputs?.roughness;null!=r&&(e.roughness=this.expectType(this.resolveOutputBinding(r,"roughness"),["float"],"roughness").value);const u=this.graph.outputs?.metalness;null!=u&&(e.metalness=this.floatOutput(u,"metalness"));const i=this.graph.outputs?.normal;null!=i&&(e.normal=this.toVec3Output(this.resolveOutputBinding(i,"normal"),"normal"));const n=this.graph.outputs?.emissive;null!=n&&(e.emissive=this.toVec3Output(this.resolveOutputBinding(n,"emissive"),"emissive"));const o=this.graph.outputs?.ambientOcclusion;null!=o&&(e.ambientOcclusion=this.floatOutput(o,"ambientOcclusion"));const s=this.graph.outputs?.ambientOcclusionIntensity;null!=s&&(e.ambientOcclusionIntensity=this.floatOutput(s,"ambientOcclusionIntensity"));const l=this.graph.outputs?.sheenColor;null!=l&&(e.sheenColor=this.toVec3Output(this.resolveOutputBinding(l,"sheenColor"),"sheenColor"));const p=this.graph.outputs?.sheenRoughness;null!=p&&(e.sheenRoughness=this.floatOutput(p,"sheenRoughness"));const c=this.graph.outputs?.anisotropy;null!=c&&(e.anisotropy=this.floatOutput(c,"anisotropy"));const h=this.graph.outputs?.anisotropyDirection;null!=h&&(e.anisotropyDirection=this.expectType(this.resolveOutputBinding(h,"anisotropyDirection"),["vec2"],"anisotropyDirection").value);const v=this.graph.outputs?.bakedLight;null!=v&&(e.bakedLight=this.toVec3Output(this.resolveOutputBinding(v,"bakedLight"),"bakedLight"));const y=this.graph.outputs?.transform;null!=y&&"decal"!==this.graph.target&&(e.transform=this.toMat4Output(this.resolveOutputBinding(y,"transform"),"transform"));const d=this.graph.outputs?.discard;null!=d&&(e.discard=this.expectType(this.resolveOutputBinding(d,"discard"),["boolean"],"discard").value);const m=this.graph.outputs?.transparent;null!=m&&null!=m.value&&(e.transparent=Boolean(m.value));const f=this.graph.outputs?.alphaTest;return null!=f&&null!=f.value&&(e.alphaTest=Number(f.value)),this.applyShadingModel(e)}applyShadingModel(t){const e=null!=t.opacity?function(t,e){if(t instanceof p)return rt(Mt(t,t,t),e);if(t instanceof g)return rt(Mt(t.x,t.y,0),e);if(t instanceof x)return rt(t.rgb,t.w.multiply(e));return rt(t,e)}(t.color,t.opacity):t.color;switch(this.graph.shadingModel??"standard"){case"standard":{const a={color:be(e),roughness:t.roughness??j(.5),...null!=t.metalness?{metalness:t.metalness}:{},..."decal"===this.graph.target?{normal:tt(se(It.normalMatrix).multiplyVec(ye))}:{},...null!=t.normal?{normal:t.normal}:{},...null!=t.emissive?{emissive:xe(t.emissive)}:{},...null!=t.ambientOcclusion?{ambientOcclusion:t.ambientOcclusion}:{},...null!=t.ambientOcclusionIntensity?{ambientOcclusionIntensity:t.ambientOcclusionIntensity}:{},...null!=t.sheenColor?{sheenColor:t.sheenColor.rgb}:{},...null!=t.sheenRoughness?{sheenRoughness:t.sheenRoughness}:{},...null!=t.anisotropy?{anisotropy:t.anisotropy}:{},...null!=t.anisotropyDirection?{anisotropyDirection:t.anisotropyDirection}:{},...null!=t.bakedLight?{bakedLight:t.bakedLight}:{}};return{...t,color:ct(a)}}case"toon":{const a={color:be(e),...null!=t.normal?{normal:t.normal}:{},...null!=t.emissive?{emissive:xe(t.emissive)}:{},...null!=t.ambientOcclusion?{ambientOcclusion:t.ambientOcclusion}:{},...null!=t.ambientOcclusionIntensity?{ambientOcclusionIntensity:t.ambientOcclusionIntensity}:{},...null!=t.bakedLight?{bakedLight:t.bakedLight}:{}};return{...t,color:ft(a)}}case"unlit":return{...t,color:e}}}compileNode(t){const e=this.compiled.get(t);if(null!=e)return e;const a=this.nodesById.get(t);if(null==a)throw new ShaderGraphCompileError(`Missing shader graph node "${t}"`,t);if(null==ne[a.kind])throw new ShaderGraphCompileError(`Unsupported shader graph node "${a.kind}"`,a.id);const r=this.compileNodeInternal(a);return this.compiled.set(t,r),r}compileNodeInternal(t){switch(t.kind){case"input.parameter":return this.output(t,this.compileParameterNode(t));case"input.slider":return this.output(t,{value:{type:"float",value:j(Ue(Te(t,"value",.5)))}});case"constant.boolean":return this.output(t,{value:{type:"boolean",value:N(Boolean(we(t,"value",!1)))}});case"constant.float":return this.output(t,{value:{type:"float",value:j(Te(t,"value",0))}});case"constant.vec2":return this.output(t,{value:{type:"vec2",value:$e(we(t,"value",[0,0]))}});case"constant.vec3":return this.output(t,{value:{type:"vec3",value:ke(we(t,"value",[0,0,0]))}});case"constant.rgba":return this.output(t,{value:{type:"rgba",value:ze(we(t,"value","#ffffff"),Te(t,"alpha",1))}});case"builtin.uv":{const e=this.defaultUV();return this.output(t,{value:{type:"vec2",value:!0===we(t,"flipY",!1)?Ot(e.x,Gt(e.y)):e},u:{type:"float",value:e.x},v:{type:"float",value:e.y}})}case"builtin.screenUv":return this.output(t,{value:{type:"vec2",value:Wt}});case"builtin.color":{const e=M(S.color);return this.output(t,{value:{type:"rgba",value:e},rgb:{type:"rgb",value:e.rgb},r:{type:"float",value:e.r},g:{type:"float",value:e.g},b:{type:"float",value:e.b},a:{type:"float",value:e.a}})}case"builtin.position":{const e=M(S.position);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.worldPosition":{const e=M(bt.worldPosition);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.viewDir":{const e=M(bt.viewDir);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.normal":{const e=M(S.normal);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.time":return this.output(t,{value:{type:"float",value:mt.elapsed}});case"builtin.camera":{const e=Tt(Yt),a=Tt(Ht),r=It.cameraPosition;return this.output(t,{position:{type:"vec3",value:r},x:{type:"float",value:r.x},y:{type:"float",value:r.y},z:{type:"float",value:r.z},near:{type:"float",value:e},far:{type:"float",value:a}})}case"builtin.particle":return this.output(t,{energy:{type:"float",value:Z.energy},color:{type:"rgb",value:Z.color},opacity:{type:"float",value:Z.opacity},time:{type:"float",value:Z.time}});case"math.add":case"math.subtract":case"math.multiply":case"math.divide":return this.output(t,{value:this.compileBinaryMath(t)});case"math.oneMinus":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:e.type,value:Gt(e.value)}})}case"math.abs":return this.output(t,{value:this.compileUnaryMath(t,w)});case"math.sign":return this.output(t,{value:this.compileUnaryMath(t,ot)});case"math.floor":return this.output(t,{value:this.compileUnaryMath(t,D)});case"math.ceil":return this.output(t,{value:this.compileUnaryMath(t,E)});case"math.fract":return this.output(t,{value:this.compileUnaryMath(t,L)});case"math.sin":return this.output(t,{value:this.compileUnaryMath(t,st)});case"math.cos":return this.output(t,{value:this.compileUnaryMath(t,G)});case"math.tan":return this.output(t,{value:this.compileUnaryMath(t,yt)});case"math.asin":return this.output(t,{value:this.compileUnaryMath(t,I)});case"math.acos":return this.output(t,{value:this.compileUnaryMath(t,T)});case"math.atan":return this.output(t,{value:this.compileUnaryMath(t,O)});case"math.radians":return this.output(t,{value:this.compileUnaryMath(t,at)});case"math.degrees":return this.output(t,{value:this.compileUnaryMath(t,$)});case"math.sqrt":return this.output(t,{value:this.compileUnaryMath(t,pt)});case"math.inverseSqrt":return this.output(t,{value:this.compileUnaryMath(t,q)});case"math.exp":return this.output(t,{value:this.compileUnaryMath(t,A)});case"math.exp2":return this.output(t,{value:this.compileUnaryMath(t,V)});case"math.log":return this.output(t,{value:this.compileUnaryMath(t,W)});case"math.log2":return this.output(t,{value:this.compileUnaryMath(t,Y)});case"math.saturate":return this.output(t,{value:this.compileUnaryMath(t,it)});case"math.length":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:"float",value:P(e.value)}})}case"math.normalize":return this.output(t,{value:this.compileUnaryMath(t,tt)});case"math.clamp":{const e=this.expectNumeric(this.input(t,"value")),a=this.expectNumeric(this.input(t,"min",{type:"float",value:j(0)})),r=this.expectNumeric(this.input(t,"max",{type:"float",value:j(1)}));return this.output(t,{value:{type:e.type,value:U(e.value,a.value,r.value)}})}case"math.min":return this.output(t,{value:this.compileBinaryFunction(t,K)});case"math.max":return this.output(t,{value:this.compileBinaryFunction(t,J)});case"math.pow":return this.output(t,{value:this.compileBinaryFunction(t,et)});case"math.mod":return this.output(t,{value:this.compileBinaryFunction(t,_)});case"math.step":return this.output(t,{value:this.compileBinaryFunction(t,vt,!0)});case"math.smoothstep":{const e=this.expectNumeric(this.input(t,"edge0",{type:"float",value:j(0)})),a=this.expectNumeric(this.input(t,"edge1",{type:"float",value:j(1)})),r=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:r.type,value:lt(e.value,a.value,r.value)}})}case"math.mix":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b")),r=this.expectNumeric(this.input(t,"t",{type:"float",value:j(.5)})),u=Me(e.type,a.type,t.id);return this.output(t,{value:{type:u,value:Q(e.value,a.value,r.value)}})}case"math.remap":{const e=this.expectType(this.input(t,"value"),["float"],t.id,"value").value,a=this.floatInput(t,"inMin",-1),r=this.floatInput(t,"inMax",1),u=this.floatInput(t,"outMin",0),i=this.floatInput(t,"outMax",1);return this.output(t,{value:{type:"float",value:$t(e,a,r,u,i)}})}case"math.select":{const e=this.boolInput(t,"condition",!1),a=this.expectNumeric(this.input(t,"a")),r=this.expectNumeric(this.input(t,"b")),u=Me(a.type,r.type,t.id);return this.output(t,{value:{type:u,value:nt(e,a.value,r.value)}})}case"math.reflect":{const e=this.expectType(this.input(t,"incident"),["vec2","vec3","vec4","rgb","rgba"],t.id,"incident"),a=this.expectType(this.input(t,"normal"),["vec2","vec3","vec4","rgb","rgba"],t.id,"normal");return this.output(t,{value:{type:e.type,value:le(e.value,a.value)}})}case"math.refract":{const e=this.expectType(this.input(t,"incident"),["vec2","vec3","vec4","rgb","rgba"],t.id,"incident"),a=this.expectType(this.input(t,"normal"),["vec2","vec3","vec4","rgb","rgba"],t.id,"normal"),r=this.floatInput(t,"ior",1.5);return this.output(t,{value:{type:e.type,value:pe(e.value,a.value,r)}})}case"math.derivative":{const e=this.expectNumeric(this.input(t,"value")),a=String(we(t,"mode","fwidth"));let r;return r="dFdx"===a?ce(e.value):"dFdy"===a?he(e.value):ve(e.value),this.output(t,{value:{type:e.type,value:r}})}case"layer.mixPainted":return this.output(t,{value:this.compilePaintedLayerMix(t)});case"math.dot":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b"));return Me(e.type,a.type,t.id),this.output(t,{value:{type:"float",value:z(e.value,a.value)}})}case"math.distance":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b"));return Me(e.type,a.type,t.id),this.output(t,{value:{type:"float",value:k(e.value,a.value)}})}case"math.cross":{const e=this.expectType(this.input(t,"a"),["vec3","rgb"],t.id,"a"),a=this.expectType(this.input(t,"b"),["vec3","rgb"],t.id,"b");return this.output(t,{value:{type:"vec3",value:B(e.value,a.value)}})}case"compare.greaterThan":case"compare.greaterThanOrEqual":case"compare.lessThan":case"compare.lessThanOrEqual":case"compare.equal":case"compare.notEqual":return this.output(t,{value:{type:"boolean",value:this.compileComparison(t)}});case"boolean.not":{const e=this.boolInput(t,"value",!1);return this.output(t,{value:{type:"boolean",value:nt(e,N(!1),N(!0))}})}case"boolean.and":return this.output(t,{value:{type:"boolean",value:this.compileBooleanBinary(t,"and")}});case"boolean.or":return this.output(t,{value:{type:"boolean",value:this.compileBooleanBinary(t,"or")}});case"compose.vec2":return this.output(t,{value:{type:"vec2",value:Ot(this.floatInput(t,"x",0),this.floatInput(t,"y",0))}});case"compose.vec3":return this.output(t,{value:{type:"vec3",value:Mt(this.floatInput(t,"x",0),this.floatInput(t,"y",0),this.floatInput(t,"z",0))}});case"compose.rgba":return this.output(t,{value:{type:"rgba",value:Ct(this.floatInput(t,"r",1),this.floatInput(t,"g",1),this.floatInput(t,"b",1),this.floatInput(t,"a",1))}});case"decompose.component":{const e=this.expectNumeric(this.input(t,"value")),a=String(we(t,"component","x"));return this.output(t,{value:{type:"float",value:Ne(e,a,t.id)}})}case"decompose.split":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,function(t,e){const a={},r=(r,u)=>{a[r]={type:"float",value:Ne(t,u,e)}};switch(t.type){case"vec2":return r("x","x"),r("y","y"),r("u","x"),r("v","y"),a;case"vec3":return r("x","x"),r("y","y"),r("z","z"),a;case"rgb":return r("r","r"),r("g","g"),r("b","b"),r("x","x"),r("y","y"),r("z","z"),a;case"vec4":return r("x","x"),r("y","y"),r("z","z"),r("w","w"),a;case"rgba":return r("r","r"),r("g","g"),r("b","b"),r("a","a"),r("x","x"),r("y","y"),r("z","z"),r("w","w"),a;case"float":return a.x={type:"float",value:t.value},a}}(e,t.id))}case"color.gradient":{const e=this.expectType(this.input(t,"t",{type:"float",value:j(.5)}),["float"],t.id,"t"),a=F(function(t){const e=we(t,"stops",[]);if(!Array.isArray(e))return[];const a=e.map((t,a)=>{if(null==t||"object"!=typeof t||Array.isArray(t))return;const r=t,u="string"==typeof r.color?r.color:"#ffffff";return{position:Ge(r.position,Ae(a,e.length)),color:u,alpha:Ge(r.alpha,1)}}).filter(t=>null!=t);return a.length>0?a:[]}(t)).sample(e.value);return this.output(t,{value:{type:"rgba",value:a}})}case"color.hueShift":{const e=this.expectType(this.input(t,"color"),["rgba","rgb","vec4","vec3"],t.id,"color"),a=e.value,r="rgba"===e.type||"vec4"===e.type?a.rgb??a.xyz:a,u=this.floatInput(t,"shift",0),i=kt(r,u);return"rgba"===e.type||"vec4"===e.type?this.output(t,{value:{type:e.type,value:Ct(i,a.a??a.w)}}):this.output(t,{value:{type:e.type,value:i}})}case"color.blend":{const e=this.expectType(this.input(t,"base"),["rgba","rgb","vec4","vec3"],t.id,"base"),a=this.expectType(this.input(t,"blend"),["rgba","rgb","vec4","vec3"],t.id,"blend"),r=String(we(t,"mode","multiply")),u=e.value,i=a.value,n="rgba"===e.type||"vec4"===e.type?u.rgb??u.xyz:u,o="rgba"===a.type||"vec4"===a.type?i.rgb??i.xyz:i;let s=zt(n,o,r);if("rgba"===a.type||"vec4"===a.type){const t=i.a??i.w;s=Q(n,s,t)}if("rgba"===e.type||"vec4"===e.type){const a=u.a??u.w;return this.output(t,{value:{type:e.type,value:Ct(s,a)}})}return this.output(t,{value:{type:e.type,value:s}})}case"color.desaturate":{const e=this.expectType(this.input(t,"color"),["rgba","rgb","vec4","vec3"],t.id,"color"),a=e.value,r="rgba"===e.type||"vec4"===e.type?a.rgb??a.xyz:a,u=this.floatInput(t,"fraction",1),i=At(r,u);return"rgba"===e.type||"vec4"===e.type?this.output(t,{value:{type:e.type,value:Ct(i,a.a??a.w)}}):this.output(t,{value:{type:e.type,value:i}})}case"texture.sampler2d":{const e=this.input(t,"texture");return this.output(t,{value:this.toSampler(e,t.id)})}case"texture.sample2d":{const e=this.toSampler(this.input(t,"sampler"),t.id),a=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv"),r=e.value.sample(a.value);return this.output(t,{rgba:{type:"rgba",value:r},rgb:{type:"rgb",value:r.rgb},r:{type:"float",value:r.r},g:{type:"float",value:r.g},b:{type:"float",value:r.b},a:{type:"float",value:r.a}})}case"texture.triplanarMapping":{const e=this.input(t,"sampler"),a=this.toSampler(e,t.id),r=this.expectType(this.input(t,"scale",{type:"float",value:j(1)}),["float"],t.id,"scale"),u=this.expectType(this.input(t,"normal",{type:"vec3",value:St.normal}),["vec3"],t.id,"normal"),i=this.expectType(this.input(t,"position",{type:"vec3",value:St.position}),["vec3"],t.id,"position"),n=xt(a.value,r.value,u.value,i.value);return this.output(t,{rgba:{type:"rgba",value:n},rgb:{type:"rgb",value:n.rgb},r:{type:"float",value:n.r},g:{type:"float",value:n.g},b:{type:"float",value:n.b},a:{type:"float",value:n.a}})}case"scene.sampleColor":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:Wt}),["vec2"],t.id,"uv"),a=Jt(e.value);return this.output(t,{rgba:{type:"rgba",value:a},rgb:{type:"rgb",value:a.rgb},r:{type:"float",value:a.r},g:{type:"float",value:a.g},b:{type:"float",value:a.b},a:{type:"float",value:a.a}})}case"scene.sampleDepth":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:Wt}),["vec2"],t.id,"uv");return this.output(t,{depth:{type:"float",value:Pt(e.value)},linearEyeDepth:{type:"float",value:Rt(e.value)}})}case"scene.fragmentDepth":return this.output(t,{linearEyeDepth:{type:"float",value:Ft}});case"transform.translate":{const e=this.expectType(this.input(t,"offset",{type:"vec3",value:Mt(0,0,0)}),["vec3","rgb"],t.id,"offset");return this.output(t,{value:{type:"mat4",value:gt(e.value)}})}case"transform.scale":{const e=this.expectType(this.input(t,"scale",{type:"vec3",value:Mt(1,1,1)}),["vec3","rgb"],t.id,"scale").value;return this.output(t,{value:{type:"mat4",value:ht(e.x,e.y,e.z)}})}case"transform.rotateAxis":{const e=this.expectType(this.input(t,"axis",{type:"vec3",value:Mt(0,1,0)}),["vec3","rgb"],t.id,"axis"),a=this.expectType(this.input(t,"angle",{type:"float",value:j(0)}),["float"],t.id,"angle");return this.output(t,{value:{type:"mat4",value:ee(e.value,a.value)}})}case"uv.rotate":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"angle",{type:"float",value:j(0)}),["float"],t.id,"angle").value,r=this.expectType(this.input(t,"center",{type:"vec2",value:Ot(.5,.5)}),["vec2"],t.id,"center").value;return this.output(t,{value:{type:"vec2",value:Ce(e,a,r)}})}case"uv.twirl":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"strength",{type:"float",value:j(1)}),["float"],t.id,"strength").value,r=this.expectType(this.input(t,"center",{type:"vec2",value:Ot(.5,.5)}),["vec2"],t.id,"center").value,u=this.expectType(this.input(t,"offset",{type:"vec2",value:Ot(0,0)}),["vec2"],t.id,"offset").value;return this.output(t,{value:{type:"vec2",value:wt(e,a,r,u)}})}case"uv.radial":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=Bt(e.subtractScalar(.5));return this.output(t,{coords:{type:"vec2",value:a.coords},radius:{type:"float",value:a.radius},angle:{type:"float",value:a.angle}})}case"uv.bulge":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"center",{type:"vec2",value:Ot(.5,.5)}),["vec2"],t.id,"center").value,r=this.expectType(this.input(t,"power",{type:"float",value:j(1)}),["float"],t.id,"power").value;return this.output(t,{value:{type:"vec2",value:C(e,a,r)}})}case"uv.flipbook":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"columns",Te(t,"columns",1)),r=this.floatInput(t,"rows",Te(t,"rows",1)),u=this.floatInput(t,"fps",Te(t,"fps",60)),i=this.expectType(this.input(t,"time",{type:"float",value:mt.elapsed}),["float"],t.id,"time").value,n=String(we(t,"mode","clamp"));return this.output(t,{value:{type:"vec2",value:ae(e,a,r,i,u,n)}})}case"uv.pom":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.input(t,"heightMap"),r=this.toSampler(a,t.id).value,u=this.floatInput(t,"heightScale",.05),i=Te(t,"minLayers",8),n=Te(t,"maxLayers",24);return this.output(t,{value:{type:"vec2",value:re(e,r,u,i,n)}})}case"shape.rectangle":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value;return this.output(t,{value:{type:"float",value:Vt(e,this.floatInput(t,"width",.5),this.floatInput(t,"height",.5))}})}case"shape.roundedRectangle":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value;return this.output(t,{value:{type:"float",value:jt(e,this.floatInput(t,"width",.5),this.floatInput(t,"height",.5),this.floatInput(t,"radius",.1))}})}case"noise.simplex":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"scale",8);return this.output(t,{value:{type:"float",value:new _t(e.multiplyScalar(a))}})}case"noise.voronoi2d":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"scale",8);return this.output(t,{value:{type:"float",value:new te(e.multiplyScalar(a))}})}case"effect.fresnel":return this.output(t,{value:{type:"float",value:M(Lt(this.floatInput(t,"power",1)))}});case"effect.edgeDepth":{const e=this.floatInput(t,"power",1);return this.output(t,{value:{type:"float",value:Dt(e)}})}case"effect.depthFade":{const e=this.floatInput(t,"distance",1);return this.output(t,{value:{type:"float",value:qt(e)}})}case"util.panner":{const e=this.expectType(this.input(t,"coord",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"coord"),a=this.expectType(this.input(t,"speed",{type:"vec2",value:Ot(0,0)}),["vec2"],t.id,"speed"),r=this.expectType(this.input(t,"tile",{type:"vec2",value:Ot(1,1)}),["vec2"],t.id,"tile"),u=this.expectType(this.input(t,"time",{type:"float",value:mt.elapsed}),["float"],t.id,"time");return this.output(t,{value:{type:"vec2",value:e.value.multiply(r.value).add(a.value.multiplyScalar(u.value))}})}}}compileParameterNode(t){const e=String(we(t,"parameter","")),a=this.graph.parameters?.find(t=>t.name===e||t.id===e);if(null==a)throw new ShaderGraphCompileError(`Parameter "${e}" does not exist`,t.id);const r=oe(a.type),u={type:r,value:Se(this.options.parameters?.[a.name]??a.defaultValue,r,a.name)};if("sampler2d"!==r)return{value:u};const i=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv"),n=u.value.sample(i.value);return{value:{type:"rgba",value:n},rgb:{type:"rgb",value:n.rgb},r:{type:"float",value:n.r},g:{type:"float",value:n.g},b:{type:"float",value:n.b},a:{type:"float",value:n.a},sampler:u}}compileBinaryMath(t){const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b")),r=t.kind.split(".")[1];if(e.type===a.type)return{type:e.type,value:Oe(e.value,a.value,r,t.id)};if("float"===e.type&&"float"!==a.type&&"multiply"===r)return{type:a.type,value:Oe(a.value,e.value,r,t.id)};if("float"!==e.type&&"float"===a.type)return{type:e.type,value:Oe(e.value,a.value,r,t.id)};throw new ShaderGraphCompileError(`Cannot ${r} ${e.type} and ${a.type}`,t.id)}compileUnaryMath(t,e){const a=this.expectNumeric(this.input(t,"value"));return{type:a.type,value:e(a.value)}}compileBinaryFunction(t,e,a=!1){const r=this.expectNumeric(this.input(t,"a")),u=this.expectNumeric(this.input(t,"b"));return{type:a&&"float"===u.type?r.type:Me(r.type,u.type,t.id),value:e(r.value,u.value)}}compilePaintedLayerMix(t){const e=this.expectNumeric(this.input(t,"base")),a=[e.value],r=[Nt(0)];let u=e.type;for(let e=1;e<=8;e++){const i=this.optionalInput(t,`layer${e}`);if(null==i)continue;const n=this.expectNumeric(i);u=Me(u,n.type,t.id),a.push(n.value),r.push(Nt(e))}return 1===a.length?e:{type:u,value:X({layerColors:a,layerWeights:r,enableNoise:Boolean(we(t,"enableNoise",!0)),noiseScale:this.floatInput(t,"noiseScale",Te(t,"noiseScale",.1)),noiseAmount:this.floatInput(t,"noiseAmount",Te(t,"noiseAmount",.5)),decay:this.floatInput(t,"softness",Te(t,"softness",.3)),mode:"hard"===String(we(t,"mode","soft"))?R.hard:R.soft})}}defaultUV(){return"trail"===this.graph.target?Zt:"decal"===this.graph.target?Qt:M(S.uv)}input(t,e,a){const r=t.inputs?.[e];if(null!=r)return this.resolveInput(r,t.id,e);const u=(this.graph.edges??[]).find(a=>a.to.nodeId===t.id&&a.to.port===e);if(null!=u)return this.resolveSocket(u.from,t.id,e);if(null!=a)return a;const i=this.inlineLiteralFallback(t,e);if(null!=i)return i;throw new ShaderGraphCompileError(`Missing input "${e}"`,t.id,e)}optionalInput(t,e){const a=t.inputs?.[e];if(null!=a)return this.resolveInput(a,t.id,e);const r=(this.graph.edges??[]).find(a=>a.to.nodeId===t.id&&a.to.port===e);return null!=r?this.resolveSocket(r.from,t.id,e):void 0}floatInput(t,e,a){return this.expectType(this.input(t,e,{type:"float",value:j(a)}),["float"],t.id,e).value}boolInput(t,e,a){return this.expectType(this.input(t,e,{type:"boolean",value:N(a)}),["boolean"],t.id,e).value}compileComparison(t){const e=this.expectType(this.input(t,"a"),["float"],t.id,"a").value,a=this.expectType(this.input(t,"b"),["float"],t.id,"b").value;switch(t.kind){case"compare.greaterThan":return e.gt(a);case"compare.greaterThanOrEqual":return e.gte(a);case"compare.lessThan":return e.lt(a);case"compare.lessThanOrEqual":return e.lte(a);case"compare.equal":return e.equals(a);case"compare.notEqual":return e.notEquals(a)}throw new ShaderGraphCompileError(`Unsupported comparison node "${t.kind}"`,t.id)}compileBooleanBinary(t,e){const a=this.boolInput(t,"a",!1),r=this.boolInput(t,"b",!1);return"and"===e?a.and(r):a.or(r)}resolveOutputBinding(t,e){if(null!=t.input)return this.resolveSocket(t.input,void 0,e);if(void 0!==t.value)return Ie(t.value);throw new ShaderGraphCompileError(`Output "${e}" is missing an input or value`)}floatOutput(t,e){return this.expectType(this.resolveOutputBinding(t,e),["float"],e).value}resolveInput(t,e,a){return function(t){return null!=t.nodeId}(t)?this.resolveSocket(t,e,a):Ie(t.value,t.valueType)}inlineLiteralFallback(t,e){const a=ne[t.kind]?.inputs.find(t=>t.name===e);if(null==a)return;const r=ie(t.kind,a),u=ue(t.kind,a);return null!=r&&void 0!==u?Ie(u,r):void 0}resolveSocket(t,e,a){const r=this.compileNode(t.nodeId).outputs[t.port];if(null==r)throw new ShaderGraphCompileError(`Node "${t.nodeId}" does not have output "${t.port}"`,e??t.nodeId,a??t.port);return r}expectType(t,e,a,r){if(!e.includes(t.type))throw new ShaderGraphCompileError(`Expected ${e.join(" or ")} but got ${t.type}`,a,r);return t}expectNumeric(t){if(!Ee(t.type))throw new ShaderGraphCompileError(`Expected a numeric value but got ${t.type}`);return t}toSampler(t,e){if("sampler2d"===t.type)return t;if("texture2d"===t.type){const a=t.value;if(null==a)throw new ShaderGraphCompileError("Texture input is empty",e);return{type:"sampler2d",value:dt(a)}}throw new ShaderGraphCompileError(`Expected texture2d or sampler2d but got ${t.type}`,e)}toColorOutput(t){switch(t.type){case"float":case"vec2":case"vec3":case"vec4":case"rgb":case"rgba":return t.value;case"boolean":{const e=nt(t.value,j(1),j(0));return rt(Mt(e,e,e),1)}case"mat4":throw new ShaderGraphCompileError("mat4 values cannot be used as color");case"texture2d":case"sampler2d":throw new ShaderGraphCompileError(`${t.type} must be sampled before it can be used as color`)}}toVec3Output(t,e){if("vec3"===t.type||"rgb"===t.type)return t.value;if("vec4"===t.type||"rgba"===t.type)return t.value.xyz;throw new ShaderGraphCompileError(`Output "${e}" expects vec3/rgb but got ${t.type}`)}toMat4Output(t,e){if("mat4"===t.type)return t.value;throw new ShaderGraphCompileError(`Output "${e}" expects mat4 but got ${t.type}`)}output(t,e){return{node:t,outputs:e}}}export function compileShaderGraph(t,e={}){return new ShaderGraphCompiler(t,e).compile()}export function compileShaderGraphPreview(t,e,a={}){if(null==e)return compileShaderGraph(t,a).output;const r=new ShaderGraphCompiler(t,a).compileNode(e),u=Object.values(r.outputs)[0];if(null==u)throw new ShaderGraphCompileError(`Node "${e}" has no previewable output`,e);return{color:fe(u),transparent:"rgba"===u.type||"vec4"===u.type}}export function buildShaderGraphMaterial(t,a={}){const r=null!=a.previewNodeId?compileShaderGraphPreview(t,a.previewNodeId,a):compileShaderGraph(t,a).output;if("sprite"===t.target)return new Et({color:r.color,discard:r.discard,transparent:r.transparent??!0,position:Ut(new f("rotation",0),new f("screenSpaceSize",0)),uniforms:{color:{value:new e(16777215)}}});if("trail"===t.target){const{position:e}=Xt.getTrailShaderNodes(a.trailBillboard??!1),u=new h({...r,position:e});return Xt.applyTrailShaderParameters(u),me(u,t),u}if("decal"===t.target){const e=null!=r.discard?Kt.or(r.discard):Kt,a=new h({...r,transparent:!1,discard:e});return a.userData.isDecal=!0,me(a,t),a}const u=new h({transparent:!1,...r});return me(u,t),u}export function shaderGraphMaterialSideToThree(e){switch(e){case"back":return t;case"double":return a;default:return r}}function de(t){return"decal"!==t.target&&(t.materialOptions?.transparent??"sprite"===t.target)}function me(t,e){"surface"===e.target&&(t.side=shaderGraphMaterialSideToThree(e.materialOptions?.side)),null!=e.materialOptions?.transparent&&(t.transparent=e.materialOptions.transparent),null!=e.materialOptions?.alphaTest&&0===t.alphaTest&&(t.alphaTest=e.materialOptions.alphaTest),null!=e.materialOptions?.bloom&&(t.userData.hasBloom=e.materialOptions.bloom)}function fe(t){switch(t.type){case"float":return ge(t.value);case"vec2":{const e=t.value;return rt(Mt(e.x,e.y,0),1)}case"vec3":case"rgb":return rt(t.value,1);case"vec4":case"rgba":return t.value;case"boolean":return ge(nt(t.value,j(1),j(0)));case"mat4":throw new ShaderGraphCompileError("mat4 values cannot be previewed as color");case"texture2d":case"sampler2d":throw new ShaderGraphCompileError(`${t.type} nodes require a sampled output to preview`)}}function ge(t){return rt(Mt(t,t,t),1)}function be(t){return t instanceof p?Mt(t,t,t).rgb:t instanceof g?Mt(t.x,t.y,0).rgb:t}function xe(t){return t.rgb}function we(t,e,a){const r=t.params?.[e];return void 0===r?a:r}function Te(t,e,a){const r=we(t,e,a);return"number"==typeof r?r:Number(r??a)}function Ie(t,e){if(null!=(a=t)&&"object"==typeof a&&!Array.isArray(a)&&"value"in a)return Ie(t.value,t.valueType??e);var a;const r=e??function(t){if("boolean"==typeof t)return"boolean";if("number"==typeof t)return"float";if(Array.isArray(t))return 2===t.length?"vec2":3===t.length?"vec3":16===t.length?"mat4":"vec4";return"string"==typeof t?"rgb":"float"}(t);return{type:r,value:Se(t,r,"literal")}}function Se(t,a,r){switch(a){case"boolean":return t instanceof l?t:N(Boolean(t));case"float":return t instanceof p?t:j(Ge(t,0));case"vec2":return t instanceof g?t:$e(t);case"vec3":return t instanceof b?t:ke(t);case"vec4":return t instanceof x?t:function(t){const[e,a,r,u]=Be(t,4,1);return Ct(e,a,r,u)}(t);case"mat4":return t instanceof c?t:function(t){if(t instanceof u)return H(t);const e=new u;Array.isArray(t)&&16===t.length&&e.fromArray(t.map(t=>Ge(t,0)));return H(e)}(t);case"rgb":return t instanceof v?t:function(t){if("string"==typeof t||"number"==typeof t||t instanceof e)return ut(t);const[a,r,u]=Be(t,3);return Mt(a,r,u).rgb}(t);case"rgba":return t instanceof y||t instanceof x?t:ze(t);case"texture2d":return t;case"sampler2d":if(function(t){const e=t;return t instanceof d||t instanceof m||"function"==typeof e?.isSampler2D||!0===e?.isSampler2D}(t))return t;if(t instanceof i)return dt(t);throw new ShaderGraphCompileError(`Parameter "${r}" needs a texture value`)}}function Oe(t,e,a,r){const u=`${a}Scalar`;if(e instanceof p&&"function"==typeof t[u])return t[u](e);if("function"==typeof t[a])return t[a](e);throw new ShaderGraphCompileError(`Node does not support ${a}`,r)}function Me(t,e,a){if(t===e)return t;if("rgb"===t&&"vec3"===e||"vec3"===t&&"rgb"===e)return"vec3";if("rgba"===t&&"vec4"===e||"vec4"===t&&"rgba"===e)return"vec4";if("float"===t&&Ee(e))return e;if("float"===e&&Ee(t))return t;throw new ShaderGraphCompileError(`Cannot mix ${t} and ${e}`,a)}function Ce(t,e,a){const r=t.subtract(a),u=st(e),i=G(e);return Ot(i.multiply(r.x).subtract(u.multiply(r.y)).add(a.x),u.multiply(r.x).add(i.multiply(r.y)).add(a.y))}function Ne(t,e,a){const r=t.value["u"===e?"x":"v"===e?"y":e];if(r instanceof p)return r;throw new ShaderGraphCompileError(`Component "${e}" is not available on ${t.type}`,a)}function Ee(t){return"float"===t||"vec2"===t||"vec3"===t||"vec4"===t||"rgb"===t||"rgba"===t}function Ue(t){return Number.isFinite(t)?Math.min(1,Math.max(0,t)):0}function Ge(t,e){if("number"==typeof t)return t;if("string"==typeof t){const a=parseFloat(t);return Number.isFinite(a)?a:e}return"boolean"==typeof t?t?1:0:e}function Be(t,a,r=0){if(Array.isArray(t))return Array.from({length:a},(e,a)=>Ge(t[a],r));if(t instanceof n||t instanceof o||t instanceof s)return Array.from({length:a},(e,a)=>t.toArray()[a]??r);if(t instanceof e){const e=t.toArray();return Array.from({length:a},(t,a)=>e[a]??(3===a?1:r))}if(null!=t&&"object"==typeof t){const e=t,u=["x","y","z","w"];if(u.some(t=>null!=e[t]))return Array.from({length:a},(t,a)=>Ge(e[u[a]],r));const i=["r","g","b","a"];if(i.some(t=>null!=e[t]))return Array.from({length:a},(t,a)=>Ge(e[i[a]],3===a?1:r))}return Array.from({length:a},()=>Ge(t,r))}function $e(t){const[e,a]=Be(t,2);return Ot(e,a)}function ke(t){const[e,a,r]=Be(t,3);return Mt(e,a,r)}function ze(t,a=1){if("string"==typeof t||"number"==typeof t||t instanceof e)return rt(t,a);if(t instanceof b)return rt(t,a);const[r,u,i,n]=Be(t,4,a);return Ct(r,u,i,n)}function Ae(t,e){return e<=1?0:t/(e-1)}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { ShaderGraphNodeKind, ShaderGraphValueType } from './model.js';
|
|
1
|
+
import type { ShaderGraphNodeKind, ShaderGraphSerializableValue, ShaderGraphValueType } from './model.js';
|
|
2
2
|
export interface ShaderGraphPortDefinition {
|
|
3
3
|
name: string;
|
|
4
4
|
type: ShaderGraphValueType | 'dynamic';
|
|
5
5
|
label?: string;
|
|
6
6
|
optional?: boolean;
|
|
7
|
+
defaultValue?: ShaderGraphSerializableValue;
|
|
8
|
+
inlineLiteral?: false;
|
|
7
9
|
}
|
|
10
|
+
export type ShaderGraphInlineLiteralType = Extract<ShaderGraphValueType, 'float' | 'vec2' | 'vec3' | 'vec4'>;
|
|
8
11
|
export interface ShaderGraphNodeDefinition {
|
|
9
12
|
kind: ShaderGraphNodeKind;
|
|
10
13
|
label: string;
|
|
@@ -14,4 +17,6 @@ export interface ShaderGraphNodeDefinition {
|
|
|
14
17
|
}
|
|
15
18
|
export declare const SHADER_GRAPH_NODE_DEFINITIONS: Record<ShaderGraphNodeKind, ShaderGraphNodeDefinition>;
|
|
16
19
|
export declare const SHADER_GRAPH_NODE_KINDS: ShaderGraphNodeKind[];
|
|
20
|
+
export declare function inlineLiteralTypeForPort(kind: ShaderGraphNodeKind, port: ShaderGraphPortDefinition): ShaderGraphInlineLiteralType | undefined;
|
|
21
|
+
export declare function defaultInlineLiteralValueForPort(kind: ShaderGraphNodeKind, port: ShaderGraphPortDefinition): ShaderGraphSerializableValue | undefined;
|
|
17
22
|
//# sourceMappingURL=registry.d.ts.map
|