@navaramap/three-plugins 0.0.5 → 0.0.7

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.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { EventHandler as e, MAPBOX_ELEVATION_DECODER as t, Plugin as n, TERRARIUM_ELEVATION_DECODER as r, convertWorldToScreen as i, degreeToRadian as a, eastNorthUpToFixedFrame as o, geodeticToVector3 as s, radianToDegree as c, vector3ToGeodetic as l } from "@navaramap/three";
2
- import { Matrix4 as u, Vector3 as d } from "three";
2
+ import { MathUtils as u, Matrix4 as d, Vector3 as f } from "three";
3
3
  //#region src/PersonViewPlugin.ts
4
- var f = {
4
+ var p = {
5
5
  x: 0,
6
6
  y: 0,
7
7
  z: 0
8
- }, p = {
8
+ }, m = {
9
9
  forward: ["KeyW"],
10
10
  backward: ["KeyS"],
11
11
  turnLeft: ["KeyA"],
@@ -19,12 +19,35 @@ var f = {
19
19
  dash: ["ShiftLeft", "ShiftRight"],
20
20
  orbitCamera: ["AltLeft", "AltRight"],
21
21
  toggleView: ["KeyV"]
22
- }, m = {
22
+ }, h = {
23
+ mode: "off",
24
+ groundOffset: 0,
25
+ alignToSlope: !0,
26
+ slopeSampleDistance: 4,
27
+ maxSlopeTilt: Math.PI / 4,
28
+ cameraSlopeFollow: 1
29
+ }, g = 10, _ = 6, v = Math.PI / 4, y = [
30
+ 0,
31
+ 1,
32
+ 2,
33
+ 3,
34
+ 4,
35
+ 5,
36
+ 6,
37
+ 7
38
+ ].map((e) => {
39
+ let t = e * Math.PI / 4;
40
+ return {
41
+ sin: Math.sin(t),
42
+ cos: Math.cos(t)
43
+ };
44
+ }), b = (e, t) => e > 0 && t > 0 ? 1 - Math.exp(-e * t) : 1, x = {
23
45
  allowCameraControl: !1,
24
46
  initialView: "tpv",
25
47
  moveSpeed: 50,
26
48
  rotationSpeed: 3,
27
49
  altSpeed: 30,
50
+ dashSpeedMultiplier: 2.5,
28
51
  minAlt: 50,
29
52
  maxAlt: 5e3,
30
53
  cameraDistance: 50,
@@ -37,20 +60,23 @@ var f = {
37
60
  startLng: 139.7671,
38
61
  startHeight: 500,
39
62
  startHeading: Math.PI * 1.3
40
- }, h = 3, g = 1e3, _ = class extends n {
63
+ }, S = 3, C = 1e3, w = class extends n {
41
64
  view;
42
65
  config;
66
+ collision;
43
67
  character;
44
68
  keys;
45
69
  keyToAction;
46
70
  handle = null;
47
71
  modelRef = null;
48
72
  animId = null;
73
+ placed = !1;
49
74
  lastTime = 0;
50
75
  state;
51
76
  listeners = /* @__PURE__ */ new Set();
77
+ actionListeners = /* @__PURE__ */ new Set();
52
78
  heldActions = /* @__PURE__ */ new Set();
53
- dashMultiplier = 1;
79
+ dashHeld = !1;
54
80
  orbitKeyHeld = !1;
55
81
  orbitLatched = !1;
56
82
  currentAnimState;
@@ -60,21 +86,33 @@ var f = {
60
86
  movementSuppressed = !1;
61
87
  boundKeyDown;
62
88
  boundKeyUp;
63
- _curPos = new d();
64
- _east = new d();
65
- _north = new d();
66
- _worldForward = new d();
67
- _offset = new d();
68
- _headingMatrix = new u();
69
- _characterFrame = new u();
89
+ _curPos = new f();
90
+ _east = new f();
91
+ _north = new f();
92
+ _worldForward = new f();
93
+ _offset = new f();
94
+ _probePos = new f();
95
+ _headingMatrix = new d();
96
+ _tiltMatrix = new d();
97
+ _characterFrame = new d();
98
+ cameraSlopePitch = 0;
99
+ slopeGradEast = 0;
100
+ slopeGradNorth = 0;
101
+ lastGroundSample;
102
+ unabsorbedGroundShift = 0;
103
+ settleVelocity = 0;
104
+ groundSurfaceHeight;
70
105
  constructor(e = {}) {
71
106
  super();
72
- let { character: t, keys: n, ...r } = e;
107
+ let { character: t, keys: n, collision: r, ...i } = e;
73
108
  this.config = {
74
- ...m,
109
+ ...x,
110
+ ...i
111
+ }, this.collision = {
112
+ ...h,
75
113
  ...r
76
114
  }, this.character = t ? this.resolveCharacter(t) : null, this.keys = {
77
- ...p,
115
+ ...m,
78
116
  ...n
79
117
  }, this.keyToAction = this.buildKeyMap(this.keys), this.modelHeading = this.config.startHeading, this.cameraHeading = this.config.startHeading, this.viewMode = this.config.initialView, this.currentAnimState = this.character ? this.character.animation.idleClip : null, this.boundKeyDown = this.onKeyDown.bind(this), this.boundKeyUp = this.onKeyUp.bind(this);
80
118
  }
@@ -91,7 +129,11 @@ var f = {
91
129
  }
92
130
  start() {
93
131
  if (!this.view || this.animId != null) return;
94
- this.animId = -1;
132
+ if (this.animId = -1, document.addEventListener("keydown", this.boundKeyDown), document.addEventListener("keyup", this.boundKeyUp), this.placed) {
133
+ this.resumeLoop(), this.placeChaseCamera(this.state.lat, this.state.lng, this.state.alt, this.cameraHeading), this.applyModelVisibility();
134
+ return;
135
+ }
136
+ this.placed = !0;
95
137
  let { startLat: e, startLng: t, startHeight: n, startHeading: r } = this.config, i = s({
96
138
  lat: a(e),
97
139
  lng: a(t),
@@ -107,7 +149,7 @@ var f = {
107
149
  animationEnabled: !0,
108
150
  animationAutoPlay: !0,
109
151
  animationActiveClip: e.idleClip,
110
- animationSpeed: e.speed,
152
+ animationSpeed: this.clipSpeed(e.idleClip),
111
153
  animationLoop: !0,
112
154
  animationCrossfadeDuration: e.crossfadeDuration
113
155
  },
@@ -123,27 +165,46 @@ var f = {
123
165
  z: n
124
166
  }
125
167
  }), this.modelRef = this.handle.ref, this.modelRef.on("load", () => {
126
- this.view && (this.lastTime = performance.now(), this.animId = requestAnimationFrame(this.tick));
168
+ !this.view || this.animId == null || this.resumeLoop();
127
169
  });
128
- } else this.lastTime = performance.now(), this.animId = requestAnimationFrame(this.tick);
129
- this.applyInitialCamera(), this.applyModelVisibility(), document.addEventListener("keydown", this.boundKeyDown), document.addEventListener("keyup", this.boundKeyUp);
170
+ } else this.resumeLoop();
171
+ this.applyInitialCamera(), this.applyModelVisibility();
172
+ }
173
+ stop() {
174
+ if (this.animId == null) return;
175
+ this.releaseControl(), this.view?.cameraFollow(!1), this.view?.cameraFreeLook(!1), this.playAnimation(this.character?.animation.idleClip);
176
+ let e = {
177
+ ...this.state,
178
+ speed: 0,
179
+ animationState: this.currentAnimState
180
+ };
181
+ this.hasStateChanged(this.state, e) && (this.state = e, this.notify());
182
+ }
183
+ releaseControl() {
184
+ this.animId != null && this.animId >= 0 && cancelAnimationFrame(this.animId), this.animId = null, document.removeEventListener("keydown", this.boundKeyDown), document.removeEventListener("keyup", this.boundKeyUp), this.heldActions.clear(), this.orbitKeyHeld = !1, this.orbitLatched = !1, this.dashHeld = !1;
185
+ }
186
+ resumeLoop() {
187
+ this.lastTime = performance.now(), this.animId = requestAnimationFrame(this.tick);
130
188
  }
131
189
  teleport(e) {
132
190
  if (!this.view) return;
133
- let { lng: t, lat: n, alt: r } = e, i = e.heading == null ? this.cameraHeading : e.heading;
134
- if (this.handle && this.character) {
191
+ let { lng: t, lat: n } = e, r = e.heading == null ? this.cameraHeading : e.heading, i = {
192
+ lat: a(n),
193
+ lng: a(t)
194
+ }, o = this.resolveGroundHeight(i, i, e.alt, 0);
195
+ if (this.updateSlopeTilt(i.lat, i.lng, o, 0), this.handle && this.character) {
135
196
  let e = s({
136
- lat: a(n),
137
- lng: a(t),
138
- height: r
197
+ lat: i.lat,
198
+ lng: i.lng,
199
+ height: o
139
200
  });
140
- this.handle.update({ matrixWorld: this.composeCharacterFrame(e, i) });
201
+ this.handle.update({ matrixWorld: this.composeCharacterFrame(e, r) });
141
202
  }
142
- this.modelHeading = i, this.cameraHeading = i, this.placeChaseCamera(n, t, r, i), this.state = {
203
+ this.modelHeading = r, this.cameraHeading = r, this.placeChaseCamera(n, t, o, r), this.state = {
143
204
  lng: t,
144
205
  lat: n,
145
- alt: r,
146
- heading: i,
206
+ alt: o,
207
+ heading: r,
147
208
  speed: 0,
148
209
  animationState: this.currentAnimState,
149
210
  mode: this.viewMode
@@ -155,6 +216,9 @@ var f = {
155
216
  onStateChange(e) {
156
217
  return this.listeners.add(e), () => this.listeners.delete(e);
157
218
  }
219
+ onAction(e) {
220
+ return this.actionListeners.add(e), () => this.actionListeners.delete(e);
221
+ }
158
222
  setViewMode(e) {
159
223
  this.viewMode !== e && (this.viewMode = e, this.state = {
160
224
  ...this.state,
@@ -167,6 +231,15 @@ var f = {
167
231
  setAllowCameraControl(e) {
168
232
  this.config.allowCameraControl = e;
169
233
  }
234
+ setCollision(e) {
235
+ this.collision = {
236
+ ...this.collision,
237
+ ...e
238
+ };
239
+ }
240
+ getCollision() {
241
+ return this.collision;
242
+ }
170
243
  setHeading(e) {
171
244
  if (!this.view) return;
172
245
  let { lat: t, lng: n, alt: r } = this.state;
@@ -204,18 +277,34 @@ var f = {
204
277
  getFpvHeightOffset() {
205
278
  return this.config.fpvHeightOffset;
206
279
  }
280
+ setAnimationSpeed(e) {
281
+ this.character && (this.character.animation.speed = e), this.modelRef?.setAnimationSpeed(this.clipSpeed(this.currentAnimState));
282
+ }
283
+ getAnimationSpeed() {
284
+ return this.character?.animation.speed ?? 1;
285
+ }
286
+ get model() {
287
+ return this.handle;
288
+ }
289
+ clipSpeed(e) {
290
+ let t = this.character?.animation;
291
+ return t ? e === t.dashClip ? t.dashSpeed ?? t.speed ?? 1 : t.walkClip != null && e === t.walkClip ? t.walkSpeed ?? t.speed ?? 1 : t.idleSpeed ?? t.speed ?? 1 : 1;
292
+ }
207
293
  dispose() {
208
- this.animId != null && cancelAnimationFrame(this.animId), this.animId = null, document.removeEventListener("keydown", this.boundKeyDown), document.removeEventListener("keyup", this.boundKeyUp), this.handle &&= (this.handle.delete(), null), this.modelRef = null, this.heldActions.clear(), this.listeners.clear(), this.orbitKeyHeld = !1, this.orbitLatched = !1, this.dashMultiplier = 1, this.view = void 0;
294
+ this.releaseControl(), this.handle &&= (this.handle.delete(), null), this.modelRef = null, this.placed = !1, this.listeners.clear(), this.actionListeners.clear(), this.view = void 0;
295
+ }
296
+ playAnimation(e) {
297
+ !e || !this.character || !this.modelRef || e !== this.currentAnimState && (this.modelRef.crossFadeAnimation(this.currentAnimState ?? "", e, this.character.animation.crossfadeDuration), this.modelRef.setAnimationSpeed(this.clipSpeed(e)), this.currentAnimState = e);
209
298
  }
210
299
  resolveCharacter(e) {
211
300
  return {
212
301
  modelUrl: e.modelUrl,
213
302
  animation: e.animation,
214
303
  modelRotationOffset: e.modelRotationOffset ? {
215
- ...f,
304
+ ...p,
216
305
  ...e.modelRotationOffset
217
- } : f,
218
- modelScale: e.modelScale ?? h,
306
+ } : p,
307
+ modelScale: e.modelScale ?? S,
219
308
  hideModelInFpv: e.hideModelInFpv ?? !0,
220
309
  castShadow: e.castShadow ?? !1,
221
310
  receiveShadow: e.receiveShadow ?? !1
@@ -242,28 +331,118 @@ var f = {
242
331
  let { startLat: e, startLng: t, startHeight: n, startHeading: r } = this.config;
243
332
  this.placeChaseCamera(e, t, n, r);
244
333
  }
245
- placeChaseCamera(e, t, n, r) {
334
+ placeChaseCamera(e, t, n, r, i = 0) {
246
335
  if (!this.view) return;
247
- let { cameraDistance: i, cameraPitch: a, fpvPitch: o, fpvHeightOffset: s, fpvForwardOffset: c } = this.config, l = this.viewMode === "fpv", u = n + s;
248
- if (l) {
249
- let n = g, i = c + g, a = Math.tan(o) * n, s = this.advanceLatLng(e, t, r, i);
250
- this._offset.set(-Math.sin(r) * n, -Math.cos(r) * n, a), this.view.cameraFollow(!0, {
251
- lat: s.lat,
252
- lng: s.lng,
253
- height: u - a
336
+ let { cameraDistance: a, fpvPitch: o, fpvForwardOffset: s } = this.config, c = this.viewMode === "fpv", l = this.eyeHeightAt(n);
337
+ if (c) {
338
+ let a = C, c = s + C, u = this.followSlopeWithPitch(o, e, t, n, r, i), d = Math.tan(u) * a, f = this.advanceLatLng(e, t, r, c);
339
+ this._offset.set(-Math.sin(r) * a, -Math.cos(r) * a, d), this.view.cameraFollow(!0, {
340
+ lat: f.lat,
341
+ lng: f.lng,
342
+ height: l - d
254
343
  }, this._offset);
255
344
  return;
256
345
  }
257
- let d = i * Math.cos(a), f = i * Math.sin(a);
346
+ let u = this.followSlopeWithPitch(this.config.cameraPitch, e, t, n, r, i), d = a * Math.cos(u), f = a * Math.sin(u);
258
347
  this._offset.set(-Math.sin(r) * d, -Math.cos(r) * d, f), this.view.cameraFollow(!0, {
259
348
  lat: e,
260
349
  lng: t,
261
- height: u
350
+ height: l
262
351
  }, this._offset);
263
352
  }
353
+ followSlopeWithPitch(e, t, n, r, i, a) {
354
+ let { cameraDistance: o, cameraLerpSpeed: s } = this.config, { mode: c, cameraSlopeFollow: l } = this.collision, d = 0;
355
+ if (c !== "off" && l > 0) {
356
+ let e = this.terrainAlong(t, n, i, o), a = this.terrainAlong(t, n, i + Math.PI, o);
357
+ e !== void 0 && a !== void 0 && (d = u.clamp(Math.atan2(e - a, 2 * o) * l * this.groundedFactor(r, o), -v, v));
358
+ }
359
+ return this.cameraSlopePitch += (d - this.cameraSlopePitch) * b(s, a), e - this.cameraSlopePitch;
360
+ }
361
+ groundedFactor(e, t) {
362
+ let n = this.groundSurfaceHeight;
363
+ return n === void 0 ? 0 : u.clamp(1 - (e - n) / t, 0, 1);
364
+ }
365
+ terrainAlong(e, t, n, r) {
366
+ let i = this.advanceLatLng(e, t, n, r);
367
+ return this.sampleTerrain(a(i.lat), a(i.lng));
368
+ }
264
369
  composeCharacterFrame(e, t) {
265
370
  let n = o(e);
266
- return this._headingMatrix.makeRotationZ(-t), this._characterFrame.multiplyMatrices(n, this._headingMatrix);
371
+ this._headingMatrix.makeRotationZ(-t), this._characterFrame.multiplyMatrices(n, this._headingMatrix);
372
+ let r = this.slopeGradEast, i = this.slopeGradNorth;
373
+ if (r !== 0 || i !== 0) {
374
+ let e = Math.sin(t), n = Math.cos(t), a = this.collision.maxSlopeTilt, o = u.clamp(Math.atan(r * e + i * n), -a, a), s = u.clamp(-Math.atan(r * n - i * e), -a, a);
375
+ this._tiltMatrix.makeRotationX(o), this._characterFrame.multiply(this._tiltMatrix), this._tiltMatrix.makeRotationY(s), this._characterFrame.multiply(this._tiltMatrix);
376
+ }
377
+ return this._characterFrame;
378
+ }
379
+ eyeHeightAt(e) {
380
+ return e + this.config.fpvHeightOffset;
381
+ }
382
+ sampleTerrain(e, t) {
383
+ return this.view?.sampleTerrainHeight({
384
+ lat: e,
385
+ lng: t
386
+ });
387
+ }
388
+ resolveGroundHeight(e, t, n, r) {
389
+ let { mode: i, groundOffset: a } = this.collision;
390
+ if (i === "off") return this.forgetGroundSamples(), n;
391
+ let o = this.sampleTerrain(e.lat, e.lng);
392
+ if (o === void 0) return this.forgetGroundSamples(), n;
393
+ this.groundSurfaceHeight = o + a;
394
+ let s = this.groundSurfaceHeight - this.absorbGroundDataShift(e, t, o, n, r);
395
+ return i === "ground" ? s : Math.max(n, s);
396
+ }
397
+ absorbGroundDataShift(e, t, n, r, i) {
398
+ let a = this.lastGroundSample, o;
399
+ if (a === void 0) o = (this.sampleTerrain(t.lat, t.lng) ?? n) + this.collision.groundOffset - r;
400
+ else {
401
+ let e = this.sampleTerrain(a.lat, a.lng);
402
+ o = e === void 0 ? 0 : e - a.height;
403
+ }
404
+ let s = this.unabsorbedGroundShift + o, c = Math.sign(s);
405
+ i > 0 && (c !== Math.sign(this.settleVelocity) && (this.settleVelocity = 0), this.settleVelocity += c * g * i);
406
+ let l = i > 0 ? Math.abs(this.settleVelocity) * i : Math.abs(s);
407
+ return this.unabsorbedGroundShift = c * Math.max(0, Math.abs(s) - l), this.unabsorbedGroundShift === 0 && (this.settleVelocity = 0), this.lastGroundSample = {
408
+ lat: e.lat,
409
+ lng: e.lng,
410
+ height: n
411
+ }, this.unabsorbedGroundShift;
412
+ }
413
+ forgetGroundSamples() {
414
+ this.lastGroundSample = void 0, this.unabsorbedGroundShift = 0, this.settleVelocity = 0, this.groundSurfaceHeight = void 0;
415
+ }
416
+ updateSlopeTilt(e, t, n, r) {
417
+ let { mode: i, alignToSlope: a, slopeSampleDistance: o } = this.collision, s = 0, c = 0;
418
+ if (i !== "off" && a) {
419
+ let r = this.measureSlopeGradient(e, t);
420
+ if (!r) return;
421
+ let i = this.groundedFactor(n, o);
422
+ s = r.east * i, c = r.north * i;
423
+ } else if (this.slopeGradEast === 0 && this.slopeGradNorth === 0) return;
424
+ let l = b(_, r);
425
+ this.slopeGradEast += (s - this.slopeGradEast) * l, this.slopeGradNorth += (c - this.slopeGradNorth) * l;
426
+ }
427
+ measureSlopeGradient(e, t) {
428
+ let n = this.collision.slopeSampleDistance, r = s({
429
+ lat: e,
430
+ lng: t,
431
+ height: 0
432
+ }), i = o(r);
433
+ this._east.setFromMatrixColumn(i, 0).normalize(), this._north.setFromMatrixColumn(i, 1).normalize();
434
+ let a = 0, c = 0;
435
+ for (let { sin: e, cos: t } of y) {
436
+ this._probePos.copy(r).addScaledVector(this._east, e * n).addScaledVector(this._north, t * n);
437
+ let i = l(this._probePos), o = this.sampleTerrain(i.lat, i.lng);
438
+ if (o === void 0) return;
439
+ a += o * e, c += o * t;
440
+ }
441
+ let u = 2 / (y.length * n);
442
+ return {
443
+ east: a * u,
444
+ north: c * u
445
+ };
267
446
  }
268
447
  advanceLatLng(e, t, n, r) {
269
448
  let i = s({
@@ -281,12 +460,15 @@ var f = {
281
460
  notify() {
282
461
  for (let e of this.listeners) e(this.state);
283
462
  }
463
+ emitAction(e) {
464
+ for (let t of this.actionListeners) t(e);
465
+ }
284
466
  onKeyDown(e) {
285
467
  let t = e.target;
286
468
  if (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable) return;
287
469
  let n = this.keyToAction.get(e.code);
288
470
  if (n !== void 0) {
289
- if (n === "toggleView") {
471
+ if (e.repeat || this.emitAction(n), n === "toggleView") {
290
472
  if (e.repeat) return;
291
473
  this.toggleViewMode();
292
474
  return;
@@ -297,7 +479,7 @@ var f = {
297
479
  }
298
480
  if (!this.movementSuppressed) {
299
481
  if (n === "dash") {
300
- this.dashMultiplier = 2.5;
482
+ this.dashHeld = !0;
301
483
  return;
302
484
  }
303
485
  this.isMovementAction(n) && (this.orbitLatched = !1), this.heldActions.add(n);
@@ -312,73 +494,73 @@ var f = {
312
494
  return;
313
495
  }
314
496
  if (t === "dash") {
315
- this.dashMultiplier = 1;
497
+ this.dashHeld = !1;
316
498
  return;
317
499
  }
318
500
  this.heldActions.delete(t);
319
501
  }
320
502
  }
321
503
  tick = (e) => {
322
- if (!this.view) return;
504
+ if (!this.view || this.animId == null) return;
323
505
  this.animId = requestAnimationFrame(this.tick);
324
506
  let t = Math.min((e - this.lastTime) / 1e3, .1);
325
507
  this.lastTime = e;
326
508
  let n = 0, r = 0, i = 0;
327
509
  this.heldActions.has("forward") && (r += 1), this.heldActions.has("backward") && --r, this.heldActions.has("turnLeft") && --n, this.heldActions.has("turnRight") && (n += 1), this.heldActions.has("ascend") && (i += 1), this.heldActions.has("descend") && --i;
328
- let { moveSpeed: u, rotationSpeed: d, altSpeed: f, minAlt: p, maxAlt: m, cameraLerpSpeed: h } = this.config;
329
- n !== 0 && (this.modelHeading += a(d * n));
330
- let g = this._curPos;
510
+ let { moveSpeed: d, rotationSpeed: f, altSpeed: p, minAlt: m, maxAlt: h, cameraLerpSpeed: g } = this.config, _ = this.dashHeld ? this.config.dashSpeedMultiplier : 1;
511
+ n !== 0 && (this.modelHeading += a(f * n));
512
+ let v = this._curPos;
331
513
  if (this.handle && this.modelRef) {
332
514
  let e = this.modelRef.getWorldPosition();
333
515
  if (!e) return;
334
- g.copy(e);
335
- } else g.copy(s({
516
+ v.copy(e);
517
+ } else v.copy(s({
336
518
  lat: a(this.state.lat),
337
519
  lng: a(this.state.lng),
338
520
  height: this.state.alt
339
521
  }));
340
- let _ = o(g);
341
- this._east.setFromMatrixColumn(_, 0).normalize(), this._north.setFromMatrixColumn(_, 1).normalize();
342
- let v = l(g);
343
- this._worldForward.copy(this._east).multiplyScalar(Math.sin(this.modelHeading)).addScaledVector(this._north, Math.cos(this.modelHeading)), r !== 0 && g.addScaledVector(this._worldForward, u * this.dashMultiplier * t * r);
344
- let y = l(g), b = v.height + i * f * t, x = Math.max(p, Math.min(m, b)), S = c(y.lat), C = c(y.lng), w = x;
345
- if (this.handle && this.character) {
522
+ let y = o(v);
523
+ this._east.setFromMatrixColumn(y, 0).normalize(), this._north.setFromMatrixColumn(y, 1).normalize();
524
+ let x = l(v);
525
+ this._worldForward.copy(this._east).multiplyScalar(Math.sin(this.modelHeading)).addScaledVector(this._north, Math.cos(this.modelHeading)), r !== 0 && v.addScaledVector(this._worldForward, d * _ * t * r);
526
+ let S = l(v), C = this.collision.mode === "ground" ? x.height : u.clamp(x.height + i * p * t, m, h), w = this.resolveGroundHeight(S, x, C, t), T = c(S.lat), E = c(S.lng), D = w;
527
+ if (this.updateSlopeTilt(S.lat, S.lng, w, t), this.handle && this.character) {
346
528
  let e = s({
347
- lat: y.lat,
348
- lng: y.lng,
349
- height: x
529
+ lat: S.lat,
530
+ lng: S.lng,
531
+ height: w
350
532
  });
351
533
  this.handle.update({ matrixWorld: this.composeCharacterFrame(e, this.modelHeading) });
352
534
  }
353
- let T = this.modelHeading - this.cameraHeading;
354
- if (T -= Math.round(T / (Math.PI * 2)) * (Math.PI * 2), this.cameraHeading += T * Math.min(t * h, 1), this.isFreeCamera()) if (this.viewMode === "fpv") {
355
- let e = this.advanceLatLng(S, C, this.cameraHeading, this.config.fpvForwardOffset);
535
+ let O = this.modelHeading - this.cameraHeading;
536
+ if (O -= Math.round(O / (Math.PI * 2)) * (Math.PI * 2), this.cameraHeading += O * b(g, t), this.isFreeCamera()) if (this.viewMode === "fpv") {
537
+ let e = this.advanceLatLng(T, E, this.cameraHeading, this.config.fpvForwardOffset);
356
538
  this.view.cameraFreeLook(!0, {
357
539
  lat: e.lat,
358
540
  lng: e.lng,
359
- height: w + this.config.fpvHeightOffset
541
+ height: this.eyeHeightAt(D)
360
542
  });
361
543
  } else this.view.cameraFollow(!0, {
362
- lat: S,
363
- lng: C,
364
- height: w + this.config.fpvHeightOffset
544
+ lat: T,
545
+ lng: E,
546
+ height: this.eyeHeightAt(D)
365
547
  });
366
- else this.placeChaseCamera(S, C, w, this.cameraHeading);
367
- let E = r !== 0 || n !== 0 || i !== 0, D = E && this.dashMultiplier > 1, O = this.currentAnimState;
368
- if (this.character && this.modelRef) {
369
- let { animation: e } = this.character, t = e.walkClip ?? e.idleClip, n;
370
- n = D ? e.dashClip : E ? t : e.idleClip, n !== this.currentAnimState && (this.modelRef.crossFadeAnimation(this.currentAnimState ?? "", n, e.crossfadeDuration), this.currentAnimState = n), O = n;
548
+ else this.placeChaseCamera(T, E, D, this.cameraHeading, t);
549
+ let k = r !== 0 || n !== 0 || i !== 0, A = k && this.dashHeld, j = this.currentAnimState;
550
+ if (this.character) {
551
+ let { animation: e } = this.character, t = e.walkClip ?? e.idleClip;
552
+ j = A ? e.dashClip : k ? t : e.idleClip, this.playAnimation(j);
371
553
  }
372
- let k = {
373
- lng: C,
374
- lat: S,
375
- alt: w,
554
+ let M = {
555
+ lng: E,
556
+ lat: T,
557
+ alt: D,
376
558
  heading: this.modelHeading,
377
- speed: u * this.dashMultiplier,
378
- animationState: O,
559
+ speed: d * _,
560
+ animationState: j,
379
561
  mode: this.viewMode
380
562
  };
381
- this.hasStateChanged(this.state, k) && (this.state = k, this.notify());
563
+ this.hasStateChanged(this.state, M) && (this.state = M, this.notify());
382
564
  };
383
565
  hasStateChanged(e, t) {
384
566
  return e.lng !== t.lng || e.lat !== t.lat || e.alt !== t.alt || e.heading !== t.heading || e.speed !== t.speed || e.animationState !== t.animationState || e.mode !== t.mode;
@@ -386,10 +568,10 @@ var f = {
386
568
  };
387
569
  //#endregion
388
570
  //#region src/OverlayPlugin.ts
389
- function v(e, t, n) {
571
+ function T(e, t, n) {
390
572
  e.style.transform = `translate(${t}px, ${n}px)`, e.style.willChange = "transform";
391
573
  }
392
- var y = 1e5, b = class extends n {
574
+ var E = 1e5, D = class extends n {
393
575
  view;
394
576
  maxDistance;
395
577
  positions = [];
@@ -397,7 +579,7 @@ var y = 1e5, b = class extends n {
397
579
  listeners = /* @__PURE__ */ new Set();
398
580
  boundHandler;
399
581
  constructor(e) {
400
- super(), this.maxDistance = e?.maxDistance ?? y, this.boundHandler = this.handlePreRender.bind(this);
582
+ super(), this.maxDistance = e?.maxDistance ?? E, this.boundHandler = this.handlePreRender.bind(this);
401
583
  }
402
584
  async init(e, t) {
403
585
  this.view = e, e.on("preRender", this.boundHandler);
@@ -451,7 +633,7 @@ var y = 1e5, b = class extends n {
451
633
  let r = { projected: this.projected };
452
634
  for (let e of this.listeners) e(r);
453
635
  }
454
- }, x = "https://api.cesium.com/v1/assets", S = class extends n {
636
+ }, O = "https://api.cesium.com/v1/assets", k = class extends n {
455
637
  view;
456
638
  config;
457
639
  endpoint;
@@ -460,7 +642,7 @@ var y = 1e5, b = class extends n {
460
642
  }
461
643
  async init(e, t) {
462
644
  this.view = e;
463
- let { assetId: n, accessToken: r, endpoint: i = x } = this.config, a = `${i}/${encodeURIComponent(String(n))}/endpoint?access_token=${encodeURIComponent(r)}`, o = await fetch(a);
645
+ let { assetId: n, accessToken: r, endpoint: i = O } = this.config, a = `${i}/${encodeURIComponent(String(n))}/endpoint?access_token=${encodeURIComponent(r)}`, o = await fetch(a);
464
646
  if (!o.ok) throw Error(`CesiumIonPlugin: failed to fetch asset ${n} endpoint (${o.status} ${o.statusText})`);
465
647
  let s = await o.json();
466
648
  this.endpoint = {
@@ -489,19 +671,19 @@ var y = 1e5, b = class extends n {
489
671
  });
490
672
  return l.once("deleted", () => c.delete()), l;
491
673
  }
492
- }, C = /^3\.\d+\.\d+$/, w = 512, T = "mapbox";
493
- function E(e) {
494
- if (typeof e.tilejson != "string" || !C.test(e.tilejson)) throw Error(`TileJsonPlugin: invalid or missing "tilejson" version field (got ${JSON.stringify(e.tilejson)}).`);
674
+ }, A = /^3\.\d+\.\d+$/, j = 512, M = "mapbox";
675
+ function N(e) {
676
+ if (typeof e.tilejson != "string" || !A.test(e.tilejson)) throw Error(`TileJsonPlugin: invalid or missing "tilejson" version field (got ${JSON.stringify(e.tilejson)}).`);
495
677
  if (!Array.isArray(e.tiles) || e.tiles.length === 0) throw Error("TileJsonPlugin: \"tiles\" must be a non-empty array of URL templates.");
496
678
  }
497
- function D(e) {
679
+ function P(e) {
498
680
  switch (e) {
499
681
  case "mapbox": return t();
500
682
  case "terrarium": return r();
501
683
  default: throw Error(`TileJsonPlugin: unsupported raster-dem encoding ${JSON.stringify(e)}. Supported encodings: "mapbox", "terrarium".`);
502
684
  }
503
685
  }
504
- var O = class extends n {
686
+ var F = class extends n {
505
687
  view;
506
688
  events = new e();
507
689
  credits = [];
@@ -521,7 +703,7 @@ var O = class extends n {
521
703
  let t = this.view;
522
704
  if (!t) throw Error("TileJsonPlugin: addSource() must be called after view.init().");
523
705
  let n = await this.fetchTileJson(e.url);
524
- E(n);
706
+ N(n);
525
707
  let [r, ...i] = n.tiles;
526
708
  i.length > 0 && console.warn(`TileJsonPlugin: TileJSON at ${e.url} lists ${n.tiles.length} mirror tile endpoints; Navara sources use a single URL, so only the first is used.`);
527
709
  let a = e.minzoom ?? n.minzoom, o = e.maxzoom ?? n.maxzoom, s = e.scheme ?? n.scheme, c = e.id, l = {
@@ -539,8 +721,8 @@ var O = class extends n {
539
721
  }) : e.type === "raster-dem" ? t.addSource({
540
722
  type: "raster-dem",
541
723
  ...u,
542
- tileSize: e.tileSize ?? n.tileSize ?? w,
543
- elevationDecoder: D(e.encoding ?? n.encoding ?? T)
724
+ tileSize: e.tileSize ?? n.tileSize ?? j,
725
+ elevationDecoder: P(e.encoding ?? n.encoding ?? M)
544
726
  }) : t.addSource({
545
727
  type: "vector-tile",
546
728
  ...l
@@ -564,4 +746,4 @@ var O = class extends n {
564
746
  }
565
747
  };
566
748
  //#endregion
567
- export { S as CesiumIonPlugin, b as OverlayPlugin, _ as PersonViewPlugin, O as TileJsonPlugin, v as moveOverlayElement };
749
+ export { k as CesiumIonPlugin, D as OverlayPlugin, w as PersonViewPlugin, F as TileJsonPlugin, T as moveOverlayElement };