@soonspacejs/plugin-patrol-controls 2.13.17 → 2.14.1

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,9 +1,6 @@
1
1
  import { PerspectiveCamera, OrthographicCamera } from 'three';
2
- import SoonSpace from 'soonspacejs';
3
- import type { CameraViewpointData, Position } from 'soonspacejs';
4
- import type { Node } from 'soonspacejs';
5
- import type { Topology } from 'soonspacejs';
6
- import type { Tween } from 'three/examples/jsm/libs/tween.module.js';
2
+ import { default as SoonSpace, CameraViewpointData, Position, Node, Topology } from 'soonspacejs';
3
+ import { Tween } from 'three/examples/jsm/libs/tween.module.js';
7
4
  export type ProgressParams = {
8
5
  patrolled: number;
9
6
  total: number;
package/dist/index.esm.js CHANGED
@@ -1 +1,242 @@
1
- import{Vector3 as t,Matrix4 as s,Quaternion as i}from"three";const e=1e-5;class o{constructor(t){this.ssp=t,this.options={naviSpeed:1,rotateSpeed:1,eyeHeight:150,flyToStartPoint:!0,onUpdate:()=>{},onProgress:()=>{},onEnd:()=>{}},this.states={moveDuration:0,rotateDuration:0},this.nodes=[],this.nextPointIndex=0,this._nodeDistances=[],this._totalDistance=0,this._updatePercent=0,this._needsUpdateProgress=!1,this.isPaused=!1,this.isStoped=!0,this._positionTween=null,this._rotationTween=null,this._cameraViewpointData=null;const{cameraManager:s}=this.ssp.viewport;this.camera=s.mainCamera}start(t,s){this.isStoped?(this.ssp.controls.saveState(),this.ssp.controls.enabled=!1,this.init(t),this.initOptions(s),this.patrolStart()):this.ssp.utils.warn("巡检已经开始!")}setProgress(t){var s,i;this._updatePercent=Math.min(Math.max(t,0),1),this._needsUpdateProgress=!0,null===(s=this._positionTween)||void 0===s||s.stop(),null===(i=this._rotationTween)||void 0===i||i.stop()}setOptions(t){if(this.isStoped)return;const{naviSpeed:s,rotateSpeed:i}=t;if(s&&this._positionTween){const t=this.states.moveDuration*this.options.naviSpeed/s;this._positionTween.duration(t),this.states.moveDuration=t}if(i&&this._rotationTween){const t=this.states.rotateDuration*this.options.rotateSpeed/i;this._rotationTween.duration(t),this.states.rotateDuration=t}this.initOptions(t)}pause(){var t,s;this.isPaused||this.isStoped||(this._cameraViewpointData=this.ssp.getCameraViewpoint(),this.isPaused=!0,null===(t=this._positionTween)||void 0===t||t.pause(),null===(s=this._rotationTween)||void 0===s||s.pause())}resume(){var t,s;this.isPaused&&!this.isStoped&&(this._cameraViewpointData&&this.ssp.setCameraViewpoint(this._cameraViewpointData),this.isPaused=!1,null===(t=this._positionTween)||void 0===t||t.resume(),null===(s=this._rotationTween)||void 0===s||s.resume())}stop(){this.isStoped||(this.patrolStop(),this.ssp.controls.reset(),this.ssp.controls.enabled=!0)}init(t){this.isPaused=!1,this.isStoped=!1,this.nextPointIndex=0,this.nodes=[...t.nodes]}initOptions(s){const{eyeHeight:i,naviSpeed:e,rotateSpeed:o,flyToStartPoint:n=!0,onUpdate:a,onProgress:h,onEnd:r}=s;i&&(this.options.eyeHeight=i),e&&(this.options.naviSpeed=e),o&&(this.options.rotateSpeed=o),this.options.flyToStartPoint=n,a&&(this.options.onUpdate=a),h&&(this.options.onProgress=h),r&&(this.options.onEnd=r),this._nodeDistances.length=0,this._nodeDistances.push(0),this._totalDistance=0;for(let s=0,i=this.nodes.length;s<i-1;s++){const i=this.nodes[s],e=this.nodes[s+1];if(i&&e){const s=i.getWorldPosition(new t),o=e.getWorldPosition(new t);s.y+=this.options.eyeHeight,o.y+=this.options.eyeHeight;const n=s.distanceTo(o);this._nodeDistances.push(n),this._totalDistance+=n}}}computedRotation(t,e){const o=new s;o.lookAt(t,e,this.camera.up);return(new i).setFromRotationMatrix(o)}computeNextRotation(s=this.nextPointIndex){var e,o;const n=null===(e=this.nodes[s])||void 0===e?void 0:e.getWorldPosition(new t),a=null===(o=this.nodes[s+1])||void 0===o?void 0:o.getWorldPosition(new t);return n&&a?this.computedRotation(n,a):new i}async patrolStart(){return new Promise(async s=>{var i;const{controls:o}=this.ssp,{onUpdate:n,onProgress:a,onEnd:h}=this.options;if(this.nextPointIndex>=this.nodes.length)null==h||h(this.camera.position.clone()),s(!0);else{if(this._needsUpdateProgress){let s=this._totalDistance*this._updatePercent;for(let i=0,e=this._nodeDistances.length;i<e;i++)if(s-=this._nodeDistances[i],s<0){this.nextPointIndex=i,s+=this._nodeDistances[i];const e=s/this._nodeDistances[i]||0,n=this.nodes[i-1],a=this.nodes[i],h=new t,r=n.getWorldPosition(new t),d=a.getWorldPosition(new t);r.y+=this.options.eyeHeight,d.y+=this.options.eyeHeight;const p=(new t).subVectors(d,r).multiplyScalar(e);h.copy(r).add(p),o.setPosition(h.x,h.y,h.z),o.setTarget(d.x,d.y,d.z);break}this._needsUpdateProgress=!1}const s=this.nodes[this.nextPointIndex],h=s.getWorldPosition(new t);h.setY(h.y+this.options.eyeHeight);const r=o.getPosition(new t).distanceTo(h);if(this.states.moveDuration=0===this.nextPointIndex?1e3:r/this.options.naviSpeed/.6,o.setTarget(h.x,h.y,h.z),0!==this.nextPointIndex||this.options.flyToStartPoint)try{await this.ssp.animation({distance:o.distance},{distance:e},{duration:this.states.moveDuration},({distance:i})=>{var e;if(this.isPaused)null===(e=this._positionTween)||void 0===e||e.pause();else if(o.dollyTo(i),null==n||n(o.getPosition(new t),s,i),this._nodeDistances[this.nextPointIndex]>0){let t=this._nodeDistances.slice(0,this.nextPointIndex+1).reduce((t,s)=>t+s,0);t-=i,null==a||a({patrolled:t,total:this._totalDistance,percent:t/this._totalDistance})}},t=>{this._positionTween=t})}catch(t){}else o.dollyTo(e);if(this.nextPointIndex<this.nodes.length-1){const s=this.computeNextRotation(),e=this.camera.quaternion.angleTo(s);this.states.rotateDuration=0===this.nextPointIndex?1e3:300*e/this.options.rotateSpeed;const n=o.getPosition(new t),a=null===(i=this.nodes[this.nextPointIndex+1])||void 0===i?void 0:i.getWorldPosition(new t);a.y+=this.options.eyeHeight;try{await this.ssp.animation({t:0},{t:1},{duration:this.states.rotateDuration},({t:t})=>{var s;if(this.isPaused)return void(null===(s=this._rotationTween)||void 0===s||s.pause());const i=h.clone().sub(n).normalize(),e=a.clone().sub(h).normalize(),{x:r,y:d,z:p}=i.lerp(e,t).add(h);o.setTarget(r,d,p)},t=>{this._rotationTween=t})}catch(t){}}this._needsUpdateProgress||this.nextPointIndex++,this.isStoped||await this.patrolStart()}})}patrolStop(){var t,s;this.options={naviSpeed:1,rotateSpeed:1,eyeHeight:150,flyToStartPoint:!0,onUpdate:()=>{},onProgress:()=>{},onEnd:()=>{}},this.nodes=[],this.nextPointIndex=0,this.isPaused=!1,this.isStoped=!0,this._needsUpdateProgress=!1,null===(t=this._positionTween)||void 0===t||t.stop(),null===(s=this._rotationTween)||void 0===s||s.stop(),this._positionTween=null,this._rotationTween=null}}export{o as default};
1
+ import { Vector3 as n, Matrix4 as S, Quaternion as f } from "three";
2
+ const m = 1e-5;
3
+ class T {
4
+ constructor(e) {
5
+ this.ssp = e;
6
+ const { cameraManager: t } = this.ssp.viewport;
7
+ this.camera = t.mainCamera;
8
+ }
9
+ camera;
10
+ options = {
11
+ naviSpeed: 1,
12
+ rotateSpeed: 1,
13
+ eyeHeight: 150,
14
+ flyToStartPoint: !0,
15
+ onUpdate: () => {
16
+ },
17
+ onProgress: () => {
18
+ },
19
+ onEnd: () => {
20
+ }
21
+ };
22
+ states = {
23
+ moveDuration: 0,
24
+ rotateDuration: 0
25
+ };
26
+ // 路径节点列表
27
+ nodes = [];
28
+ nextPointIndex = 0;
29
+ /**
30
+ * y 轴加上 eyeHeight 的节点之间距离
31
+ */
32
+ _nodeDistances = [];
33
+ _totalDistance = 0;
34
+ /**
35
+ * 0 - 1
36
+ */
37
+ _updatePercent = 0;
38
+ _needsUpdateProgress = !1;
39
+ isPaused = !1;
40
+ isStoped = !0;
41
+ _positionTween = null;
42
+ _rotationTween = null;
43
+ _cameraViewpointData = null;
44
+ /**
45
+ * 开始巡检
46
+ *
47
+ * @param path
48
+ * @param options
49
+ */
50
+ start(e, t) {
51
+ if (!this.isStoped) {
52
+ this.ssp.utils.warn("巡检已经开始!");
53
+ return;
54
+ }
55
+ this.ssp.controls.saveState(), this.ssp.controls.enabled = !1, this.init(e), this.initOptions(t), this.patrolStart();
56
+ }
57
+ /**
58
+ * 设置巡检进度
59
+ * @param percent 0 - 1(不包含 1)
60
+ */
61
+ setProgress(e) {
62
+ this._updatePercent = Math.min(Math.max(e, 0), 1), this._needsUpdateProgress = !0, this._positionTween?.stop(), this._rotationTween?.stop();
63
+ }
64
+ /**
65
+ * 设置巡检参数
66
+ * @param options
67
+ * @returns
68
+ */
69
+ setOptions(e) {
70
+ if (this.isStoped) return;
71
+ const { naviSpeed: t, rotateSpeed: o } = e;
72
+ if (t && this._positionTween) {
73
+ const r = this.states.moveDuration * this.options.naviSpeed / t;
74
+ this._positionTween.duration(r), this.states.moveDuration = r;
75
+ }
76
+ if (o && this._rotationTween) {
77
+ const r = this.states.rotateDuration * this.options.rotateSpeed / o;
78
+ this._rotationTween.duration(r), this.states.rotateDuration = r;
79
+ }
80
+ this.initOptions(e);
81
+ }
82
+ /**
83
+ * 暂停巡检
84
+ */
85
+ pause() {
86
+ this.isPaused || this.isStoped || (this._cameraViewpointData = this.ssp.getCameraViewpoint(), this.isPaused = !0, this._positionTween?.pause(), this._rotationTween?.pause());
87
+ }
88
+ /**
89
+ * 恢复巡检
90
+ */
91
+ resume() {
92
+ !this.isPaused || this.isStoped || (this._cameraViewpointData && this.ssp.setCameraViewpoint(this._cameraViewpointData), this.isPaused = !1, this._positionTween?.resume(), this._rotationTween?.resume());
93
+ }
94
+ /**
95
+ * 中断巡检
96
+ */
97
+ stop() {
98
+ this.isStoped || (this.patrolStop(), this.ssp.controls.reset(), this.ssp.controls.enabled = !0);
99
+ }
100
+ init(e) {
101
+ this.isPaused = !1, this.isStoped = !1, this.nextPointIndex = 0, this.nodes = [...e.nodes];
102
+ }
103
+ initOptions(e) {
104
+ const { eyeHeight: t, naviSpeed: o, rotateSpeed: r, flyToStartPoint: _ = !0, onUpdate: P, onProgress: a, onEnd: w } = e;
105
+ t && (this.options.eyeHeight = t), o && (this.options.naviSpeed = o), r && (this.options.rotateSpeed = r), this.options.flyToStartPoint = _, P && (this.options.onUpdate = P), a && (this.options.onProgress = a), w && (this.options.onEnd = w), this._nodeDistances.length = 0, this._nodeDistances.push(0), this._totalDistance = 0;
106
+ for (let s = 0, i = this.nodes.length; s < i - 1; s++) {
107
+ const p = this.nodes[s], h = this.nodes[s + 1];
108
+ if (p && h) {
109
+ const c = p.getWorldPosition(new n()), u = h.getWorldPosition(new n());
110
+ c.y += this.options.eyeHeight, u.y += this.options.eyeHeight;
111
+ const d = c.distanceTo(u);
112
+ this._nodeDistances.push(d), this._totalDistance += d;
113
+ }
114
+ }
115
+ }
116
+ /**
117
+ * 计算两点之间的弧度
118
+ * @param sourcePoint
119
+ * @param targetPoint
120
+ * @returns
121
+ */
122
+ computedRotation(e, t) {
123
+ const o = new S();
124
+ return o.lookAt(e, t, this.camera.up), new f().setFromRotationMatrix(o);
125
+ }
126
+ /**
127
+ * 计算下一弧度
128
+ * @returns
129
+ */
130
+ computeNextRotation(e = this.nextPointIndex) {
131
+ const t = this.nodes[e]?.getWorldPosition(new n()), o = this.nodes[e + 1]?.getWorldPosition(new n());
132
+ return t && o ? this.computedRotation(t, o) : new f();
133
+ }
134
+ /**
135
+ * 开始巡检
136
+ * @returns
137
+ */
138
+ async patrolStart() {
139
+ return new Promise(async (e) => {
140
+ const { controls: t } = this.ssp, {
141
+ onUpdate: o,
142
+ onProgress: r,
143
+ onEnd: _
144
+ } = this.options;
145
+ if (this.nextPointIndex >= this.nodes.length)
146
+ _?.(this.camera.position.clone()), e(!0);
147
+ else {
148
+ if (this._needsUpdateProgress) {
149
+ let s = this._totalDistance * this._updatePercent;
150
+ for (let i = 0, p = this._nodeDistances.length; i < p; i++)
151
+ if (s -= this._nodeDistances[i], s < 0) {
152
+ this.nextPointIndex = i, s += this._nodeDistances[i];
153
+ const h = s / this._nodeDistances[i] || 0, c = this.nodes[i - 1], u = this.nodes[i], d = new n(), x = c.getWorldPosition(new n()), l = u.getWorldPosition(new n());
154
+ x.y += this.options.eyeHeight, l.y += this.options.eyeHeight;
155
+ const g = new n().subVectors(l, x).multiplyScalar(h);
156
+ d.copy(x).add(g), t.setPosition(d.x, d.y, d.z), t.setTarget(l.x, l.y, l.z);
157
+ break;
158
+ }
159
+ this._needsUpdateProgress = !1;
160
+ }
161
+ const P = this.nodes[this.nextPointIndex], a = P.getWorldPosition(new n());
162
+ a.setY(a.y + this.options.eyeHeight);
163
+ const w = t.getPosition(new n()).distanceTo(a);
164
+ if (this.states.moveDuration = this.nextPointIndex === 0 ? 1e3 : w / this.options.naviSpeed / 0.6, t.setTarget(a.x, a.y, a.z), this.nextPointIndex === 0 && !this.options.flyToStartPoint)
165
+ t.dollyTo(m);
166
+ else
167
+ try {
168
+ await this.ssp.animation(
169
+ { distance: t.distance },
170
+ { distance: m },
171
+ {
172
+ duration: this.states.moveDuration
173
+ },
174
+ ({ distance: s }) => {
175
+ if (this.isPaused) {
176
+ this._positionTween?.pause();
177
+ return;
178
+ }
179
+ if (t.dollyTo(s), o?.(t.getPosition(new n()), P, s), this._nodeDistances[this.nextPointIndex] > 0) {
180
+ let i = this._nodeDistances.slice(0, this.nextPointIndex + 1).reduce((p, h) => p + h, 0);
181
+ i -= s, r?.({
182
+ patrolled: i,
183
+ total: this._totalDistance,
184
+ percent: i / this._totalDistance
185
+ });
186
+ }
187
+ },
188
+ (s) => {
189
+ this._positionTween = s;
190
+ }
191
+ );
192
+ } catch {
193
+ }
194
+ if (this.nextPointIndex < this.nodes.length - 1) {
195
+ const s = this.computeNextRotation(), i = this.camera.quaternion.angleTo(s);
196
+ this.states.rotateDuration = this.nextPointIndex === 0 ? 1e3 : i * 300 / this.options.rotateSpeed;
197
+ const p = t.getPosition(new n()), h = this.nodes[this.nextPointIndex + 1]?.getWorldPosition(new n());
198
+ h.y += this.options.eyeHeight;
199
+ try {
200
+ await this.ssp.animation(
201
+ { t: 0 },
202
+ { t: 1 },
203
+ {
204
+ duration: this.states.rotateDuration
205
+ },
206
+ ({ t: c }) => {
207
+ if (this.isPaused) {
208
+ this._rotationTween?.pause();
209
+ return;
210
+ }
211
+ const u = a.clone().sub(p).normalize(), d = h.clone().sub(a).normalize(), { x, y: l, z: g } = u.lerp(d, c).add(a);
212
+ t.setTarget(x, l, g);
213
+ },
214
+ (c) => {
215
+ this._rotationTween = c;
216
+ }
217
+ );
218
+ } catch {
219
+ }
220
+ }
221
+ this._needsUpdateProgress || this.nextPointIndex++, this.isStoped || await this.patrolStart();
222
+ }
223
+ });
224
+ }
225
+ patrolStop() {
226
+ this.options = {
227
+ naviSpeed: 1,
228
+ rotateSpeed: 1,
229
+ eyeHeight: 150,
230
+ flyToStartPoint: !0,
231
+ onUpdate: () => {
232
+ },
233
+ onProgress: () => {
234
+ },
235
+ onEnd: () => {
236
+ }
237
+ }, this.nodes = [], this.nextPointIndex = 0, this.isPaused = !1, this.isStoped = !0, this._needsUpdateProgress = !1, this._positionTween?.stop(), this._rotationTween?.stop(), this._positionTween = null, this._rotationTween = null;
238
+ }
239
+ }
240
+ export {
241
+ T as default
242
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@soonspacejs/plugin-patrol-controls",
3
3
  "pluginName": "PatrolControlsPlugin",
4
- "version": "2.13.17",
4
+ "version": "2.14.1",
5
5
  "description": "Patrol-controls 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": "8afa5fda9a0ef2c080060e7d8e71a8bf168fd4d2",
16
+ "gitHead": "27d5e0bcd79ff71c8e2943a8420c39624ae6f8e6",
17
17
  "peerDependencies": {
18
- "soonspacejs": "2.13.17"
18
+ "soonspacejs": "2.14.1"
19
19
  }
20
20
  }