@soonspacejs/plugin-first-person-controls 2.13.16 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Vector3, Vector2, Intersection, Sphere, Object3D, Box3, Camera } from 'three';
2
- import SoonSpace, { Position, Rotation } from 'soonspacejs';
2
+ import { default as SoonSpace, Position, Rotation } from 'soonspacejs';
3
3
  export type ClashCheckAxis = 'front' | 'back' | 'left' | 'right' | 'up' | 'down';
4
4
  /**
5
5
  * 碰撞对象过滤器
@@ -193,7 +193,7 @@ export default class FirstPersonControlsPlugin {
193
193
  */
194
194
  searchRadiusFactor: number;
195
195
  checkedSphere: Sphere;
196
- getCheckedObjects(origin: Vector3): Object3D<import("three").Object3DEventMap>[];
196
+ getCheckedObjects(origin: Vector3): Object3D<import('three').Object3DEventMap>[];
197
197
  /**
198
198
  * 重力搜索系数
199
199
  * @remarks
@@ -202,8 +202,8 @@ export default class FirstPersonControlsPlugin {
202
202
  gravitySearchFactor: number;
203
203
  gravityCheckedObjects: Object3D[] | null;
204
204
  gravityCheckedBox: Box3;
205
- getGravityCheckedObjects(origin: Vector3, dropY: number): Object3D<import("three").Object3DEventMap>[];
206
- gravityClashCheck(origin: Vector3, dropY: number): Intersection<Object3D<import("three").Object3DEventMap>>;
205
+ getGravityCheckedObjects(origin: Vector3, dropY: number): Object3D<import('three').Object3DEventMap>[];
206
+ gravityClashCheck(origin: Vector3, dropY: number): Intersection<Object3D<import('three').Object3DEventMap>>;
207
207
  setOptions(options: StartOptions): void;
208
208
  start(options: StartOptions): void;
209
209
  stop(): void;
package/dist/index.esm.js CHANGED
@@ -1 +1,463 @@
1
- import{Vector2 as t,Vector3 as e,Sphere as s,Box3 as i,Raycaster as o,Matrix4 as n,Euler as a,Quaternion as r}from"three";import h from"soonspacejs";const{utils:{isObjectVisible:c}}=h;function l(t,e){const s=h.utils.getBoundingBox(e);return t.intersectsBox(s)}function d(t,e){t.disableAll();for(const s of e)t.enable(s)}function p(t,e){return t.intersectObjects(e).filter(({object:t})=>c(t))}const{EPSILON:v,approxEquals:m}=h.utils,{utils:y}=h;class u{get rotate(){return this._rotate&&(this.horizontalRotate||this.verticalRotate)}set rotate(t){this._rotate=t}constructor(o){this.enabled=!1,this.keyCodeMap={moveForward:["ArrowUp","KeyW"],moveBackward:["ArrowDown","KeyS"],moveLeft:["ArrowLeft","KeyA"],moveRight:["ArrowRight","KeyD"],moveUp:["KeyQ"],moveDown:["KeyE"],rotateUp:["KeyI"],rotateDown:["KeyK"],rotateLeft:["KeyJ"],rotateRight:["KeyL"],jump:["Space"]},this.state={moveForward:!1,moveBackward:!1,moveLeft:!1,moveRight:!1,moveUp:!1,moveDown:!1,canJump:!1,canRotate:!1},this.moveSpeed=10,this.gravitySpeed=10,this.jumpOffset=0,this.clashCheckDistance=200,this.clashDistance=50,this.eyeHeight=160,this.kneeHeight=50,this.jumpHeight=110,this.enableClash=!0,this.enableGravity=!0,this.reverseRotate=!1,this._rotate=!0,this.rotateSpeed=1,this.horizontalRotate=!0,this.verticalRotate=!0,this.dblClickForward=!1,this.movement=new t,this._dblVector=new e,this._dblDeltaVector=new e,this._pointerId=null,this.lastDirection=new e,this.searchRadiusFactor=3,this.checkedSphere=new s,this.gravitySearchFactor=3,this.gravityCheckedObjects=null,this.gravityCheckedBox=new i,this.gravityInterObject=null,this.kneeInterObject=null,this.eyeInterObject=null,this.ssp=o,this.viewport=o.viewport,this.controls=o.controls,this.camera=o.controls.camera,this.container=o.viewport.container,this.onKeyDown=this.onKeyDown.bind(this),this.onKeyUp=this.onKeyUp.bind(this),this.onDblClick=this.onDblClick.bind(this),this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this)}onKeyDown(t){if(!1!==this.enabled){t:for(const[e,s]of Object.entries(this.keyCodeMap))if(s.includes(t.code))switch(e){case"moveForward":this.state.moveForward=!0;break t;case"moveBackward":this.state.moveBackward=!0;break t;case"moveLeft":this.state.moveLeft=!0;break t;case"moveRight":this.state.moveRight=!0;break t;case"moveUp":this.state.moveUp=!0;break t;case"moveDown":this.state.moveDown=!0;break t;case"rotateUp":this.state.canRotate=!0,this.movement.x=0,this.movement.y=-10;break t;case"rotateDown":this.state.canRotate=!0,this.movement.x=0,this.movement.y=10;break t;case"rotateLeft":this.state.canRotate=!0,this.movement.x=-10,this.movement.y=0;break t;case"rotateRight":this.state.canRotate=!0,this.movement.x=10,this.movement.y=0;break t;case"jump":!0===this.state.canJump&&!1===t.repeat&&(this.jumpOffset=this.jumpHeight),this.state.canJump=!1;break t}(this.jumpOffset>0||Object.values(this.state).some(t=>t))&&this.ssp.render()}}onKeyUp(t){t:for(const[e,s]of Object.entries(this.keyCodeMap))if(s.includes(t.code))switch(e){case"moveForward":this.state.moveForward=!1;break t;case"moveBackward":this.state.moveBackward=!1;break t;case"moveLeft":this.state.moveLeft=!1;break t;case"moveRight":this.state.moveRight=!1;break t;case"moveUp":this.state.moveUp=!1;break t;case"moveDown":this.state.moveDown=!1;break t;case"rotateUp":case"rotateDown":case"rotateLeft":case"rotateRight":this.state.canRotate=!1;break t}}onDblClick(t){if(!0===this.dblClickForward){const[e]=this.ssp.viewport.getIntersects(t);if(e){const{point:t}=e;t.y+=this.eyeHeight,t.sub(this.camera.position),this._dblVector.copy(t),this._dblDeltaVector.set(0,0,0),this.ssp.render()}}}onPointerDown(t){null===this._pointerId&&0===t.button&&(this.container.setPointerCapture(t.pointerId),this._pointerId=t.pointerId,this.state.canRotate=!0)}onPointerMove(t){if(t.preventDefault(),this.enabled&&this.state.canRotate){let e=t.movementY,s=t.movementX;this.reverseRotate&&(s=-s,e=-e),this.movement.x=s,this.movement.y=e,this.ssp.render()}}onPointerUp(t){null!==this._pointerId&&(this.container.releasePointerCapture(t.pointerId),this._pointerId=null,this.state.canRotate=!1)}clearClashCache(){this.kneeInterObject=null,this.eyeInterObject=null}onClashCheck(t,e){const s=e.length(),i=e.clone().divideScalar(s);i.distanceToSquared(this.lastDirection)>1e-9&&this.clearClashCache(),this.lastDirection=i;const{eyeHeight:n,kneeHeight:a,camera:r,clashCheckDistance:h,clashDistance:c,clashLayers:l}=this;let{kneeInterObject:v,eyeInterObject:m}=this;if(!v){const e=t.clone().setY(t.y-n+a),s=new o(e,i,0,h);s.firstHitOnly=!0,null!=l&&d(s.layers,l),s.camera=r;const c=p(s,this.getCheckedObjects(e));this.kneeInterObject=v=c[0]}let y=-s;if(v&&(y+=v.distance,y<c))return!0;if(!m){const e=new o(t,i,0,h);e.firstHitOnly=!0,null!=l&&d(e.layers,l),e.camera=r;const s=p(e,this.getCheckedObjects(t));this.eyeInterObject=m=s[0]}let u=-s;if(m){if(u+=m.distance,u<c)return!0;m.distance=u}return v&&(v.distance=y),!1}getCheckedObjects(t){const{clashDistance:e,clashCheckDistance:s,searchRadiusFactor:i,clashFilter:o}=this,n=s*i,a=this.checkedSphere,r=n+e;a.set(t,r);const h=null!=o?o:function(){return!0};return this.viewport.scener.intersectsList.getAll().filter(t=>!!h(t)&&l(a,t))}getGravityCheckedObjects(t,s){const i=this.gravityCheckedBox;let o=this.gravityCheckedObjects;if(o){const e=t.clone();e.y=s,i.containsPoint(t)&&i.containsPoint(e)||(o=null)}if(!o){const{eyeHeight:s,clashCheckDistance:n,gravitySearchFactor:a,clashDistance:r,clashFilter:h}=this,c=n+r,d=new e(c,c,0),p=t.clone().add(d),v=t.clone().sub(d);v.y-=s*a,i.set(v,p);const m=this.viewport.scener.intersectsList.getAll(),y=null!=h?h:function(){return!0};o=m.filter(t=>!!y(t)&&l(i,t))}return o}gravityClashCheck(t,s){var i;let a=this.gravityInterObject;if(a){const{object:s,face:o,instanceId:r}=a,h=null===(i=s.geometry)||void 0===i?void 0:i.getAttribute("position");if(h&&o){let i=a.facePoints;if(!i){let t=s.matrixWorld;if(null!=r){const e=new n;s.getMatrixAt(r,e),t=e.premultiply(t)}const{a:c,b:l,c:d}=o,p=new e(h.getX(c),h.getY(c),h.getZ(c));p.applyMatrix4(t),p.setY(0);const v=new e(h.getX(l),h.getY(l),h.getZ(l));v.applyMatrix4(t),v.setY(0);const m=new e(h.getX(d),h.getY(d),h.getZ(d));m.applyMatrix4(t),m.setY(0),a.facePoints=i=[p,v,m]}let c=i[2],l=null;const d=t.clone();d.y=0;i.every(t=>{const e=t.clone();e.sub(c);const s=d.clone();if(s.sub(c),e.cross(s),l){if(e.dot(l)<=0)return!1}return l=e,c=t,!0})||(this.gravityInterObject=a=null)}}if(!a){const i=new o(t,new e(0,-1,0));i.firstHitOnly=!0;const n=this.clashLayers;null!=n&&d(i.layers,n),i.camera=this.camera;const r=p(i,this.getGravityCheckedObjects(t,s));this.gravityInterObject=a=r[0]}return a}setOptions(t){const{position:s=new e,rotation:i=new a,moveSpeed:o,eyeHeight:n,kneeHeight:r,jumpHeight:h,enableClash:c,enableGravity:l,searchRadiusFactor:d,clashDistance:p,clashCheckDistance:m,gravitySpeed:u,gravitySearchFactor:b,reverseRotate:g,rotate:w,rotateSpeed:f,horizontalRotate:k,verticalRotate:C,dblClickForward:D,clashFilter:j,clashLayers:R}=t;if(n&&(this.eyeHeight=n),r&&(this.kneeHeight=r),h&&(this.jumpHeight=h),d&&(this.searchRadiusFactor=d),p&&(this.clashDistance=p),m&&(this.clashCheckDistance=m),u&&(this.gravitySpeed=u),b&&(this.gravitySearchFactor=b),null!=g&&(this.reverseRotate=g),null!=w&&(this.rotate=w),null!=k&&(this.horizontalRotate=k),null!=C&&(this.verticalRotate=C),y.isBoolean(D)&&(this.dblClickForward=D),y.isNumber(f)&&(this.rotateSpeed=f),null!=c&&(this.enableClash=c),null!=l&&(this.enableGravity=l),null!=j&&(this.clashFilter=j),null!=R&&(this.clashLayers=R),s&&(this.controls.setPosition(s.x,s.y+this.eyeHeight,s.z),this.gravityInterObject=null,this.clearClashCache()),i){const t=y.computeTargetByRotation(this.controls.getPosition(new e),i,v);this.controls.setTarget(t.x,t.y,t.z)}o&&(this.moveSpeed=o)}start(t){this.viewport.controls.saveState(),this.viewport.controls.enabled=!1,this.enabled=!0,this.setOptions(t),this.viewport.postRender.set("FirstPersonControls",this.update.bind(this)),this.ssp.signals.dblClick.add(this.onDblClick),this.ssp.signals.keyDown.add(this.onKeyDown),this.ssp.signals.keyUp.add(this.onKeyUp);const e=this.container;e.addEventListener("pointerdown",this.onPointerDown),e.addEventListener("pointermove",this.onPointerMove),e.addEventListener("pointerup",this.onPointerUp),e.style.touchAction="none",e.style.userSelect="none"}stop(){this.viewport.controls.reset(),this.viewport.controls.enabled=!0,this.enabled=!1,this.viewport.postRender.delete("FirstPersonControls"),this.ssp.signals.dblClick.remove(this.onDblClick),this.ssp.signals.keyDown.remove(this.onKeyDown),this.ssp.signals.keyUp.remove(this.onKeyUp);const t=this.container;t.removeEventListener("pointerdown",this.onPointerDown),t.removeEventListener("pointermove",this.onPointerMove),t.removeEventListener("pointerup",this.onPointerUp),t.style.touchAction="auto",t.style.userSelect="auto",this.ssp.render()}update(){if(!this.enabled)return;const{delta:t}=this.viewport.state,s=new e,{controls:i,state:o,camera:n,eyeHeight:h,kneeHeight:c}=this,l=i.getPosition(new e),d=20*this.moveSpeed,p=20*this.gravitySpeed;o.moveForward&&(s.z-=d),o.moveBackward&&(s.z+=d),o.moveLeft&&(s.x-=d),o.moveRight&&(s.x+=d),o.moveUp&&(s.y+=2*p),o.moveDown&&(s.y-=2*p),s.multiplyScalar(t);const{x:y,y:u}=this.movement,b=this.horizontalRotate&&0!==y,g=this.verticalRotate&&0!==u;if(this.rotate&&o.canRotate&&(b||g)){let{azimuthAngle:t,polarAngle:e}=i;g&&(e-=.003*u*this.rotateSpeed),b&&(t-=.003*y*this.rotateSpeed),i.rotateTo(t,e)}const w=new a(0,0,0,"YXZ");if(w.setFromQuaternion(n.quaternion),0!==w.y&&!s.equals(new e)){const t=new r;t.setFromAxisAngle(new e(0,1,0),w.y),s.applyQuaternion(t)}if(!this._dblVector.equals(new e)){const e=this._dblVector.clone().multiplyScalar(t);this._dblDeltaVector.add(e),this._dblDeltaVector.length()>this._dblVector.length()?(this._dblVector.set(0,0,0),this._dblDeltaVector.set(0,0,0)):s.add(e)}const f=l.clone();if((!this.enableClash||!this.onClashCheck(l,s))&&(f.add(s),this.gravityInterObject)){const t=this.gravityInterObject.point.clone().sub(f);t.y=0,t.length()>c&&(this.gravityInterObject=null)}let k=f.y;if(this.enableGravity){const e=k;this.jumpOffset>0&&(this.jumpOffset-=p*t,k+=2*p*t),k-=p*t,o.canJump=!1;const s=this.gravityClashCheck(f,k);if(s){const t=s.point.y+h;k<t&&(k=t,this.jumpOffset=0,o.canJump=!0)}e!==k&&this.clearClashCache()}f.y=k,m(l.x,f.x)&&m(l.y,f.y)&&m(l.z,f.z)||(i.moveTo(f.x,f.y,f.z),i.dollyTo(v))}}export{u as default};
1
+ import { Vector2 as K, Vector3 as g, Raycaster as O, Sphere as _, Box3 as H, Matrix4 as V, Euler as F, Quaternion as A } from "three";
2
+ import D from "soonspacejs";
3
+ const { utils: { isObjectVisible: B } } = D;
4
+ function L(w, e) {
5
+ const t = D.utils.getBoundingBox(e);
6
+ return w.intersectsBox(t);
7
+ }
8
+ function R(w, e) {
9
+ w.disableAll();
10
+ for (const t of e)
11
+ w.enable(t);
12
+ }
13
+ function I(w, e) {
14
+ return w.intersectObjects(e).filter(({ object: s }) => B(s));
15
+ }
16
+ const { EPSILON: U, approxEquals: P } = D.utils, { utils: S } = D;
17
+ class M {
18
+ ssp;
19
+ viewport;
20
+ controls;
21
+ camera;
22
+ container;
23
+ enabled = !1;
24
+ keyCodeMap = {
25
+ moveForward: ["ArrowUp", "KeyW"],
26
+ moveBackward: ["ArrowDown", "KeyS"],
27
+ moveLeft: ["ArrowLeft", "KeyA"],
28
+ moveRight: ["ArrowRight", "KeyD"],
29
+ moveUp: ["KeyQ"],
30
+ moveDown: ["KeyE"],
31
+ rotateUp: ["KeyI"],
32
+ rotateDown: ["KeyK"],
33
+ rotateLeft: ["KeyJ"],
34
+ rotateRight: ["KeyL"],
35
+ jump: ["Space"]
36
+ };
37
+ state = {
38
+ moveForward: !1,
39
+ moveBackward: !1,
40
+ moveLeft: !1,
41
+ moveRight: !1,
42
+ moveUp: !1,
43
+ moveDown: !1,
44
+ canJump: !1,
45
+ canRotate: !1
46
+ };
47
+ /**
48
+ * 移动速度
49
+ */
50
+ moveSpeed = 10;
51
+ /**
52
+ * 重力速度
53
+ */
54
+ gravitySpeed = 10;
55
+ jumpOffset = 0;
56
+ /**
57
+ * 碰撞检测距离
58
+ */
59
+ clashCheckDistance = 200;
60
+ /**
61
+ * 碰撞距离
62
+ */
63
+ clashDistance = 50;
64
+ eyeHeight = 160;
65
+ kneeHeight = 50;
66
+ jumpHeight = 110;
67
+ enableClash = !0;
68
+ enableGravity = !0;
69
+ /**
70
+ * 反向旋转
71
+ */
72
+ reverseRotate = !1;
73
+ _rotate = !0;
74
+ /**
75
+ * 是否能旋转
76
+ */
77
+ get rotate() {
78
+ return this._rotate && (this.horizontalRotate || this.verticalRotate);
79
+ }
80
+ set rotate(e) {
81
+ this._rotate = e;
82
+ }
83
+ /**
84
+ * 旋转速度
85
+ */
86
+ rotateSpeed = 1;
87
+ /**
88
+ * 是否开启水平方向的旋转
89
+ */
90
+ horizontalRotate = !0;
91
+ /**
92
+ * 是否开启垂直方向旋转
93
+ */
94
+ verticalRotate = !0;
95
+ /**
96
+ * 开启双击前进
97
+ */
98
+ dblClickForward = !1;
99
+ movement = new K();
100
+ /**
101
+ * 碰撞对象过滤器
102
+ * @remarks
103
+ * 会在遍历对象时逐个调用该方法
104
+ *
105
+ * @param obj - Object3D 对象
106
+ * @returns true:表示检测该对象的碰撞;false | null | undefined | void:表示不检测该对象的碰撞;
107
+ */
108
+ clashFilter;
109
+ /**
110
+ * 碰撞检测的层级
111
+ */
112
+ clashLayers;
113
+ /**
114
+ *
115
+ * @param ssp
116
+ * @param camera - 自定义的摄像机,默认会自动生成一个新的摄像机
117
+ */
118
+ constructor(e) {
119
+ this.ssp = e, this.viewport = e.viewport, this.controls = e.controls, this.camera = e.controls.camera, this.container = e.viewport.container, this.onKeyDown = this.onKeyDown.bind(this), this.onKeyUp = this.onKeyUp.bind(this), this.onDblClick = this.onDblClick.bind(this), this.onPointerDown = this.onPointerDown.bind(this), this.onPointerMove = this.onPointerMove.bind(this), this.onPointerUp = this.onPointerUp.bind(this);
120
+ }
121
+ onKeyDown(e) {
122
+ if (this.enabled !== !1) {
123
+ e: for (const [t, s] of Object.entries(this.keyCodeMap))
124
+ if (s.includes(e.code))
125
+ switch (t) {
126
+ case "moveForward":
127
+ this.state.moveForward = !0;
128
+ break e;
129
+ case "moveBackward":
130
+ this.state.moveBackward = !0;
131
+ break e;
132
+ case "moveLeft":
133
+ this.state.moveLeft = !0;
134
+ break e;
135
+ case "moveRight":
136
+ this.state.moveRight = !0;
137
+ break e;
138
+ case "moveUp":
139
+ this.state.moveUp = !0;
140
+ break e;
141
+ case "moveDown":
142
+ this.state.moveDown = !0;
143
+ break e;
144
+ case "rotateUp":
145
+ this.state.canRotate = !0, this.movement.x = 0, this.movement.y = -10;
146
+ break e;
147
+ case "rotateDown":
148
+ this.state.canRotate = !0, this.movement.x = 0, this.movement.y = 10;
149
+ break e;
150
+ case "rotateLeft":
151
+ this.state.canRotate = !0, this.movement.x = -10, this.movement.y = 0;
152
+ break e;
153
+ case "rotateRight":
154
+ this.state.canRotate = !0, this.movement.x = 10, this.movement.y = 0;
155
+ break e;
156
+ case "jump":
157
+ this.state.canJump === !0 && e.repeat === !1 && (this.jumpOffset = this.jumpHeight), this.state.canJump = !1;
158
+ break e;
159
+ }
160
+ (this.jumpOffset > 0 || Object.values(this.state).some((t) => t)) && this.ssp.render();
161
+ }
162
+ }
163
+ onKeyUp(e) {
164
+ e: for (const [t, s] of Object.entries(this.keyCodeMap))
165
+ if (s.includes(e.code))
166
+ switch (t) {
167
+ case "moveForward":
168
+ this.state.moveForward = !1;
169
+ break e;
170
+ case "moveBackward":
171
+ this.state.moveBackward = !1;
172
+ break e;
173
+ case "moveLeft":
174
+ this.state.moveLeft = !1;
175
+ break e;
176
+ case "moveRight":
177
+ this.state.moveRight = !1;
178
+ break e;
179
+ case "moveUp":
180
+ this.state.moveUp = !1;
181
+ break e;
182
+ case "moveDown":
183
+ this.state.moveDown = !1;
184
+ break e;
185
+ case "rotateUp":
186
+ case "rotateDown":
187
+ case "rotateLeft":
188
+ case "rotateRight":
189
+ this.state.canRotate = !1;
190
+ break e;
191
+ }
192
+ }
193
+ _dblVector = new g();
194
+ _dblDeltaVector = new g();
195
+ onDblClick(e) {
196
+ if (this.dblClickForward === !0) {
197
+ const [t] = this.ssp.viewport.getIntersects(e);
198
+ if (t) {
199
+ const { point: s } = t;
200
+ s.y += this.eyeHeight, s.sub(this.camera.position), this._dblVector.copy(s), this._dblDeltaVector.set(0, 0, 0), this.ssp.render();
201
+ }
202
+ }
203
+ }
204
+ _pointerId = null;
205
+ onPointerDown(e) {
206
+ this._pointerId === null && // 左键
207
+ e.button === 0 && (this.container.setPointerCapture(e.pointerId), this._pointerId = e.pointerId, this.state.canRotate = !0);
208
+ }
209
+ /**
210
+ * events handler for pointer movement
211
+ */
212
+ onPointerMove(e) {
213
+ if (e.preventDefault(), this.enabled && this.state.canRotate) {
214
+ let t = e.movementY, s = e.movementX;
215
+ this.reverseRotate && (s = -s, t = -t), this.movement.x = s, this.movement.y = t, this.ssp.render();
216
+ }
217
+ }
218
+ onPointerUp(e) {
219
+ this._pointerId !== null && (this.container.releasePointerCapture(e.pointerId), this._pointerId = null, this.state.canRotate = !1);
220
+ }
221
+ clearClashCache() {
222
+ this.kneeInterObject = null, this.eyeInterObject = null;
223
+ }
224
+ lastDirection = new g();
225
+ onClashCheck(e, t) {
226
+ const s = t.length(), i = t.clone().divideScalar(s);
227
+ i.distanceToSquared(this.lastDirection) > 1e-9 && this.clearClashCache(), this.lastDirection = i;
228
+ const {
229
+ eyeHeight: v,
230
+ kneeHeight: p,
231
+ camera: n,
232
+ clashCheckDistance: h,
233
+ clashDistance: m,
234
+ clashLayers: r
235
+ } = this;
236
+ let { kneeInterObject: c, eyeInterObject: y } = this;
237
+ if (!c) {
238
+ const a = e.clone().setY(e.y - v + p), o = new O(
239
+ a,
240
+ i,
241
+ 0,
242
+ h
243
+ );
244
+ o.firstHitOnly = !0, r != null && R(o.layers, r), o.camera = n;
245
+ const u = this.getCheckedObjects(a), d = I(o, u);
246
+ this.kneeInterObject = c = d[0];
247
+ }
248
+ let l = -s;
249
+ if (c && (l += c.distance, l < m))
250
+ return !0;
251
+ if (!y) {
252
+ const a = new O(
253
+ e,
254
+ i,
255
+ 0,
256
+ h
257
+ );
258
+ a.firstHitOnly = !0, r != null && R(a.layers, r), a.camera = n;
259
+ const o = this.getCheckedObjects(e), u = I(a, o);
260
+ this.eyeInterObject = y = u[0];
261
+ }
262
+ let f = -s;
263
+ if (y) {
264
+ if (f += y.distance, f < m) return !0;
265
+ y.distance = f;
266
+ }
267
+ return c && (c.distance = l), !1;
268
+ }
269
+ /**
270
+ * 模型对象的搜索半径的系数
271
+ * @remarks
272
+ * 搜索半径是 clashCheckDistance 的多少倍
273
+ */
274
+ searchRadiusFactor = 3;
275
+ checkedSphere = new _();
276
+ getCheckedObjects(e) {
277
+ const {
278
+ clashDistance: t,
279
+ clashCheckDistance: s,
280
+ searchRadiusFactor: i,
281
+ clashFilter: v
282
+ } = this, p = s * i, n = this.checkedSphere, h = p + t;
283
+ n.set(e, h);
284
+ const m = v ?? function() {
285
+ return !0;
286
+ };
287
+ return this.viewport.scener.intersectsList.getAll().filter((c) => m(c) ? L(n, c) : !1);
288
+ }
289
+ /**
290
+ * 重力搜索系数
291
+ * @remarks
292
+ * 重力搜索系数 表示 向下搜索多少个 eyeHeight 的深度
293
+ */
294
+ gravitySearchFactor = 3;
295
+ gravityCheckedObjects = null;
296
+ gravityCheckedBox = new H();
297
+ getGravityCheckedObjects(e, t) {
298
+ const s = this.gravityCheckedBox;
299
+ let i = this.gravityCheckedObjects;
300
+ if (i) {
301
+ const v = e.clone();
302
+ v.y = t, s.containsPoint(e) && s.containsPoint(v) || (i = null);
303
+ }
304
+ if (!i) {
305
+ const {
306
+ eyeHeight: v,
307
+ clashCheckDistance: p,
308
+ gravitySearchFactor: n,
309
+ clashDistance: h,
310
+ clashFilter: m
311
+ } = this, r = p + h, c = new g(r, r, 0), y = e.clone().add(c), l = e.clone().sub(c);
312
+ l.y -= v * n, s.set(l, y);
313
+ const f = this.viewport.scener.intersectsList.getAll(), a = m ?? function() {
314
+ return !0;
315
+ };
316
+ i = f.filter((o) => a(o) ? L(s, o) : !1);
317
+ }
318
+ return i;
319
+ }
320
+ gravityClashCheck(e, t) {
321
+ let s = this.gravityInterObject;
322
+ if (s) {
323
+ const { object: i, face: v, instanceId: p } = s, n = i.geometry?.getAttribute(
324
+ "position"
325
+ );
326
+ if (n && v) {
327
+ let h = s.facePoints;
328
+ if (!h) {
329
+ let l = i.matrixWorld;
330
+ if (p != null) {
331
+ const k = new V();
332
+ i.getMatrixAt(p, k), l = k.premultiply(l);
333
+ }
334
+ const { a: f, b: a, c: o } = v, u = new g(
335
+ n.getX(f),
336
+ n.getY(f),
337
+ n.getZ(f)
338
+ );
339
+ u.applyMatrix4(l), u.setY(0);
340
+ const d = new g(
341
+ n.getX(a),
342
+ n.getY(a),
343
+ n.getZ(a)
344
+ );
345
+ d.applyMatrix4(l), d.setY(0);
346
+ const b = new g(
347
+ n.getX(o),
348
+ n.getY(o),
349
+ n.getZ(o)
350
+ );
351
+ b.applyMatrix4(l), b.setY(0), s.facePoints = h = [
352
+ u,
353
+ d,
354
+ b
355
+ ];
356
+ }
357
+ let m = h[2], r = null;
358
+ const c = e.clone();
359
+ c.y = 0, h.every((l) => {
360
+ const f = l.clone();
361
+ f.sub(m);
362
+ const a = c.clone();
363
+ return a.sub(m), f.cross(a), r && f.dot(r) <= 0 ? !1 : (r = f, m = l, !0);
364
+ }) || (this.gravityInterObject = s = null);
365
+ }
366
+ }
367
+ if (!s) {
368
+ const i = new O(e, new g(0, -1, 0));
369
+ i.firstHitOnly = !0;
370
+ const v = this.clashLayers;
371
+ v != null && R(i.layers, v), i.camera = this.camera;
372
+ const p = this.getGravityCheckedObjects(e, t), n = I(i, p);
373
+ this.gravityInterObject = s = n[0];
374
+ }
375
+ return s;
376
+ }
377
+ setOptions(e) {
378
+ const {
379
+ position: t = new g(),
380
+ rotation: s = new F(),
381
+ moveSpeed: i,
382
+ eyeHeight: v,
383
+ kneeHeight: p,
384
+ jumpHeight: n,
385
+ enableClash: h,
386
+ enableGravity: m,
387
+ searchRadiusFactor: r,
388
+ clashDistance: c,
389
+ clashCheckDistance: y,
390
+ gravitySpeed: l,
391
+ gravitySearchFactor: f,
392
+ reverseRotate: a,
393
+ rotate: o,
394
+ rotateSpeed: u,
395
+ horizontalRotate: d,
396
+ verticalRotate: b,
397
+ dblClickForward: k,
398
+ clashFilter: C,
399
+ clashLayers: x
400
+ } = e;
401
+ if (v && (this.eyeHeight = v), p && (this.kneeHeight = p), n && (this.jumpHeight = n), r && (this.searchRadiusFactor = r), c && (this.clashDistance = c), y && (this.clashCheckDistance = y), l && (this.gravitySpeed = l), f && (this.gravitySearchFactor = f), a != null && (this.reverseRotate = a), o != null && (this.rotate = o), d != null && (this.horizontalRotate = d), b != null && (this.verticalRotate = b), S.isBoolean(k) && (this.dblClickForward = k), S.isNumber(u) && (this.rotateSpeed = u), h != null && (this.enableClash = h), m != null && (this.enableGravity = m), C != null && (this.clashFilter = C), x != null && (this.clashLayers = x), t && (this.controls.setPosition(
402
+ t.x,
403
+ t.y + this.eyeHeight,
404
+ t.z
405
+ ), this.gravityInterObject = null, this.clearClashCache()), s) {
406
+ const j = S.computeTargetByRotation(this.controls.getPosition(new g()), s, U);
407
+ this.controls.setTarget(j.x, j.y, j.z);
408
+ }
409
+ i && (this.moveSpeed = i);
410
+ }
411
+ start(e) {
412
+ this.viewport.controls.saveState(), this.viewport.controls.enabled = !1, this.enabled = !0, this.setOptions(e), this.viewport.postRender.set("FirstPersonControls", this.update.bind(this)), this.ssp.signals.dblClick.add(this.onDblClick), this.ssp.signals.keyDown.add(this.onKeyDown), this.ssp.signals.keyUp.add(this.onKeyUp);
413
+ const t = this.container;
414
+ t.addEventListener("pointerdown", this.onPointerDown), t.addEventListener("pointermove", this.onPointerMove), t.addEventListener("pointerup", this.onPointerUp), t.style.touchAction = "none", t.style.userSelect = "none";
415
+ }
416
+ stop() {
417
+ this.viewport.controls.reset(), this.viewport.controls.enabled = !0, this.enabled = !1, this.viewport.postRender.delete("FirstPersonControls"), this.ssp.signals.dblClick.remove(this.onDblClick), this.ssp.signals.keyDown.remove(this.onKeyDown), this.ssp.signals.keyUp.remove(this.onKeyUp);
418
+ const e = this.container;
419
+ e.removeEventListener("pointerdown", this.onPointerDown), e.removeEventListener("pointermove", this.onPointerMove), e.removeEventListener("pointerup", this.onPointerUp), e.style.touchAction = "auto", e.style.userSelect = "auto", this.ssp.render();
420
+ }
421
+ gravityInterObject = null;
422
+ kneeInterObject = null;
423
+ eyeInterObject = null;
424
+ update() {
425
+ if (!this.enabled) return;
426
+ const { delta: e } = this.viewport.state, t = new g(), { controls: s, state: i, camera: v, eyeHeight: p, kneeHeight: n } = this, h = s.getPosition(new g()), m = this.moveSpeed * 20, r = this.gravitySpeed * 20;
427
+ i.moveForward && (t.z -= m), i.moveBackward && (t.z += m), i.moveLeft && (t.x -= m), i.moveRight && (t.x += m), i.moveUp && (t.y += r * 2), i.moveDown && (t.y -= r * 2), t.multiplyScalar(e);
428
+ const { x: c, y } = this.movement, l = this.horizontalRotate && c !== 0, f = this.verticalRotate && y !== 0;
429
+ if (this.rotate && i.canRotate && (l || f)) {
430
+ let { azimuthAngle: d, polarAngle: b } = s;
431
+ f && (b -= y * 3e-3 * this.rotateSpeed), l && (d -= c * 3e-3 * this.rotateSpeed), s.rotateTo(d, b);
432
+ }
433
+ const a = new F(0, 0, 0, "YXZ");
434
+ if (a.setFromQuaternion(v.quaternion), !(a.y === 0 || t.equals(new g()))) {
435
+ const d = new A();
436
+ d.setFromAxisAngle(new g(0, 1, 0), a.y), t.applyQuaternion(d);
437
+ }
438
+ if (!this._dblVector.equals(new g())) {
439
+ const d = this._dblVector.clone().multiplyScalar(e);
440
+ this._dblDeltaVector.add(d), this._dblDeltaVector.length() > this._dblVector.length() ? (this._dblVector.set(0, 0, 0), this._dblDeltaVector.set(0, 0, 0)) : t.add(d);
441
+ }
442
+ const o = h.clone();
443
+ if ((!this.enableClash || !this.onClashCheck(h, t)) && (o.add(t), this.gravityInterObject)) {
444
+ const b = this.gravityInterObject.point.clone().sub(o);
445
+ b.y = 0, b.length() > n && (this.gravityInterObject = null);
446
+ }
447
+ let u = o.y;
448
+ if (this.enableGravity) {
449
+ const d = u;
450
+ this.jumpOffset > 0 && (this.jumpOffset -= r * e, u += r * 2 * e), u -= r * e, i.canJump = !1;
451
+ const b = this.gravityClashCheck(o, u);
452
+ if (b) {
453
+ const C = b.point.y + p;
454
+ u < C && (u = C, this.jumpOffset = 0, i.canJump = !0);
455
+ }
456
+ d !== u && this.clearClashCache();
457
+ }
458
+ o.y = u, (!P(h.x, o.x) || !P(h.y, o.y) || !P(h.z, o.z)) && (s.moveTo(o.x, o.y, o.z), s.dollyTo(U));
459
+ }
460
+ }
461
+ export {
462
+ M as default
463
+ };
package/dist/tools.d.ts CHANGED
@@ -4,4 +4,4 @@ import { Box3, Object3D, Sphere, Layers, Raycaster } from 'three';
4
4
  */
