@mml-io/3d-web-client-core 0.18.0 → 0.19.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/build/camera/CameraManager.d.ts +16 -18
- package/build/character/LocalController.d.ts +1 -9
- package/build/index.js +470 -418
- package/build/index.js.map +3 -3
- package/build/input/KeyInputManager.d.ts +11 -8
- package/build/input/VirtualJoystick.d.ts +28 -36
- package/build/mml/MMLCompositionScene.d.ts +2 -1
- package/build/rendering/composer.d.ts +11 -3
- package/build/tweakpane/TweakPane.d.ts +1 -1
- package/build/tweakpane/blades/cameraFolder.d.ts +0 -6
- package/package.json +5 -5
package/build/index.js
CHANGED
@@ -82,159 +82,6 @@ var EventHandlerCollection = class _EventHandlerCollection {
|
|
82
82
|
}
|
83
83
|
};
|
84
84
|
|
85
|
-
// src/input/VirtualJoystick.ts
|
86
|
-
var VirtualJoystick = class _VirtualJoystick {
|
87
|
-
constructor(holderElement, attrs) {
|
88
|
-
this.holderElement = holderElement;
|
89
|
-
this.left = false;
|
90
|
-
this.right = false;
|
91
|
-
this.up = false;
|
92
|
-
this.down = false;
|
93
|
-
this.hasDirection = false;
|
94
|
-
this.clearFlags = () => {
|
95
|
-
this.left = false;
|
96
|
-
this.right = false;
|
97
|
-
this.up = false;
|
98
|
-
this.down = false;
|
99
|
-
this.hasDirection = false;
|
100
|
-
this.control.style.left = `${this.width / 2 - this.inner_radius}px`;
|
101
|
-
this.control.style.top = `${this.height / 2 - this.inner_radius}px`;
|
102
|
-
};
|
103
|
-
this.radius = attrs.radius || 50;
|
104
|
-
this.inner_radius = attrs.inner_radius || this.radius / 2;
|
105
|
-
this.anchor = attrs.anchor || "left";
|
106
|
-
this.x = attrs.x || 0;
|
107
|
-
this.y = attrs.y || 0;
|
108
|
-
this.width = attrs.width || this.radius * 2 + this.inner_radius * 2;
|
109
|
-
this.height = attrs.height || this.radius * 2 + this.inner_radius * 2;
|
110
|
-
this.mouse_support = this.checkTouch() || attrs.mouse_support === true;
|
111
|
-
this.div = document.createElement("div");
|
112
|
-
const divStyle = this.div.style;
|
113
|
-
divStyle.display = this.checkTouch() || this.mouse_support ? "visible" : "none";
|
114
|
-
divStyle.position = "fixed";
|
115
|
-
if (this.anchor === "left") {
|
116
|
-
divStyle.left = `${this.x}px`;
|
117
|
-
} else {
|
118
|
-
divStyle.right = `${this.x}px`;
|
119
|
-
}
|
120
|
-
divStyle.bottom = `${this.y}px`;
|
121
|
-
divStyle.width = `${this.width}px`;
|
122
|
-
divStyle.height = `${this.height}px`;
|
123
|
-
divStyle.zIndex = "10000";
|
124
|
-
divStyle.overflow = "hidden";
|
125
|
-
this.holderElement.appendChild(this.div);
|
126
|
-
this.setupBaseAndControl();
|
127
|
-
this.bindEvents();
|
128
|
-
}
|
129
|
-
static checkForTouch() {
|
130
|
-
try {
|
131
|
-
document.createEvent("TouchEvent");
|
132
|
-
return true;
|
133
|
-
} catch (e) {
|
134
|
-
return false;
|
135
|
-
}
|
136
|
-
}
|
137
|
-
checkTouch() {
|
138
|
-
return _VirtualJoystick.checkForTouch();
|
139
|
-
}
|
140
|
-
setupBaseAndControl() {
|
141
|
-
this.base = document.createElement("span");
|
142
|
-
let divStyle = this.base.style;
|
143
|
-
divStyle.width = `${this.radius * 2}px`;
|
144
|
-
divStyle.height = `${this.radius * 2}px`;
|
145
|
-
divStyle.position = "absolute";
|
146
|
-
divStyle.left = `${this.width / 2 - this.radius}px`;
|
147
|
-
divStyle.bottom = `${this.height / 2 - this.radius}px`;
|
148
|
-
divStyle.borderRadius = "50%";
|
149
|
-
divStyle.borderColor = "rgba(200,200,200,0.5)";
|
150
|
-
divStyle.borderWidth = "2px";
|
151
|
-
divStyle.borderStyle = "solid";
|
152
|
-
this.div.appendChild(this.base);
|
153
|
-
this.control = document.createElement("span");
|
154
|
-
divStyle = this.control.style;
|
155
|
-
divStyle.width = `${this.inner_radius * 2}px`;
|
156
|
-
divStyle.height = `${this.inner_radius * 2}px`;
|
157
|
-
divStyle.position = "absolute";
|
158
|
-
divStyle.left = `${this.width / 2 - this.inner_radius}px`;
|
159
|
-
divStyle.bottom = `${this.height / 2 - this.inner_radius}px`;
|
160
|
-
divStyle.borderRadius = "50%";
|
161
|
-
divStyle.backgroundColor = "rgba(200,200,200,0.3)";
|
162
|
-
divStyle.borderWidth = "1px";
|
163
|
-
divStyle.borderColor = "rgba(200,200,200,0.8)";
|
164
|
-
divStyle.borderStyle = "solid";
|
165
|
-
this.div.appendChild(this.control);
|
166
|
-
}
|
167
|
-
bindEvents() {
|
168
|
-
this.div.addEventListener("touchstart", this.handleTouchStart.bind(this), false);
|
169
|
-
this.div.addEventListener("touchmove", this.handleTouchMove.bind(this), false);
|
170
|
-
this.div.addEventListener("touchend", this.clearFlags.bind(this), false);
|
171
|
-
if (this.mouse_support) {
|
172
|
-
this.div.addEventListener("mousedown", this.handleMouseDown.bind(this));
|
173
|
-
this.div.addEventListener("mousemove", this.handleMouseMove.bind(this));
|
174
|
-
this.div.addEventListener("mouseup", this.handleMouseUp.bind(this));
|
175
|
-
}
|
176
|
-
}
|
177
|
-
handleTouchStart(evt) {
|
178
|
-
evt.preventDefault();
|
179
|
-
evt.stopPropagation();
|
180
|
-
if (evt.touches) {
|
181
|
-
const touch = evt.touches[0];
|
182
|
-
this.updateControlAndDirection(touch);
|
183
|
-
}
|
184
|
-
}
|
185
|
-
handleTouchMove(evt) {
|
186
|
-
evt.preventDefault();
|
187
|
-
evt.stopPropagation();
|
188
|
-
if (evt.touches.length > 0) {
|
189
|
-
const touch = evt.touches[0];
|
190
|
-
this.updateControlAndDirection(touch);
|
191
|
-
}
|
192
|
-
}
|
193
|
-
handleMouseDown(evt) {
|
194
|
-
evt.preventDefault();
|
195
|
-
evt.stopPropagation();
|
196
|
-
this.updateControlAndDirection(evt);
|
197
|
-
}
|
198
|
-
handleMouseMove(evt) {
|
199
|
-
if (evt.buttons === 1) {
|
200
|
-
evt.preventDefault();
|
201
|
-
evt.stopPropagation();
|
202
|
-
this.updateControlAndDirection(evt);
|
203
|
-
}
|
204
|
-
}
|
205
|
-
handleMouseUp(evt) {
|
206
|
-
this.clearFlags();
|
207
|
-
}
|
208
|
-
updateControlAndDirection(input) {
|
209
|
-
const rect = this.div.getBoundingClientRect();
|
210
|
-
const dx = input.clientX - (rect.left + this.div.offsetWidth / 2);
|
211
|
-
const dy = input.clientY - (rect.top + this.div.offsetHeight / 2);
|
212
|
-
const distance = Math.min(Math.sqrt(dx * dx + dy * dy), this.radius);
|
213
|
-
const angle = Math.atan2(dy, dx);
|
214
|
-
const constrainedX = distance * Math.cos(angle);
|
215
|
-
const constrainedY = distance * Math.sin(angle);
|
216
|
-
this.control.style.left = `${constrainedX + this.width / 2 - this.inner_radius}px`;
|
217
|
-
this.control.style.top = `${constrainedY + this.height / 2 - this.inner_radius}px`;
|
218
|
-
this.up = this.isUp(dx, dy);
|
219
|
-
this.down = this.isDown(dx, dy);
|
220
|
-
this.left = this.isLeft(dx, dy);
|
221
|
-
this.right = this.isRight(dx, dy);
|
222
|
-
this.hasDirection = this.up || this.down || this.left || this.right;
|
223
|
-
}
|
224
|
-
isUp(dx, dy) {
|
225
|
-
return dy < 0 && Math.abs(dx) <= 2 * Math.abs(dy);
|
226
|
-
}
|
227
|
-
isDown(dx, dy) {
|
228
|
-
return dy > 0 && Math.abs(dx) <= 2 * Math.abs(dy);
|
229
|
-
}
|
230
|
-
isLeft(dx, dy) {
|
231
|
-
return dx < 0 && Math.abs(dy) <= 2 * Math.abs(dx);
|
232
|
-
}
|
233
|
-
isRight(dx, dy) {
|
234
|
-
return dx > 0 && Math.abs(dy) <= 2 * Math.abs(dx);
|
235
|
-
}
|
236
|
-
};
|
237
|
-
|
238
85
|
// src/tweakpane/blades/cameraFolder.ts
|
239
86
|
var camValues = {
|
240
87
|
initialDistance: 3.3,
|
@@ -244,10 +91,9 @@ var camValues = {
|
|
244
91
|
maxFOV: 70,
|
245
92
|
minFOV: 60,
|
246
93
|
invertFOVMapping: false,
|
247
|
-
damping: 0.
|
248
|
-
dampingScale: 5e-3,
|
94
|
+
damping: 0.25,
|
249
95
|
zoomScale: 0.088,
|
250
|
-
zoomDamping: 0.
|
96
|
+
zoomDamping: 0.4
|
251
97
|
};
|
252
98
|
var camOptions = {
|
253
99
|
initialDistance: { min: 1, max: 5, step: 0.1 },
|
@@ -256,8 +102,7 @@ var camOptions = {
|
|
256
102
|
initialFOV: { min: 60, max: 85, step: 1 },
|
257
103
|
maxFOV: { min: 50, max: 100, step: 1 },
|
258
104
|
minFOV: { min: 50, max: 100, step: 1 },
|
259
|
-
damping: { min: 0.01, max:
|
260
|
-
dampingScale: { min: 1e-3, max: 0.02, step: 1e-3 },
|
105
|
+
damping: { min: 0.01, max: 1, step: 1e-3 },
|
261
106
|
zoomScale: { min: 5e-3, max: 0.3, step: 1e-3 },
|
262
107
|
zoomDamping: { min: 0, max: 2, step: 0.01 }
|
263
108
|
};
|
@@ -277,7 +122,6 @@ var CameraFolder = class {
|
|
277
122
|
this.folder.addBinding(camValues, "maxFOV", camOptions.maxFOV);
|
278
123
|
this.folder.addBinding({ invertFOVMapping: camValues.invertFOVMapping }, "invertFOVMapping");
|
279
124
|
this.folder.addBinding(camValues, "damping", camOptions.damping);
|
280
|
-
this.folder.addBinding(camValues, "dampingScale", camOptions.dampingScale);
|
281
125
|
this.folder.addBinding(camValues, "zoomScale", camOptions.zoomScale);
|
282
126
|
this.folder.addBinding(camValues, "zoomDamping", camOptions.zoomDamping);
|
283
127
|
}
|
@@ -326,20 +170,16 @@ var CameraFolder = class {
|
|
326
170
|
cameraManager.recomputeFoV();
|
327
171
|
break;
|
328
172
|
}
|
329
|
-
case "invertFOVMapping":
|
173
|
+
case "invertFOVMapping": {
|
330
174
|
const boolValue = e.value;
|
331
175
|
cameraManager.invertFOVMapping = boolValue;
|
332
176
|
break;
|
177
|
+
}
|
333
178
|
case "damping": {
|
334
179
|
const value = e.value;
|
335
180
|
cameraManager.damping = value;
|
336
181
|
break;
|
337
182
|
}
|
338
|
-
case "dampingScale": {
|
339
|
-
const value = e.value;
|
340
|
-
cameraManager.dampingScale = value;
|
341
|
-
break;
|
342
|
-
}
|
343
183
|
case "zoomScale": {
|
344
184
|
const value = e.value;
|
345
185
|
cameraManager.zoomScale = value;
|
@@ -371,124 +211,114 @@ function getTweakpaneActive() {
|
|
371
211
|
}
|
372
212
|
|
373
213
|
// src/camera/CameraManager.ts
|
214
|
+
var cameraPanSensitivity = 20;
|
215
|
+
var scrollZoomSensitivity = 0.1;
|
216
|
+
var pinchZoomSensitivity = 0.025;
|
374
217
|
var CameraManager = class {
|
375
218
|
constructor(targetElement, collisionsManager, initialPhi = Math.PI / 2, initialTheta = -Math.PI / 2) {
|
219
|
+
this.targetElement = targetElement;
|
376
220
|
this.collisionsManager = collisionsManager;
|
377
221
|
this.initialDistance = camValues.initialDistance;
|
378
222
|
this.minDistance = camValues.minDistance;
|
379
223
|
this.maxDistance = camValues.maxDistance;
|
380
|
-
this.initialFOV = camValues.initialFOV;
|
381
|
-
this.maxFOV = camValues.maxFOV;
|
382
|
-
this.minFOV = camValues.minFOV;
|
383
224
|
this.damping = camValues.damping;
|
384
|
-
this.dampingScale = 0.01;
|
385
225
|
this.zoomScale = camValues.zoomScale;
|
386
226
|
this.zoomDamping = camValues.zoomDamping;
|
227
|
+
this.initialFOV = camValues.initialFOV;
|
228
|
+
this.maxFOV = camValues.maxFOV;
|
229
|
+
this.minFOV = camValues.minFOV;
|
387
230
|
this.invertFOVMapping = camValues.invertFOVMapping;
|
388
231
|
this.fov = this.initialFOV;
|
389
232
|
this.targetFOV = this.initialFOV;
|
390
233
|
this.minPolarAngle = Math.PI * 0.25;
|
391
234
|
this.maxPolarAngle = Math.PI * 0.95;
|
392
|
-
this.targetDistance = this.initialDistance;
|
393
235
|
this.distance = this.initialDistance;
|
236
|
+
this.targetDistance = this.initialDistance;
|
394
237
|
this.desiredDistance = this.initialDistance;
|
395
|
-
this.phi = Math.PI / 2;
|
396
|
-
this.theta = Math.PI / 2;
|
397
|
-
this.dragging = false;
|
398
238
|
this.target = new Vector32(0, 1.55, 0);
|
399
239
|
this.hadTarget = false;
|
400
|
-
this.isLerping = false;
|
401
240
|
this.finalTarget = new Vector32();
|
241
|
+
this.isLerping = false;
|
402
242
|
this.lerpTarget = new Vector32();
|
403
243
|
this.lerpFactor = 0;
|
404
244
|
this.lerpDuration = 2.1;
|
405
|
-
this.
|
406
|
-
this.
|
407
|
-
this.lastTouchY = 0;
|
245
|
+
this.activePointers = /* @__PURE__ */ new Map();
|
246
|
+
this.targetElement.style.touchAction = "pinch-zoom";
|
408
247
|
this.phi = initialPhi;
|
409
|
-
this.targetPhi =
|
248
|
+
this.targetPhi = this.phi;
|
410
249
|
this.theta = initialTheta;
|
411
|
-
this.targetTheta =
|
250
|
+
this.targetTheta = this.theta;
|
412
251
|
this.camera = new PerspectiveCamera(this.fov, window.innerWidth / window.innerHeight, 0.1, 400);
|
413
252
|
this.camera.position.set(0, 1.4, -this.initialDistance);
|
414
253
|
this.rayCaster = new Raycaster();
|
415
|
-
this.hasTouchControl = VirtualJoystick.checkForTouch();
|
416
254
|
this.eventHandlerCollection = EventHandlerCollection.create([
|
417
|
-
[targetElement, "
|
418
|
-
[
|
419
|
-
[document, "
|
255
|
+
[targetElement, "pointerdown", this.onPointerDown.bind(this)],
|
256
|
+
[targetElement, "gesturestart", this.preventDefaultAndStopPropagation.bind(this)],
|
257
|
+
[document, "pointerup", this.onPointerUp.bind(this)],
|
258
|
+
[document, "pointercancel", this.onPointerUp.bind(this)],
|
259
|
+
[document, "pointermove", this.onPointerMove.bind(this)],
|
420
260
|
[targetElement, "wheel", this.onMouseWheel.bind(this)],
|
421
261
|
[targetElement, "contextmenu", this.onContextMenu.bind(this)]
|
422
262
|
]);
|
423
|
-
if (this.hasTouchControl) {
|
424
|
-
this.eventHandlerCollection.add(targetElement, "touchstart", this.onTouchStart.bind(this), {
|
425
|
-
passive: false
|
426
|
-
});
|
427
|
-
this.eventHandlerCollection.add(document, "touchmove", this.onTouchMove.bind(this), {
|
428
|
-
passive: false
|
429
|
-
});
|
430
|
-
this.eventHandlerCollection.add(document, "touchend", this.onTouchEnd.bind(this), {
|
431
|
-
passive: false
|
432
|
-
});
|
433
|
-
}
|
434
|
-
}
|
435
|
-
setupTweakPane(tweakPane) {
|
436
|
-
tweakPane.setupCamPane(this);
|
437
|
-
}
|
438
|
-
onTouchStart(evt) {
|
439
|
-
Array.from(evt.touches).forEach((touch) => {
|
440
|
-
this.dragging = true;
|
441
|
-
this.lastTouchX = touch.clientX;
|
442
|
-
this.lastTouchY = touch.clientY;
|
443
|
-
});
|
444
263
|
}
|
445
|
-
|
446
|
-
if (!this.dragging || getTweakpaneActive()) {
|
447
|
-
return;
|
448
|
-
}
|
264
|
+
preventDefaultAndStopPropagation(evt) {
|
449
265
|
evt.preventDefault();
|
450
|
-
|
451
|
-
if (touch) {
|
452
|
-
const dx = touch.clientX - this.lastTouchX;
|
453
|
-
const dy = touch.clientY - this.lastTouchY;
|
454
|
-
this.lastTouchX = touch.clientX;
|
455
|
-
this.lastTouchY = touch.clientY;
|
456
|
-
if (this.targetTheta !== null && this.targetPhi !== null) {
|
457
|
-
this.targetTheta += dx * this.dampingScale;
|
458
|
-
this.targetPhi -= dy * this.dampingScale;
|
459
|
-
this.targetPhi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.targetPhi));
|
460
|
-
}
|
461
|
-
}
|
266
|
+
evt.stopPropagation();
|
462
267
|
}
|
463
|
-
|
464
|
-
|
465
|
-
const touchEnded = Array.from(evt.changedTouches).some((t) => true);
|
466
|
-
if (touchEnded) {
|
467
|
-
this.dragging = false;
|
468
|
-
}
|
469
|
-
}
|
268
|
+
setupTweakPane(tweakPane) {
|
269
|
+
tweakPane.setupCamPane(this);
|
470
270
|
}
|
471
|
-
|
271
|
+
onPointerDown(event) {
|
472
272
|
if (event.button === 0 || event.button === 2) {
|
473
|
-
|
273
|
+
const pointerInfo = { x: event.clientX, y: event.clientY };
|
274
|
+
this.activePointers.set(event.pointerId, pointerInfo);
|
474
275
|
document.body.style.cursor = "none";
|
475
276
|
}
|
476
277
|
}
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
278
|
+
onPointerUp(event) {
|
279
|
+
const existingPointer = this.activePointers.get(event.pointerId);
|
280
|
+
if (existingPointer) {
|
281
|
+
this.activePointers.delete(event.pointerId);
|
282
|
+
if (this.activePointers.size === 0) {
|
283
|
+
document.body.style.cursor = "default";
|
284
|
+
}
|
481
285
|
}
|
482
286
|
}
|
483
|
-
|
287
|
+
getAveragePointerPositionAndSpread() {
|
288
|
+
const existingSum = { x: 0, y: 0 };
|
289
|
+
this.activePointers.forEach((p) => {
|
290
|
+
existingSum.x += p.x;
|
291
|
+
existingSum.y += p.y;
|
292
|
+
});
|
293
|
+
const aX = existingSum.x / this.activePointers.size;
|
294
|
+
const aY = existingSum.y / this.activePointers.size;
|
295
|
+
let sumOfDistances = 0;
|
296
|
+
this.activePointers.forEach((p) => {
|
297
|
+
const distance = Math.sqrt((p.x - aX) ** 2 + (p.y - aY) ** 2);
|
298
|
+
sumOfDistances += distance;
|
299
|
+
});
|
300
|
+
return { pos: { x: aX, y: aY }, spread: sumOfDistances / this.activePointers.size };
|
301
|
+
}
|
302
|
+
onPointerMove(event) {
|
484
303
|
if (getTweakpaneActive()) {
|
485
304
|
return;
|
486
305
|
}
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
306
|
+
const existingPointer = this.activePointers.get(event.pointerId);
|
307
|
+
if (existingPointer) {
|
308
|
+
const previous = this.getAveragePointerPositionAndSpread();
|
309
|
+
existingPointer.x = event.clientX;
|
310
|
+
existingPointer.y = event.clientY;
|
311
|
+
const latest = this.getAveragePointerPositionAndSpread();
|
312
|
+
const sX = latest.pos.x - previous.pos.x;
|
313
|
+
const sY = latest.pos.y - previous.pos.y;
|
314
|
+
const dx = sX / this.targetElement.clientWidth * cameraPanSensitivity;
|
315
|
+
const dy = sY / this.targetElement.clientHeight * cameraPanSensitivity;
|
316
|
+
if (this.activePointers.size > 1) {
|
317
|
+
const zoomDelta = latest.spread - previous.spread;
|
318
|
+
this.zoom(-zoomDelta * pinchZoomSensitivity);
|
319
|
+
}
|
320
|
+
this.targetTheta += dx;
|
321
|
+
this.targetPhi -= dy;
|
492
322
|
this.targetPhi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.targetPhi));
|
493
323
|
event.preventDefault();
|
494
324
|
}
|
@@ -497,14 +327,17 @@ var CameraManager = class {
|
|
497
327
|
if (getTweakpaneActive()) {
|
498
328
|
return;
|
499
329
|
}
|
500
|
-
|
501
|
-
this.
|
330
|
+
event.preventDefault();
|
331
|
+
const scrollAmount = event.deltaY * this.zoomScale * scrollZoomSensitivity;
|
332
|
+
this.zoom(scrollAmount);
|
333
|
+
}
|
334
|
+
zoom(delta) {
|
335
|
+
this.targetDistance += delta;
|
502
336
|
this.targetDistance = Math.max(
|
503
337
|
this.minDistance,
|
504
338
|
Math.min(this.maxDistance, this.targetDistance)
|
505
339
|
);
|
506
340
|
this.desiredDistance = this.targetDistance;
|
507
|
-
event.preventDefault();
|
508
341
|
}
|
509
342
|
onContextMenu(event) {
|
510
343
|
event.preventDefault();
|
@@ -533,12 +366,12 @@ var CameraManager = class {
|
|
533
366
|
const dy = this.camera.position.y - this.target.y;
|
534
367
|
const dz = this.camera.position.z - this.target.z;
|
535
368
|
this.targetDistance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
536
|
-
this.targetTheta = Math.atan2(dz, dx);
|
537
|
-
this.targetPhi = Math.acos(dy / this.targetDistance);
|
538
|
-
this.phi = this.targetPhi;
|
539
|
-
this.theta = this.targetTheta;
|
540
369
|
this.distance = this.targetDistance;
|
541
370
|
this.desiredDistance = this.targetDistance;
|
371
|
+
this.theta = Math.atan2(dz, dx);
|
372
|
+
this.targetTheta = this.theta;
|
373
|
+
this.phi = Math.acos(dy / this.targetDistance);
|
374
|
+
this.targetPhi = this.phi;
|
542
375
|
this.recomputeFoV(true);
|
543
376
|
}
|
544
377
|
adjustCameraPosition() {
|
@@ -546,19 +379,20 @@ var CameraManager = class {
|
|
546
379
|
const offset = new Vector32(0, 0, offsetDistance);
|
547
380
|
offset.applyEuler(this.camera.rotation);
|
548
381
|
const rayOrigin = this.camera.position.clone().add(offset);
|
549
|
-
const rayDirection = this.target.clone()
|
550
|
-
this.rayCaster.set(
|
382
|
+
const rayDirection = rayOrigin.sub(this.target.clone()).normalize();
|
383
|
+
this.rayCaster.set(this.target.clone(), rayDirection);
|
551
384
|
const firstRaycastHit = this.collisionsManager.raycastFirst(this.rayCaster.ray);
|
552
|
-
|
553
|
-
|
554
|
-
this.targetDistance =
|
555
|
-
this.distance =
|
385
|
+
if (firstRaycastHit !== null && firstRaycastHit[0] <= this.desiredDistance) {
|
386
|
+
const distanceToCollision = firstRaycastHit[0] - 0.1;
|
387
|
+
this.targetDistance = distanceToCollision;
|
388
|
+
this.distance = distanceToCollision;
|
556
389
|
} else {
|
557
|
-
this.targetDistance
|
390
|
+
this.targetDistance = this.desiredDistance;
|
558
391
|
}
|
559
392
|
}
|
560
393
|
dispose() {
|
561
394
|
this.eventHandlerCollection.clear();
|
395
|
+
document.body.style.cursor = "";
|
562
396
|
}
|
563
397
|
easeOutExpo(x) {
|
564
398
|
return x === 1 ? 1 : 1 - Math.pow(2, -10 * x);
|
@@ -586,24 +420,25 @@ var CameraManager = class {
|
|
586
420
|
} else {
|
587
421
|
this.adjustCameraPosition();
|
588
422
|
}
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
this.isLerping = false;
|
604
|
-
}
|
423
|
+
this.distance += (this.targetDistance - this.distance) * this.zoomDamping;
|
424
|
+
this.theta += (this.targetTheta - this.theta) * this.damping;
|
425
|
+
this.phi += (this.targetPhi - this.phi) * this.damping;
|
426
|
+
const x = this.target.x + this.distance * Math.sin(this.phi) * Math.cos(this.theta);
|
427
|
+
const y = this.target.y + this.distance * Math.cos(this.phi);
|
428
|
+
const z = this.target.z + this.distance * Math.sin(this.phi) * Math.sin(this.theta);
|
429
|
+
this.recomputeFoV();
|
430
|
+
this.fov += (this.targetFOV - this.fov) * this.zoomDamping;
|
431
|
+
this.camera.fov = this.fov;
|
432
|
+
this.camera.updateProjectionMatrix();
|
433
|
+
this.camera.position.set(x, y, z);
|
434
|
+
this.camera.lookAt(this.target);
|
435
|
+
if (this.isLerping && this.lerpFactor >= 1) {
|
436
|
+
this.isLerping = false;
|
605
437
|
}
|
606
438
|
}
|
439
|
+
hasActiveInput() {
|
440
|
+
return this.activePointers.size > 0;
|
441
|
+
}
|
607
442
|
};
|
608
443
|
|
609
444
|
// src/character/Character.ts
|
@@ -1480,6 +1315,9 @@ var Character = class extends Group {
|
|
1480
1315
|
}
|
1481
1316
|
async load() {
|
1482
1317
|
const previousModel = this.model;
|
1318
|
+
if (previousModel && previousModel.mesh) {
|
1319
|
+
this.remove(previousModel.mesh);
|
1320
|
+
}
|
1483
1321
|
this.model = new CharacterModel({
|
1484
1322
|
characterDescription: this.config.characterDescription,
|
1485
1323
|
animationConfig: this.config.animationConfig,
|
@@ -1489,9 +1327,6 @@ var Character = class extends Group {
|
|
1489
1327
|
isLocal: this.config.isLocal
|
1490
1328
|
});
|
1491
1329
|
await this.model.init();
|
1492
|
-
if (previousModel && previousModel.mesh) {
|
1493
|
-
this.remove(previousModel.mesh);
|
1494
|
-
}
|
1495
1330
|
this.add(this.model.mesh);
|
1496
1331
|
if (this.speakingIndicator === null) {
|
1497
1332
|
this.speakingIndicator = new CharacterSpeakingIndicator(this.config.composer.postPostScene);
|
@@ -1769,6 +1604,7 @@ var LocalController = class {
|
|
1769
1604
|
this.jumpPressed = false;
|
1770
1605
|
// Tracks if the jump button is pressed
|
1771
1606
|
this.jumpReleased = true;
|
1607
|
+
this.controlState = null;
|
1772
1608
|
this.networkState = {
|
1773
1609
|
id: this.config.id,
|
1774
1610
|
position: { x: 0, y: 0, z: 0 },
|
@@ -1776,35 +1612,22 @@ var LocalController = class {
|
|
1776
1612
|
state: 0 /* idle */
|
1777
1613
|
};
|
1778
1614
|
}
|
1779
|
-
updateControllerState() {
|
1780
|
-
var _a, _b, _c, _d, _e;
|
1781
|
-
this.forward = this.config.keyInputManager.forward || ((_a = this.config.virtualJoystick) == null ? void 0 : _a.up) || false;
|
1782
|
-
this.backward = this.config.keyInputManager.backward || ((_b = this.config.virtualJoystick) == null ? void 0 : _b.down) || false;
|
1783
|
-
this.left = this.config.keyInputManager.left || ((_c = this.config.virtualJoystick) == null ? void 0 : _c.left) || false;
|
1784
|
-
this.right = this.config.keyInputManager.right || ((_d = this.config.virtualJoystick) == null ? void 0 : _d.right) || false;
|
1785
|
-
this.run = this.config.keyInputManager.run;
|
1786
|
-
this.jump = this.config.keyInputManager.jump;
|
1787
|
-
this.anyDirection = this.config.keyInputManager.anyDirection || ((_e = this.config.virtualJoystick) == null ? void 0 : _e.hasDirection) || false;
|
1788
|
-
this.conflictingDirections = this.config.keyInputManager.conflictingDirection;
|
1789
|
-
if (!this.jump) {
|
1790
|
-
this.jumpReleased = true;
|
1791
|
-
}
|
1792
|
-
}
|
1793
1615
|
update() {
|
1794
|
-
|
1616
|
+
var _a, _b;
|
1617
|
+
this.controlState = this.config.keyInputManager.getOutput() || ((_a = this.config.virtualJoystick) == null ? void 0 : _a.getOutput()) || null;
|
1795
1618
|
this.rayCaster.set(this.config.character.position, this.vectorDown);
|
1796
1619
|
const firstRaycastHit = this.config.collisionsManager.raycastFirst(this.rayCaster.ray);
|
1797
1620
|
if (firstRaycastHit !== null) {
|
1798
1621
|
this.currentHeight = firstRaycastHit[0];
|
1799
1622
|
this.currentSurfaceAngle.copy(firstRaycastHit[1]);
|
1800
1623
|
}
|
1801
|
-
if (this.
|
1624
|
+
if (((_b = this.controlState) == null ? void 0 : _b.direction) !== null || !this.characterOnGround) {
|
1802
1625
|
const targetAnimation = this.getTargetAnimation();
|
1803
1626
|
this.config.character.updateAnimation(targetAnimation);
|
1804
1627
|
} else {
|
1805
1628
|
this.config.character.updateAnimation(0 /* idle */);
|
1806
1629
|
}
|
1807
|
-
if (this.
|
1630
|
+
if (this.controlState) {
|
1808
1631
|
this.updateRotation();
|
1809
1632
|
}
|
1810
1633
|
for (let i = 0; i < this.collisionDetectionSteps; i++) {
|
@@ -1829,30 +1652,17 @@ var LocalController = class {
|
|
1829
1652
|
}
|
1830
1653
|
return 4 /* air */;
|
1831
1654
|
}
|
1832
|
-
if (this.
|
1655
|
+
if (!this.controlState) {
|
1833
1656
|
return 0 /* idle */;
|
1834
1657
|
}
|
1835
|
-
|
1658
|
+
if (this.controlState.isSprinting) {
|
1659
|
+
return 2 /* running */;
|
1660
|
+
}
|
1661
|
+
return 1 /* walking */;
|
1836
1662
|
}
|
1837
1663
|
updateRotationOffset() {
|
1838
|
-
if (this.
|
1839
|
-
|
1840
|
-
if (this.forward) {
|
1841
|
-
this.rotationOffset = Math.PI;
|
1842
|
-
if (this.left)
|
1843
|
-
this.rotationOffset = Math.PI + Math.PI / 4;
|
1844
|
-
if (this.right)
|
1845
|
-
this.rotationOffset = Math.PI - Math.PI / 4;
|
1846
|
-
} else if (this.backward) {
|
1847
|
-
this.rotationOffset = Math.PI * 2;
|
1848
|
-
if (this.left)
|
1849
|
-
this.rotationOffset = -Math.PI * 2 - Math.PI / 4;
|
1850
|
-
if (this.right)
|
1851
|
-
this.rotationOffset = Math.PI * 2 + Math.PI / 4;
|
1852
|
-
} else if (this.left) {
|
1853
|
-
this.rotationOffset = Math.PI * -0.5;
|
1854
|
-
} else if (this.right) {
|
1855
|
-
this.rotationOffset = Math.PI * 0.5;
|
1664
|
+
if (this.controlState && this.controlState.direction !== null) {
|
1665
|
+
this.rotationOffset = this.controlState.direction;
|
1856
1666
|
}
|
1857
1667
|
}
|
1858
1668
|
updateAzimuthalAngle() {
|
@@ -1887,17 +1697,19 @@ var LocalController = class {
|
|
1887
1697
|
this.config.character.quaternion.rotateTowards(rotationQuaternion, frameRotation);
|
1888
1698
|
}
|
1889
1699
|
processJump(currentAcceleration, deltaTime) {
|
1700
|
+
var _a;
|
1701
|
+
const jump = (_a = this.controlState) == null ? void 0 : _a.jump;
|
1890
1702
|
if (this.characterOnGround) {
|
1891
1703
|
this.coyoteJumped = false;
|
1892
1704
|
this.canDoubleJump = false;
|
1893
1705
|
this.doubleJumpUsed = false;
|
1894
1706
|
this.jumpCounter = 0;
|
1895
|
-
if (!
|
1707
|
+
if (!jump) {
|
1896
1708
|
this.canDoubleJump = !this.doubleJumpUsed && this.jumpReleased && this.jumpCounter === 1;
|
1897
1709
|
this.canJump = true;
|
1898
1710
|
this.jumpReleased = true;
|
1899
1711
|
}
|
1900
|
-
if (
|
1712
|
+
if (jump && this.canJump && this.jumpReleased) {
|
1901
1713
|
currentAcceleration.y += this.jumpForce / deltaTime;
|
1902
1714
|
this.canJump = false;
|
1903
1715
|
this.jumpReleased = false;
|
@@ -1908,13 +1720,13 @@ var LocalController = class {
|
|
1908
1720
|
}
|
1909
1721
|
}
|
1910
1722
|
} else {
|
1911
|
-
if (
|
1723
|
+
if (jump && !this.coyoteJumped && this.coyoteTime) {
|
1912
1724
|
this.coyoteJumped = true;
|
1913
1725
|
currentAcceleration.y += this.jumpForce / deltaTime;
|
1914
1726
|
this.canJump = false;
|
1915
1727
|
this.jumpReleased = false;
|
1916
1728
|
this.jumpCounter++;
|
1917
|
-
} else if (
|
1729
|
+
} else if (jump && this.canDoubleJump) {
|
1918
1730
|
currentAcceleration.y += this.doubleJumpForce / deltaTime;
|
1919
1731
|
this.doubleJumpUsed = true;
|
1920
1732
|
this.jumpReleased = false;
|
@@ -1924,7 +1736,7 @@ var LocalController = class {
|
|
1924
1736
|
this.canJump = false;
|
1925
1737
|
}
|
1926
1738
|
}
|
1927
|
-
if (!
|
1739
|
+
if (!jump) {
|
1928
1740
|
this.jumpReleased = true;
|
1929
1741
|
if (!this.characterOnGround) {
|
1930
1742
|
currentAcceleration.y += this.gravity;
|
@@ -1932,31 +1744,19 @@ var LocalController = class {
|
|
1932
1744
|
}
|
1933
1745
|
}
|
1934
1746
|
applyControls(deltaTime) {
|
1747
|
+
var _a;
|
1935
1748
|
const resistance = this.characterOnGround ? this.groundResistance : this.airResistance;
|
1936
1749
|
const speedFactor = Math.pow(1 - resistance, deltaTime);
|
1937
1750
|
this.characterVelocity.multiplyScalar(speedFactor);
|
1938
1751
|
const acceleration = this.tempVector.set(0, 0, 0);
|
1939
1752
|
this.canDoubleJump = !this.doubleJumpUsed && this.jumpReleased && this.jumpCounter === 1;
|
1940
1753
|
this.processJump(acceleration, deltaTime);
|
1941
|
-
const control = (this.characterOnGround ? this.
|
1754
|
+
const control = (this.characterOnGround ? ((_a = this.controlState) == null ? void 0 : _a.isSprinting) ? this.groundRunControl : this.groundWalkControl : this.airControlModifier) * this.baseControl;
|
1942
1755
|
const controlAcceleration = this.tempVector2.set(0, 0, 0);
|
1943
|
-
if (
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
}
|
1948
|
-
if (this.backward) {
|
1949
|
-
const backward = this.tempVector3.set(0, 0, 1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
|
1950
|
-
controlAcceleration.add(backward);
|
1951
|
-
}
|
1952
|
-
if (this.left) {
|
1953
|
-
const left = this.tempVector3.set(-1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
|
1954
|
-
controlAcceleration.add(left);
|
1955
|
-
}
|
1956
|
-
if (this.right) {
|
1957
|
-
const right = this.tempVector3.set(1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
|
1958
|
-
controlAcceleration.add(right);
|
1959
|
-
}
|
1756
|
+
if (this.controlState && this.controlState.direction !== null) {
|
1757
|
+
const heading = this.controlState.direction;
|
1758
|
+
const headingVector = this.tempVector3.set(0, 0, 1).applyAxisAngle(this.vectorUp, this.azimuthalAngle + heading);
|
1759
|
+
controlAcceleration.add(headingVector);
|
1960
1760
|
}
|
1961
1761
|
if (controlAcceleration.length() > 0) {
|
1962
1762
|
controlAcceleration.normalize();
|
@@ -1967,6 +1767,7 @@ var LocalController = class {
|
|
1967
1767
|
this.config.character.position.addScaledVector(this.characterVelocity, deltaTime);
|
1968
1768
|
}
|
1969
1769
|
updatePosition(deltaTime, stepDeltaTime, iter) {
|
1770
|
+
var _a;
|
1970
1771
|
this.applyControls(stepDeltaTime);
|
1971
1772
|
if (iter === 0) {
|
1972
1773
|
const lastMovement = this.getMovementFromSurfaces(this.config.character.position, deltaTime);
|
@@ -1998,7 +1799,7 @@ var LocalController = class {
|
|
1998
1799
|
if (this.characterWasOnGround && !this.characterOnGround) {
|
1999
1800
|
this.characterAirborneSince = Date.now();
|
2000
1801
|
}
|
2001
|
-
if (!this.jump) {
|
1802
|
+
if (!((_a = this.controlState) == null ? void 0 : _a.jump)) {
|
2002
1803
|
this.jumpReleased = true;
|
2003
1804
|
}
|
2004
1805
|
this.coyoteTime = this.characterVelocity.y < 0 && !this.characterOnGround && Date.now() - this.characterAirborneSince < this.coyoteTimeThreshold;
|
@@ -2320,7 +2121,11 @@ var CharacterManager = class {
|
|
2320
2121
|
this.remoteCharacterControllers.delete(id);
|
2321
2122
|
}
|
2322
2123
|
}
|
2323
|
-
if (this.config.updateURLLocation && this.config.timeManager.frame % 60 === 0 && document.hasFocus()
|
2124
|
+
if (this.config.updateURLLocation && this.config.timeManager.frame % 60 === 0 && document.hasFocus() && /*
|
2125
|
+
Don't update the URL if the camera is being controlled as some browsers (e.g. Chrome) cause a hitch to Pointer
|
2126
|
+
events when the url is updated
|
2127
|
+
*/
|
2128
|
+
!this.config.cameraManager.hasActiveInput()) {
|
2324
2129
|
const hash = encodeCharacterAndCamera(
|
2325
2130
|
this.localCharacter,
|
2326
2131
|
this.config.cameraManager.camera
|
@@ -2449,41 +2254,243 @@ var KeyInputManager = class {
|
|
2449
2254
|
isMovementKeyPressed() {
|
2450
2255
|
return ["w" /* W */, "a" /* A */, "s" /* S */, "d" /* D */].some((key) => this.isKeyPressed(key));
|
2451
2256
|
}
|
2452
|
-
|
2257
|
+
getForward() {
|
2453
2258
|
return this.isKeyPressed("w" /* W */);
|
2454
2259
|
}
|
2455
|
-
|
2260
|
+
getBackward() {
|
2456
2261
|
return this.isKeyPressed("s" /* S */);
|
2457
2262
|
}
|
2458
|
-
|
2263
|
+
getLeft() {
|
2459
2264
|
return this.isKeyPressed("a" /* A */);
|
2460
2265
|
}
|
2461
|
-
|
2266
|
+
getRight() {
|
2462
2267
|
return this.isKeyPressed("d" /* D */);
|
2463
2268
|
}
|
2464
|
-
|
2269
|
+
getRun() {
|
2465
2270
|
return this.isKeyPressed("shift" /* SHIFT */);
|
2466
2271
|
}
|
2467
|
-
|
2272
|
+
getJump() {
|
2468
2273
|
return this.isKeyPressed(" " /* SPACE */);
|
2469
2274
|
}
|
2470
|
-
|
2471
|
-
|
2472
|
-
|
2473
|
-
|
2474
|
-
|
2275
|
+
getOutput() {
|
2276
|
+
const dx = (this.getRight() ? 1 : 0) - (this.getLeft() ? 1 : 0);
|
2277
|
+
const dy = (this.getBackward() ? 1 : 0) - (this.getForward() ? 1 : 0);
|
2278
|
+
const jump = this.getJump();
|
2279
|
+
if (dx === 0 && dy === 0) {
|
2280
|
+
if (this.getJump()) {
|
2281
|
+
return { direction: null, isSprinting: false, jump };
|
2282
|
+
}
|
2283
|
+
return null;
|
2284
|
+
}
|
2285
|
+
const direction = Math.atan2(dx, dy);
|
2286
|
+
return { direction, isSprinting: this.getRun(), jump };
|
2475
2287
|
}
|
2476
2288
|
dispose() {
|
2477
2289
|
this.eventHandlerCollection.clear();
|
2478
2290
|
}
|
2479
2291
|
};
|
2480
2292
|
|
2293
|
+
// src/input/VirtualJoystick.ts
|
2294
|
+
var sprintingThreshold = 0.6;
|
2295
|
+
var VirtualJoystick = class _VirtualJoystick {
|
2296
|
+
constructor(holderElement, config) {
|
2297
|
+
this.holderElement = holderElement;
|
2298
|
+
this.config = config;
|
2299
|
+
this.joystickPointerId = null;
|
2300
|
+
this.joystickOutput = null;
|
2301
|
+
this.jumpPointerId = null;
|
2302
|
+
this.clearJoystickState = () => {
|
2303
|
+
this.joystickOutput = null;
|
2304
|
+
this.joystickCenterElement.style.left = `${this.radius - this.innerRadius}px`;
|
2305
|
+
this.joystickCenterElement.style.top = `${this.radius - this.innerRadius}px`;
|
2306
|
+
};
|
2307
|
+
this.radius = config.radius || 50;
|
2308
|
+
this.innerRadius = config.innerRadius || this.radius / 2;
|
2309
|
+
this.mouseSupport = this.checkTouch() || config.mouseSupport === true;
|
2310
|
+
this.element = document.createElement("div");
|
2311
|
+
const style = this.element.style;
|
2312
|
+
style.display = this.mouseSupport ? "flex" : "none";
|
2313
|
+
style.position = "absolute";
|
2314
|
+
style.width = `100%`;
|
2315
|
+
style.height = `200px`;
|
2316
|
+
style.bottom = "50px";
|
2317
|
+
style.zIndex = "10000";
|
2318
|
+
style.alignItems = "center";
|
2319
|
+
style.justifyContent = "space-between";
|
2320
|
+
style.pointerEvents = "none";
|
2321
|
+
style.padding = "20px";
|
2322
|
+
style.boxSizing = "border-box";
|
2323
|
+
style.userSelect = "none";
|
2324
|
+
this.holderElement.appendChild(this.element);
|
2325
|
+
this.joystickBaseElement = this.createBase();
|
2326
|
+
this.element.appendChild(this.joystickBaseElement);
|
2327
|
+
this.joystickCenterElement = this.createCenter();
|
2328
|
+
this.joystickBaseElement.appendChild(this.joystickCenterElement);
|
2329
|
+
this.jumpButton = this.createJumpButton();
|
2330
|
+
this.element.appendChild(this.jumpButton);
|
2331
|
+
this.bindEvents();
|
2332
|
+
this.clearJoystickState();
|
2333
|
+
}
|
2334
|
+
static checkForTouch() {
|
2335
|
+
try {
|
2336
|
+
document.createEvent("TouchEvent");
|
2337
|
+
return true;
|
2338
|
+
} catch (e) {
|
2339
|
+
return false;
|
2340
|
+
}
|
2341
|
+
}
|
2342
|
+
checkTouch() {
|
2343
|
+
return _VirtualJoystick.checkForTouch();
|
2344
|
+
}
|
2345
|
+
createBase() {
|
2346
|
+
const base = document.createElement("span");
|
2347
|
+
const style = base.style;
|
2348
|
+
style.touchAction = "pinch-zoom";
|
2349
|
+
style.width = `${this.radius * 2}px`;
|
2350
|
+
style.height = `${this.radius * 2}px`;
|
2351
|
+
style.position = "relative";
|
2352
|
+
style.display = "block";
|
2353
|
+
style.borderRadius = "50%";
|
2354
|
+
style.borderColor = "rgba(200,200,200,0.5)";
|
2355
|
+
style.borderWidth = "2px";
|
2356
|
+
style.borderStyle = "solid";
|
2357
|
+
style.pointerEvents = "auto";
|
2358
|
+
style.userSelect = "none";
|
2359
|
+
return base;
|
2360
|
+
}
|
2361
|
+
createCenter() {
|
2362
|
+
const center = document.createElement("div");
|
2363
|
+
const style = center.style;
|
2364
|
+
style.width = `${this.innerRadius * 2}px`;
|
2365
|
+
style.height = `${this.innerRadius * 2}px`;
|
2366
|
+
style.position = "absolute";
|
2367
|
+
style.borderRadius = "50%";
|
2368
|
+
style.backgroundColor = "rgba(200,200,200,0.3)";
|
2369
|
+
style.borderWidth = "1px";
|
2370
|
+
style.borderColor = "rgba(200,200,200,0.8)";
|
2371
|
+
style.borderStyle = "solid";
|
2372
|
+
style.userSelect = "none";
|
2373
|
+
return center;
|
2374
|
+
}
|
2375
|
+
createJumpButton() {
|
2376
|
+
const button = document.createElement("button");
|
2377
|
+
button.textContent = "JUMP";
|
2378
|
+
const style = button.style;
|
2379
|
+
style.touchAction = "pinch-zoom";
|
2380
|
+
style.width = `100px`;
|
2381
|
+
style.height = `100px`;
|
2382
|
+
style.borderRadius = "20px";
|
2383
|
+
style.color = "white";
|
2384
|
+
style.font = "Helvetica, sans-serif";
|
2385
|
+
style.fontSize = "16px";
|
2386
|
+
style.backgroundColor = "rgba(200,200,200,0.3)";
|
2387
|
+
style.color = "rgba(220,220,220,1)";
|
2388
|
+
style.borderWidth = "1px";
|
2389
|
+
style.borderColor = "rgba(200,200,200,0.8)";
|
2390
|
+
style.borderStyle = "solid";
|
2391
|
+
style.pointerEvents = "auto";
|
2392
|
+
style.userSelect = "none";
|
2393
|
+
return button;
|
2394
|
+
}
|
2395
|
+
bindEvents() {
|
2396
|
+
this.joystickBaseElement.addEventListener("pointerdown", this.onJoystickPointerDown.bind(this));
|
2397
|
+
this.joystickBaseElement.addEventListener(
|
2398
|
+
"contextmenu",
|
2399
|
+
this.preventDefaultAndStopPropagation.bind(this)
|
2400
|
+
);
|
2401
|
+
this.joystickBaseElement.addEventListener(
|
2402
|
+
"touchstart",
|
2403
|
+
this.preventDefaultAndStopPropagation.bind(this)
|
2404
|
+
);
|
2405
|
+
this.jumpButton.addEventListener("pointerdown", this.onJumpPointerDown.bind(this));
|
2406
|
+
this.jumpButton.addEventListener(
|
2407
|
+
"contextmenu",
|
2408
|
+
this.preventDefaultAndStopPropagation.bind(this)
|
2409
|
+
);
|
2410
|
+
this.jumpButton.addEventListener(
|
2411
|
+
"touchstart",
|
2412
|
+
this.preventDefaultAndStopPropagation.bind(this)
|
2413
|
+
);
|
2414
|
+
document.addEventListener("pointermove", this.onPointerMove.bind(this));
|
2415
|
+
document.addEventListener("pointerup", this.onPointerUp.bind(this));
|
2416
|
+
document.addEventListener("pointercancel", this.onPointerUp.bind(this));
|
2417
|
+
}
|
2418
|
+
preventDefaultAndStopPropagation(evt) {
|
2419
|
+
evt.preventDefault();
|
2420
|
+
evt.stopPropagation();
|
2421
|
+
}
|
2422
|
+
onJumpPointerDown(evt) {
|
2423
|
+
if (this.jumpPointerId === null) {
|
2424
|
+
this.jumpPointerId = evt.pointerId;
|
2425
|
+
}
|
2426
|
+
}
|
2427
|
+
onJoystickPointerDown(evt) {
|
2428
|
+
evt.preventDefault();
|
2429
|
+
evt.stopPropagation();
|
2430
|
+
if (evt.buttons !== 1) {
|
2431
|
+
return;
|
2432
|
+
}
|
2433
|
+
if (this.joystickPointerId === null) {
|
2434
|
+
this.joystickPointerId = evt.pointerId;
|
2435
|
+
this.updateControlAndDirection(evt);
|
2436
|
+
}
|
2437
|
+
}
|
2438
|
+
onPointerMove(evt) {
|
2439
|
+
evt.preventDefault();
|
2440
|
+
evt.stopPropagation();
|
2441
|
+
if (evt.pointerId !== this.joystickPointerId) {
|
2442
|
+
return;
|
2443
|
+
}
|
2444
|
+
this.updateControlAndDirection(evt);
|
2445
|
+
}
|
2446
|
+
onPointerUp(evt) {
|
2447
|
+
evt.preventDefault();
|
2448
|
+
evt.stopPropagation();
|
2449
|
+
if (evt.pointerId === this.jumpPointerId) {
|
2450
|
+
this.jumpPointerId = null;
|
2451
|
+
}
|
2452
|
+
if (evt.pointerId === this.joystickPointerId) {
|
2453
|
+
this.joystickPointerId = null;
|
2454
|
+
this.clearJoystickState();
|
2455
|
+
}
|
2456
|
+
}
|
2457
|
+
updateControlAndDirection(input) {
|
2458
|
+
const rect = this.joystickBaseElement.getBoundingClientRect();
|
2459
|
+
const dx = input.clientX - (rect.left + this.radius);
|
2460
|
+
const dy = input.clientY - (rect.top + this.radius);
|
2461
|
+
const distance = Math.min(Math.sqrt(dx * dx + dy * dy), this.radius);
|
2462
|
+
const angle = Math.atan2(dy, dx);
|
2463
|
+
const constrainedX = distance * Math.cos(angle);
|
2464
|
+
const constrainedY = distance * Math.sin(angle);
|
2465
|
+
this.joystickCenterElement.style.left = `${constrainedX + this.radius - this.innerRadius}px`;
|
2466
|
+
this.joystickCenterElement.style.top = `${constrainedY + this.radius - this.innerRadius}px`;
|
2467
|
+
const direction = Math.atan2(dx, dy);
|
2468
|
+
const speed = distance / this.radius;
|
2469
|
+
const isSprinting = speed > sprintingThreshold;
|
2470
|
+
this.joystickOutput = { direction, isSprinting };
|
2471
|
+
}
|
2472
|
+
getOutput() {
|
2473
|
+
const jump = this.jumpPointerId !== null;
|
2474
|
+
if (!this.joystickOutput) {
|
2475
|
+
if (jump) {
|
2476
|
+
return { direction: null, isSprinting: false, jump };
|
2477
|
+
}
|
2478
|
+
return null;
|
2479
|
+
}
|
2480
|
+
return {
|
2481
|
+
...this.joystickOutput,
|
2482
|
+
jump
|
2483
|
+
};
|
2484
|
+
}
|
2485
|
+
};
|
2486
|
+
|
2481
2487
|
// src/mml/MMLCompositionScene.ts
|
2482
2488
|
import {
|
2483
2489
|
InteractionManager,
|
2484
2490
|
MMLClickTrigger,
|
2485
2491
|
PromptManager,
|
2486
|
-
LoadingProgressManager
|
2492
|
+
LoadingProgressManager,
|
2493
|
+
MMLDocumentTimeManager
|
2487
2494
|
} from "mml-web";
|
2488
2495
|
import { Group as Group3 } from "three";
|
2489
2496
|
var MMLCompositionScene = class {
|
@@ -2500,6 +2507,7 @@ var MMLCompositionScene = class {
|
|
2500
2507
|
this.interactionManager = interactionManager;
|
2501
2508
|
this.interactionListener = interactionListener;
|
2502
2509
|
this.loadingProgressManager = new LoadingProgressManager();
|
2510
|
+
this.documentTimeManager = new MMLDocumentTimeManager();
|
2503
2511
|
this.mmlScene = {
|
2504
2512
|
getAudioListener: () => this.config.audioListener,
|
2505
2513
|
getRenderer: () => this.config.renderer,
|
@@ -2533,8 +2541,11 @@ var MMLCompositionScene = class {
|
|
2533
2541
|
removeChatProbe: (chatProbe) => {
|
2534
2542
|
this.chatProbes.delete(chatProbe);
|
2535
2543
|
},
|
2536
|
-
prompt: (promptProps, callback) => {
|
2537
|
-
this.promptManager.prompt(promptProps, callback);
|
2544
|
+
prompt: (promptProps, abortSignal, callback) => {
|
2545
|
+
this.promptManager.prompt(promptProps, abortSignal, callback);
|
2546
|
+
},
|
2547
|
+
link: (linkProps, abortSignal, windowCallback) => {
|
2548
|
+
this.promptManager.link(linkProps, abortSignal, windowCallback);
|
2538
2549
|
},
|
2539
2550
|
getLoadingProgressManager: () => {
|
2540
2551
|
return this.loadingProgressManager;
|
@@ -3436,24 +3447,27 @@ var TweakPane = class {
|
|
3436
3447
|
this.characterControls = new CharacterControlsFolder(this.gui, false);
|
3437
3448
|
this.toneMappingFolder.folder.hidden = rendererValues.toneMapping === 5 ? false : true;
|
3438
3449
|
this.export = this.gui.addFolder({ title: "import / export", expanded: false });
|
3439
|
-
this.
|
3440
|
-
window.addEventListener("keydown", (e) => {
|
3441
|
-
this.processKey(e);
|
3442
|
-
});
|
3443
|
-
}
|
3444
|
-
setupGUIListeners() {
|
3450
|
+
this.eventHandlerCollection = new EventHandlerCollection();
|
3445
3451
|
const gui = this.gui;
|
3446
3452
|
const paneElement = gui.containerElem_;
|
3447
3453
|
paneElement.style.right = this.guiVisible ? "0px" : "-450px";
|
3448
|
-
this.gui.element
|
3449
|
-
this.gui.element
|
3450
|
-
this.gui.element
|
3451
|
-
this.
|
3452
|
-
|
3454
|
+
this.eventHandlerCollection.add(this.gui.element, "mouseenter", () => setTweakpaneActive(true));
|
3455
|
+
this.eventHandlerCollection.add(this.gui.element, "mousemove", () => setTweakpaneActive(true));
|
3456
|
+
this.eventHandlerCollection.add(this.gui.element, "mousedown", () => setTweakpaneActive(true));
|
3457
|
+
this.eventHandlerCollection.add(
|
3458
|
+
this.gui.element,
|
3459
|
+
"mouseleave",
|
3460
|
+
() => setTweakpaneActive(false)
|
3461
|
+
);
|
3462
|
+
this.eventHandlerCollection.add(this.gui.element, "mouseup", () => setTweakpaneActive(false));
|
3463
|
+
this.eventHandlerCollection.add(window, "keydown", (e) => {
|
3464
|
+
this.processKey(e);
|
3465
|
+
});
|
3453
3466
|
}
|
3454
3467
|
processKey(e) {
|
3455
|
-
if (e.key === "p")
|
3468
|
+
if (e.key === "p") {
|
3456
3469
|
this.toggleGUI();
|
3470
|
+
}
|
3457
3471
|
}
|
3458
3472
|
setupRenderPane(composer, normalPass, ppssaoEffect, ppssaoPass, n8aopass, toneMappingEffect, toneMappingPass, brightnessContrastSaturation, bloomEffect, gaussGrainEffect, hasLighting, sun, setHDR, setSkyboxAzimuthalAngle, setSkyboxPolarAngle, setAmbientLight, setFog) {
|
3459
3473
|
this.rendererFolder.setupChangeEvent(
|
@@ -3487,6 +3501,7 @@ var TweakPane = class {
|
|
3487
3501
|
});
|
3488
3502
|
}
|
3489
3503
|
dispose() {
|
3504
|
+
this.eventHandlerCollection.clear();
|
3490
3505
|
this.gui.dispose();
|
3491
3506
|
this.tweakPaneWrapper.remove();
|
3492
3507
|
}
|
@@ -5144,12 +5159,12 @@ var Composer = class {
|
|
5144
5159
|
this.width = 1;
|
5145
5160
|
this.height = 1;
|
5146
5161
|
this.resolution = new Vector27(this.width, this.height);
|
5147
|
-
this.isEnvHDRI = false;
|
5148
5162
|
this.bcs = BrightnessContrastSaturation;
|
5149
5163
|
this.gaussGrainEffect = GaussGrainEffect;
|
5150
5164
|
this.ambientLight = null;
|
5165
|
+
this.skyboxState = { src: {}, latestPromise: null };
|
5151
5166
|
this.sun = null;
|
5152
|
-
var _a;
|
5167
|
+
var _a, _b;
|
5153
5168
|
this.scene = scene;
|
5154
5169
|
this.postPostScene = new Scene4();
|
5155
5170
|
this.camera = camera;
|
@@ -5262,6 +5277,13 @@ var Composer = class {
|
|
5262
5277
|
this.sun = new Sun();
|
5263
5278
|
this.scene.add(this.sun);
|
5264
5279
|
}
|
5280
|
+
if ((_b = this.environmentConfiguration) == null ? void 0 : _b.skybox) {
|
5281
|
+
if ("hdrJpgUrl" in this.environmentConfiguration.skybox) {
|
5282
|
+
this.useHDRJPG(this.environmentConfiguration.skybox.hdrJpgUrl);
|
5283
|
+
} else if ("hdrUrl" in this.environmentConfiguration.skybox) {
|
5284
|
+
this.useHDRI(this.environmentConfiguration.skybox.hdrUrl);
|
5285
|
+
}
|
5286
|
+
}
|
5265
5287
|
this.updateSunValues();
|
5266
5288
|
this.resizeListener = () => {
|
5267
5289
|
this.fitContainer();
|
@@ -5269,6 +5291,19 @@ var Composer = class {
|
|
5269
5291
|
window.addEventListener("resize", this.resizeListener, false);
|
5270
5292
|
this.fitContainer();
|
5271
5293
|
}
|
5294
|
+
updateEnvironmentConfiguration(environmentConfiguration) {
|
5295
|
+
this.environmentConfiguration = environmentConfiguration;
|
5296
|
+
if (environmentConfiguration.skybox) {
|
5297
|
+
if ("hdrJpgUrl" in environmentConfiguration.skybox) {
|
5298
|
+
this.useHDRJPG(environmentConfiguration.skybox.hdrJpgUrl);
|
5299
|
+
} else if ("hdrUrl" in environmentConfiguration.skybox) {
|
5300
|
+
this.useHDRI(environmentConfiguration.skybox.hdrUrl);
|
5301
|
+
}
|
5302
|
+
}
|
5303
|
+
this.updateSkyboxAndEnvValues();
|
5304
|
+
this.updateAmbientLightValues();
|
5305
|
+
this.updateSunValues();
|
5306
|
+
}
|
5272
5307
|
setupTweakPane(tweakPane) {
|
5273
5308
|
tweakPane.setupRenderPane(
|
5274
5309
|
this.effectComposer,
|
@@ -5359,71 +5394,71 @@ var Composer = class {
|
|
5359
5394
|
0
|
5360
5395
|
);
|
5361
5396
|
}
|
5362
|
-
|
5363
|
-
|
5364
|
-
|
5365
|
-
const
|
5366
|
-
|
5367
|
-
|
5368
|
-
|
5369
|
-
|
5370
|
-
envMap.colorSpace = LinearSRGBColorSpace;
|
5371
|
-
envMap.needsUpdate = true;
|
5372
|
-
this.scene.environment = envMap;
|
5373
|
-
this.scene.environmentIntensity = envValues.envMapIntensity;
|
5374
|
-
this.scene.environmentRotation = new Euler3(
|
5375
|
-
MathUtils.degToRad(envValues.skyboxPolarAngle),
|
5376
|
-
MathUtils.degToRad(envValues.skyboxAzimuthalAngle),
|
5377
|
-
0
|
5378
|
-
);
|
5379
|
-
this.scene.background = envMap;
|
5380
|
-
this.scene.backgroundIntensity = envValues.skyboxIntensity;
|
5381
|
-
this.scene.backgroundBlurriness = envValues.skyboxBlurriness;
|
5382
|
-
this.scene.backgroundRotation = new Euler3(
|
5383
|
-
MathUtils.degToRad(envValues.skyboxPolarAngle),
|
5384
|
-
MathUtils.degToRad(envValues.skyboxAzimuthalAngle),
|
5385
|
-
0
|
5386
|
-
);
|
5387
|
-
this.isEnvHDRI = true;
|
5397
|
+
async loadHDRJPG(url) {
|
5398
|
+
return new Promise((resolve, reject) => {
|
5399
|
+
const pmremGenerator = new PMREMGenerator(this.renderer);
|
5400
|
+
const hdrJpg = new HDRJPGLoader(this.renderer).load(url, () => {
|
5401
|
+
const hdrJpgEquirectangularMap = hdrJpg.renderTarget.texture;
|
5402
|
+
hdrJpgEquirectangularMap.mapping = EquirectangularReflectionMapping;
|
5403
|
+
hdrJpgEquirectangularMap.needsUpdate = true;
|
5404
|
+
const envMap = pmremGenerator.fromEquirectangular(hdrJpgEquirectangularMap).texture;
|
5388
5405
|
hdrJpgEquirectangularMap.dispose();
|
5389
5406
|
pmremGenerator.dispose();
|
5390
|
-
|
5391
|
-
|
5407
|
+
hdrJpg.dispose();
|
5408
|
+
if (envMap) {
|
5409
|
+
envMap.colorSpace = LinearSRGBColorSpace;
|
5410
|
+
envMap.needsUpdate = true;
|
5411
|
+
resolve(envMap);
|
5412
|
+
} else {
|
5413
|
+
reject("Failed to generate environment map");
|
5414
|
+
}
|
5415
|
+
});
|
5392
5416
|
});
|
5393
5417
|
}
|
5394
|
-
|
5395
|
-
|
5396
|
-
|
5397
|
-
|
5398
|
-
const pmremGenerator = new PMREMGenerator(this.renderer);
|
5399
|
-
new RGBELoader(new LoadingManager()).load(
|
5400
|
-
url,
|
5401
|
-
(texture) => {
|
5418
|
+
async loadHDRi(url) {
|
5419
|
+
return new Promise((resolve, reject) => {
|
5420
|
+
const pmremGenerator = new PMREMGenerator(this.renderer);
|
5421
|
+
new RGBELoader(new LoadingManager()).load(url, (texture) => {
|
5402
5422
|
const envMap = pmremGenerator.fromEquirectangular(texture).texture;
|
5423
|
+
texture.dispose();
|
5424
|
+
pmremGenerator.dispose();
|
5403
5425
|
if (envMap) {
|
5404
5426
|
envMap.colorSpace = LinearSRGBColorSpace;
|
5405
5427
|
envMap.needsUpdate = true;
|
5406
|
-
|
5407
|
-
|
5408
|
-
|
5409
|
-
MathUtils.degToRad(envValues.skyboxPolarAngle),
|
5410
|
-
MathUtils.degToRad(envValues.skyboxAzimuthalAngle),
|
5411
|
-
0
|
5412
|
-
);
|
5413
|
-
this.scene.background = envMap;
|
5414
|
-
this.scene.backgroundIntensity = envValues.skyboxIntensity;
|
5415
|
-
this.scene.backgroundBlurriness = envValues.skyboxBlurriness;
|
5416
|
-
this.isEnvHDRI = true;
|
5417
|
-
texture.dispose();
|
5418
|
-
pmremGenerator.dispose();
|
5428
|
+
resolve(envMap);
|
5429
|
+
} else {
|
5430
|
+
reject("Failed to generate environment map");
|
5419
5431
|
}
|
5420
|
-
}
|
5421
|
-
|
5422
|
-
|
5423
|
-
|
5424
|
-
|
5432
|
+
});
|
5433
|
+
});
|
5434
|
+
}
|
5435
|
+
useHDRJPG(url, fromFile = false) {
|
5436
|
+
if (this.skyboxState.src.hdrJpgUrl === url) {
|
5437
|
+
return;
|
5438
|
+
}
|
5439
|
+
const hdrJPGPromise = this.loadHDRJPG(url);
|
5440
|
+
this.skyboxState.src = { hdrJpgUrl: url };
|
5441
|
+
this.skyboxState.latestPromise = hdrJPGPromise;
|
5442
|
+
hdrJPGPromise.then((envMap) => {
|
5443
|
+
if (this.skyboxState.latestPromise !== hdrJPGPromise) {
|
5444
|
+
return;
|
5425
5445
|
}
|
5426
|
-
|
5446
|
+
this.applyEnvMap(envMap);
|
5447
|
+
});
|
5448
|
+
}
|
5449
|
+
useHDRI(url) {
|
5450
|
+
if (this.skyboxState.src.hdrUrl === url) {
|
5451
|
+
return;
|
5452
|
+
}
|
5453
|
+
const hdrPromise = this.loadHDRi(url);
|
5454
|
+
this.skyboxState.src = { hdrUrl: url };
|
5455
|
+
this.skyboxState.latestPromise = hdrPromise;
|
5456
|
+
hdrPromise.then((envMap) => {
|
5457
|
+
if (this.skyboxState.latestPromise !== hdrPromise) {
|
5458
|
+
return;
|
5459
|
+
}
|
5460
|
+
this.applyEnvMap(envMap);
|
5461
|
+
});
|
5427
5462
|
}
|
5428
5463
|
setHDRIFromFile() {
|
5429
5464
|
if (!this.renderer)
|
@@ -5442,7 +5477,7 @@ var Composer = class {
|
|
5442
5477
|
const fileURL = URL.createObjectURL(file);
|
5443
5478
|
if (fileURL) {
|
5444
5479
|
if (extension === "hdr") {
|
5445
|
-
this.useHDRI(fileURL
|
5480
|
+
this.useHDRI(fileURL);
|
5446
5481
|
} else if (extension === "jpg") {
|
5447
5482
|
this.useHDRJPG(fileURL);
|
5448
5483
|
} else {
|
@@ -5524,6 +5559,23 @@ var Composer = class {
|
|
5524
5559
|
}
|
5525
5560
|
this.setAmbientLight();
|
5526
5561
|
}
|
5562
|
+
applyEnvMap(envMap) {
|
5563
|
+
this.scene.environment = envMap;
|
5564
|
+
this.scene.environmentIntensity = envValues.envMapIntensity;
|
5565
|
+
this.scene.environmentRotation = new Euler3(
|
5566
|
+
MathUtils.degToRad(envValues.skyboxPolarAngle),
|
5567
|
+
MathUtils.degToRad(envValues.skyboxAzimuthalAngle),
|
5568
|
+
0
|
5569
|
+
);
|
5570
|
+
this.scene.background = envMap;
|
5571
|
+
this.scene.backgroundIntensity = envValues.skyboxIntensity;
|
5572
|
+
this.scene.backgroundBlurriness = envValues.skyboxBlurriness;
|
5573
|
+
this.scene.backgroundRotation = new Euler3(
|
5574
|
+
MathUtils.degToRad(envValues.skyboxPolarAngle),
|
5575
|
+
MathUtils.degToRad(envValues.skyboxAzimuthalAngle),
|
5576
|
+
0
|
5577
|
+
);
|
5578
|
+
}
|
5527
5579
|
};
|
5528
5580
|
|
5529
5581
|
// src/time/TimeManager.ts
|