5
5
  export declare function boundingIsIntersected(target: Box3 | Sphere, obj: Object3D): boolean;
6
6
  export declare function setLayers(layer: Layers, layerNums: number[]): void;
7
- export declare function raycasterFilter(raycaster: Raycaster, objs: Object3D[]): import("three").Intersection<Object3D<import("three").Object3DEventMap>>[];
7
+ export declare function raycasterFilter(raycaster: Raycaster, objs: Object3D[]): import('three').Intersection<Object3D<import('three').Object3DEventMap>>[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@soonspacejs/plugin-first-person-controls",
3
3
  "pluginName": "FirstPersonControlsPlugin",
4
- "version": "2.13.16",
4
+ "version": "2.14.0",
5
5
  "description": "FirstPersonControls plugin for SoonSpace.js",
6
6
  "main": "dist/index.esm.js",
7
7
  "module": "dist/index.esm.js",
@@ -13,8 +13,8 @@
13
13
  ],
14
14
  "author": "xunwei",
15
15
  "license": "UNLICENSED",
16
- "gitHead": "aaf0c46565c740277fad34bc3a3ba9fa61d48278",
16
+ "gitHead": "4c85e8b7b8ad24ccb9b42f3a1826bca377c42a6d",
17
17
  "peerDependencies": {
18
- "soonspacejs": "2.13.16"
18
+ "soonspacejs": "2.14.0"
19
19
  }
20
20
  }