@mml-io/3d-web-client-core 0.19.0 → 0.20.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/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/camera/CameraManager.ts
2
2
  import { PerspectiveCamera, Raycaster, Vector3 as Vector32 } from "three";
3
+ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
3
4
 
4
5
  // src/helpers/math-helpers.ts
5
6
  import { Quaternion, Vector3, Vector4 } from "three";
@@ -218,6 +219,7 @@ var CameraManager = class {
218
219
  constructor(targetElement, collisionsManager, initialPhi = Math.PI / 2, initialTheta = -Math.PI / 2) {
219
220
  this.targetElement = targetElement;
220
221
  this.collisionsManager = collisionsManager;
222
+ this.isMainCameraActive = true;
221
223
  this.initialDistance = camValues.initialDistance;
222
224
  this.minDistance = camValues.minDistance;
223
225
  this.maxDistance = camValues.maxDistance;
@@ -248,19 +250,36 @@ var CameraManager = class {
248
250
  this.targetPhi = this.phi;
249
251
  this.theta = initialTheta;
250
252
  this.targetTheta = this.theta;
251
- this.camera = new PerspectiveCamera(this.fov, window.innerWidth / window.innerHeight, 0.1, 400);
253
+ const aspect = window.innerWidth / window.innerHeight;
254
+ this.camera = new PerspectiveCamera(this.fov, aspect, 0.1, 400);
252
255
  this.camera.position.set(0, 1.4, -this.initialDistance);
256
+ this.camera.name = "MainCamera";
257
+ this.flyCamera = new PerspectiveCamera(this.initialFOV, aspect, 0.1, 400);
258
+ this.flyCamera.name = "FlyCamera";
259
+ this.flyCamera.position.copy(this.camera.position);
260
+ this.flyCamera.name = "FlyCamera";
261
+ this.orbitControls = new OrbitControls(this.flyCamera, this.targetElement);
262
+ this.orbitControls.enableDamping = true;
263
+ this.orbitControls.dampingFactor = 0.05;
264
+ this.orbitControls.enablePan = true;
265
+ this.orbitControls.enabled = false;
253
266
  this.rayCaster = new Raycaster();
267
+ this.createEventHandlers();
268
+ }
269
+ createEventHandlers() {
254
270
  this.eventHandlerCollection = EventHandlerCollection.create([
255
- [targetElement, "pointerdown", this.onPointerDown.bind(this)],
256
- [targetElement, "gesturestart", this.preventDefaultAndStopPropagation.bind(this)],
271
+ [this.targetElement, "pointerdown", this.onPointerDown.bind(this)],
272
+ [this.targetElement, "gesturestart", this.preventDefaultAndStopPropagation.bind(this)],
273
+ [this.targetElement, "wheel", this.onMouseWheel.bind(this)],
274
+ [this.targetElement, "contextmenu", this.onContextMenu.bind(this)],
257
275
  [document, "pointerup", this.onPointerUp.bind(this)],
258
276
  [document, "pointercancel", this.onPointerUp.bind(this)],
259
- [document, "pointermove", this.onPointerMove.bind(this)],
260
- [targetElement, "wheel", this.onMouseWheel.bind(this)],
261
- [targetElement, "contextmenu", this.onContextMenu.bind(this)]
277
+ [document, "pointermove", this.onPointerMove.bind(this)]
262
278
  ]);
263
279
  }
280
+ disposeEventHandlers() {
281
+ this.eventHandlerCollection.clear();
282
+ }
264
283
  preventDefaultAndStopPropagation(evt) {
265
284
  evt.preventDefault();
266
285
  evt.stopPropagation();
@@ -391,7 +410,8 @@ var CameraManager = class {
391
410
  }
392
411
  }
393
412
  dispose() {
394
- this.eventHandlerCollection.clear();
413
+ this.disposeEventHandlers();
414
+ this.orbitControls.dispose();
395
415
  document.body.style.cursor = "";
396
416
  }
397
417
  easeOutExpo(x) {
@@ -399,6 +419,7 @@ var CameraManager = class {
399
419
  }
400
420
  updateAspect(aspect) {
401
421
  this.camera.aspect = aspect;
422
+ this.flyCamera.aspect = aspect;
402
423
  }
403
424
  recomputeFoV(immediately = false) {
404
425
  this.targetFOV = remap(
@@ -412,7 +433,31 @@ var CameraManager = class {
412
433
  this.fov = this.targetFOV;
413
434
  }
414
435
  }
436
+ toggleFlyCamera() {
437
+ this.isMainCameraActive = !this.isMainCameraActive;
438
+ this.orbitControls.enabled = !this.isMainCameraActive;
439
+ if (!this.isMainCameraActive) {
440
+ this.updateAspect(window.innerWidth / window.innerHeight);
441
+ this.flyCamera.position.copy(this.camera.position);
442
+ this.flyCamera.rotation.copy(this.camera.rotation);
443
+ const target = new Vector32();
444
+ this.camera.getWorldDirection(target);
445
+ target.multiplyScalar(this.targetDistance).add(this.camera.position);
446
+ this.orbitControls.target.copy(target);
447
+ this.orbitControls.update();
448
+ this.disposeEventHandlers();
449
+ } else {
450
+ this.createEventHandlers();
451
+ }
452
+ }
453
+ get activeCamera() {
454
+ return this.isMainCameraActive ? this.camera : this.flyCamera;
455
+ }
415
456
  update() {
457
+ if (!this.isMainCameraActive) {
458
+ this.orbitControls.update();
459
+ return;
460
+ }
416
461
  if (this.isLerping && this.lerpFactor < 1) {
417
462
  this.lerpFactor += 0.01 / this.lerpDuration;
418
463
  this.lerpFactor = Math.min(1, this.lerpFactor);
@@ -1666,17 +1711,17 @@ var LocalController = class {
1666
1711
  }
1667
1712
  }
1668
1713
  updateAzimuthalAngle() {
1669
- const camToModelDistance = this.config.cameraManager.camera.position.distanceTo(
1714
+ const camToModelDistance = this.config.cameraManager.activeCamera.position.distanceTo(
1670
1715
  this.config.character.position
1671
1716
  );
1672
1717
  const isCameraFirstPerson = camToModelDistance < 2;
1673
1718
  if (isCameraFirstPerson) {
1674
- const cameraForward = this.tempVector.set(0, 0, 1).applyQuaternion(this.config.cameraManager.camera.quaternion);
1719
+ const cameraForward = this.tempVector.set(0, 0, 1).applyQuaternion(this.config.cameraManager.activeCamera.quaternion);
1675
1720
  this.azimuthalAngle = Math.atan2(cameraForward.x, cameraForward.z);
1676
1721
  } else {
1677
1722
  this.azimuthalAngle = Math.atan2(
1678
- this.config.cameraManager.camera.position.x - this.config.character.position.x,
1679
- this.config.cameraManager.camera.position.z - this.config.character.position.z
1723
+ this.config.cameraManager.activeCamera.position.x - this.config.character.position.x,
1724
+ this.config.cameraManager.activeCamera.position.z - this.config.character.position.z
1680
1725
  );
1681
1726
  }
1682
1727
  }
@@ -2221,11 +2266,22 @@ var CharacterModelLoader = class {
2221
2266
  };
2222
2267
 
2223
2268
  // src/input/KeyInputManager.ts
2269
+ var Key = /* @__PURE__ */ ((Key2) => {
2270
+ Key2["W"] = "w";
2271
+ Key2["A"] = "a";
2272
+ Key2["S"] = "s";
2273
+ Key2["D"] = "d";
2274
+ Key2["SHIFT"] = "shift";
2275
+ Key2["SPACE"] = " ";
2276
+ Key2["C"] = "c";
2277
+ return Key2;
2278
+ })(Key || {});
2224
2279
  var KeyInputManager = class {
2225
2280
  constructor(shouldCaptureKeyPress = () => true) {
2226
2281
  this.shouldCaptureKeyPress = shouldCaptureKeyPress;
2227
2282
  this.keys = /* @__PURE__ */ new Map();
2228
2283
  this.eventHandlerCollection = new EventHandlerCollection();
2284
+ this.bindings = /* @__PURE__ */ new Map();
2229
2285
  this.eventHandlerCollection.add(document, "keydown", this.onKeyDown.bind(this));
2230
2286
  this.eventHandlerCollection.add(document, "keyup", this.onKeyUp.bind(this));
2231
2287
  this.eventHandlerCollection.add(window, "blur", this.handleUnfocus.bind(this));
@@ -2247,10 +2303,16 @@ var KeyInputManager = class {
2247
2303
  }
2248
2304
  onKeyUp(event) {
2249
2305
  this.keys.set(event.key.toLowerCase(), false);
2306
+ if (this.bindings.has(event.key.toLowerCase())) {
2307
+ this.bindings.get(event.key.toLowerCase())();
2308
+ }
2250
2309
  }
2251
2310
  isKeyPressed(key) {
2252
2311
  return this.keys.get(key) || false;
2253
2312
  }
2313
+ createKeyBinding(key, callback) {
2314
+ this.bindings.set(key, callback);
2315
+ }
2254
2316
  isMovementKeyPressed() {
2255
2317
  return ["w" /* W */, "a" /* A */, "s" /* S */, "d" /* D */].some((key) => this.isKeyPressed(key));
2256
2318
  }
@@ -2287,6 +2349,7 @@ var KeyInputManager = class {
2287
2349
  }
2288
2350
  dispose() {
2289
2351
  this.eventHandlerCollection.clear();
2352
+ this.bindings.clear();
2290
2353
  }
2291
2354
  };
2292
2355
 
@@ -2487,11 +2550,15 @@ var VirtualJoystick = class _VirtualJoystick {
2487
2550
  // src/mml/MMLCompositionScene.ts
2488
2551
  import {
2489
2552
  InteractionManager,
2490
- MMLClickTrigger,
2491
- PromptManager,
2492
2553
  LoadingProgressManager,
2493
- MMLDocumentTimeManager
2494
- } from "mml-web";
2554
+ MMLDocumentTimeManager,
2555
+ PromptManager
2556
+ } from "@mml-io/mml-web";
2557
+ import {
2558
+ ThreeJSClickTrigger,
2559
+ ThreeJSGraphicsInterface,
2560
+ ThreeJSInteractionAdapter
2561
+ } from "@mml-io/mml-web-threejs";
2495
2562
  import { Group as Group3 } from "three";
2496
2563
  var MMLCompositionScene = class {
2497
2564
  constructor(config) {
@@ -2499,21 +2566,55 @@ var MMLCompositionScene = class {
2499
2566
  this.chatProbes = /* @__PURE__ */ new Set();
2500
2567
  this.group = new Group3();
2501
2568
  this.promptManager = PromptManager.init(this.config.targetElement);
2569
+ const graphicsAdapter = {
2570
+ collisionType: null,
2571
+ containerType: null,
2572
+ getGraphicsAdapterFactory: () => {
2573
+ return ThreeJSGraphicsInterface;
2574
+ },
2575
+ getRootContainer: () => {
2576
+ return this.group;
2577
+ },
2578
+ interactionShouldShowDistance(interaction) {
2579
+ return ThreeJSInteractionAdapter.interactionShouldShowDistance(
2580
+ interaction,
2581
+ this.config.camera,
2582
+ this.config.scene
2583
+ );
2584
+ },
2585
+ dispose() {
2586
+ },
2587
+ getAudioListener: () => {
2588
+ return config.audioListener;
2589
+ },
2590
+ getCamera: () => {
2591
+ return config.camera;
2592
+ },
2593
+ getThreeScene: () => {
2594
+ return config.scene;
2595
+ },
2596
+ getUserPositionAndRotation: () => {
2597
+ return this.config.getUserPositionAndRotation();
2598
+ }
2599
+ };
2502
2600
  const { interactionListener, interactionManager } = InteractionManager.init(
2503
2601
  this.config.targetElement,
2504
- this.config.camera,
2505
- this.config.scene
2602
+ (interaction) => {
2603
+ return graphicsAdapter.interactionShouldShowDistance(interaction);
2604
+ }
2506
2605
  );
2507
2606
  this.interactionManager = interactionManager;
2508
2607
  this.interactionListener = interactionListener;
2509
2608
  this.loadingProgressManager = new LoadingProgressManager();
2510
2609
  this.documentTimeManager = new MMLDocumentTimeManager();
2511
2610
  this.mmlScene = {
2512
- getAudioListener: () => this.config.audioListener,
2513
- getRenderer: () => this.config.renderer,
2514
- getThreeScene: () => this.config.scene,
2611
+ getGraphicsAdapter() {
2612
+ return graphicsAdapter;
2613
+ },
2614
+ hasGraphicsAdapter() {
2615
+ return true;
2616
+ },
2515
2617
  getRootContainer: () => this.group,
2516
- getCamera: () => this.config.camera,
2517
2618
  addCollider: (object, mElement) => {
2518
2619
  this.config.collisionsManager.addMeshesGroup(object, mElement);
2519
2620
  },
@@ -2551,7 +2652,11 @@ var MMLCompositionScene = class {
2551
2652
  return this.loadingProgressManager;
2552
2653
  }
2553
2654
  };
2554
- this.clickTrigger = MMLClickTrigger.init(this.config.targetElement, this.mmlScene);
2655
+ this.clickTrigger = ThreeJSClickTrigger.init(
2656
+ this.config.targetElement,
2657
+ this.group,
2658
+ this.config.camera
2659
+ );
2555
2660
  }
2556
2661
  onChatMessage(message) {
2557
2662
  for (const chatProbe of this.chatProbes) {
@@ -5152,7 +5257,7 @@ var N8SSAOPass = class extends Pass {
5152
5257
  var Composer = class {
5153
5258
  constructor({
5154
5259
  scene,
5155
- camera,
5260
+ cameraManager,
5156
5261
  spawnSun = false,
5157
5262
  environmentConfiguration
5158
5263
  }) {
@@ -5166,8 +5271,8 @@ var Composer = class {
5166
5271
  this.sun = null;
5167
5272
  var _a, _b;
5168
5273
  this.scene = scene;
5274
+ this.cameraManager = cameraManager;
5169
5275
  this.postPostScene = new Scene4();
5170
- this.camera = camera;
5171
5276
  this.spawnSun = spawnSun;
5172
5277
  this.renderer = new WebGLRenderer4({
5173
5278
  powerPreference: "high-performance",
@@ -5187,14 +5292,14 @@ var Composer = class {
5187
5292
  this.effectComposer = new EffectComposer2(this.renderer, {
5188
5293
  frameBufferType: HalfFloatType2
5189
5294
  });
5190
- this.renderPass = new RenderPass(this.scene, this.camera);
5191
- this.normalPass = new NormalPass2(this.scene, this.camera);
5295
+ this.renderPass = new RenderPass(this.scene, this.cameraManager.activeCamera);
5296
+ this.normalPass = new NormalPass2(this.scene, this.cameraManager.activeCamera);
5192
5297
  this.normalPass.enabled = ppssaoValues.enabled;
5193
5298
  this.normalTextureEffect = new TextureEffect({
5194
5299
  blendFunction: BlendFunction2.SKIP,
5195
5300
  texture: this.normalPass.texture
5196
5301
  });
5197
- this.ppssaoEffect = new SSAOEffect2(this.camera, this.normalPass.texture, {
5302
+ this.ppssaoEffect = new SSAOEffect2(this.cameraManager.activeCamera, this.normalPass.texture, {
5198
5303
  blendFunction: ppssaoValues.blendFunction,
5199
5304
  distanceScaling: ppssaoValues.distanceScaling,
5200
5305
  depthAwareUpsampling: ppssaoValues.depthAwareUpsampling,
@@ -5212,7 +5317,11 @@ var Composer = class {
5212
5317
  worldProximityThreshold: ppssaoValues.worldProximityThreshold,
5213
5318
  worldProximityFalloff: ppssaoValues.worldProximityFalloff
5214
5319
  });
5215
- this.ppssaoPass = new EffectPass2(this.camera, this.ppssaoEffect, this.normalTextureEffect);
5320
+ this.ppssaoPass = new EffectPass2(
5321
+ this.cameraManager.activeCamera,
5322
+ this.ppssaoEffect,
5323
+ this.normalTextureEffect
5324
+ );
5216
5325
  this.ppssaoPass.enabled = ppssaoValues.enabled;
5217
5326
  this.fxaaEffect = new FXAAEffect();
5218
5327
  if ((_a = environmentConfiguration == null ? void 0 : environmentConfiguration.postProcessing) == null ? void 0 : _a.bloomIntensity) {
@@ -5221,7 +5330,12 @@ var Composer = class {
5221
5330
  this.bloomEffect = new BloomEffect({
5222
5331
  intensity: extrasValues.bloom
5223
5332
  });
5224
- this.n8aopass = new N8SSAOPass(this.scene, this.camera, this.width, this.height);
5333
+ this.n8aopass = new N8SSAOPass(
5334
+ this.scene,
5335
+ this.cameraManager.activeCamera,
5336
+ this.width,
5337
+ this.height
5338
+ );
5225
5339
  this.n8aopass.configuration.aoRadius = n8ssaoValues.aoRadius;
5226
5340
  this.n8aopass.configuration.distanceFalloff = n8ssaoValues.distanceFalloff;
5227
5341
  this.n8aopass.configuration.intensity = n8ssaoValues.intensity;
@@ -5234,8 +5348,8 @@ var Composer = class {
5234
5348
  this.n8aopass.configuration.denoiseSamples = n8ssaoValues.denoiseSamples;
5235
5349
  this.n8aopass.configuration.denoiseRadius = n8ssaoValues.denoiseRadius;
5236
5350
  this.n8aopass.enabled = n8ssaoValues.enabled;
5237
- this.fxaaPass = new EffectPass2(this.camera, this.fxaaEffect);
5238
- this.bloomPass = new EffectPass2(this.camera, this.bloomEffect);
5351
+ this.fxaaPass = new EffectPass2(this.cameraManager.activeCamera, this.fxaaEffect);
5352
+ this.bloomPass = new EffectPass2(this.cameraManager.activeCamera, this.bloomEffect);
5239
5353
  this.toneMappingEffect = new ToneMappingEffect({
5240
5354
  mode: toneMappingValues.mode,
5241
5355
  resolution: toneMappingValues.resolution,
@@ -5250,7 +5364,7 @@ var Composer = class {
5250
5364
  edgeDetectionMode: EdgeDetectionMode.COLOR,
5251
5365
  predicationMode: PredicationMode.DEPTH
5252
5366
  });
5253
- this.toneMappingPass = new EffectPass2(this.camera, this.toneMappingEffect);
5367
+ this.toneMappingPass = new EffectPass2(this.cameraManager.activeCamera, this.toneMappingEffect);
5254
5368
  this.toneMappingPass.enabled = rendererValues.toneMapping === 5 || rendererValues.toneMapping === 0 ? true : false;
5255
5369
  this.bcsPass = new ShaderPass(this.bcs, "tDiffuse");
5256
5370
  this.bcs.uniforms.brightness.value = bcsValues.brightness;
@@ -5259,7 +5373,7 @@ var Composer = class {
5259
5373
  this.gaussGrainPass = new ShaderPass(this.gaussGrainEffect, "tDiffuse");
5260
5374
  this.gaussGrainEffect.uniforms.amount.value = extrasValues.grain;
5261
5375
  this.gaussGrainEffect.uniforms.alpha.value = 1;
5262
- this.smaaPass = new EffectPass2(this.camera, this.smaaEffect);
5376
+ this.smaaPass = new EffectPass2(this.cameraManager.activeCamera, this.smaaEffect);
5263
5377
  this.effectComposer.addPass(this.renderPass);
5264
5378
  if (ppssaoValues.enabled) {
5265
5379
  this.effectComposer.addPass(this.normalPass);
@@ -5346,8 +5460,8 @@ var Composer = class {
5346
5460
  }
5347
5461
  this.width = parentElement.clientWidth;
5348
5462
  this.height = parentElement.clientHeight;
5349
- this.camera.aspect = this.width / this.height;
5350
- this.camera.updateProjectionMatrix();
5463
+ this.cameraManager.activeCamera.aspect = this.width / this.height;
5464
+ this.cameraManager.activeCamera.updateProjectionMatrix();
5351
5465
  this.renderer.setPixelRatio(window.devicePixelRatio);
5352
5466
  this.resolution.set(
5353
5467
  this.width * window.devicePixelRatio,
@@ -5376,11 +5490,12 @@ var Composer = class {
5376
5490
  }
5377
5491
  render(timeManager) {
5378
5492
  this.renderer.info.reset();
5493
+ this.renderPass.mainCamera = this.cameraManager.activeCamera;
5379
5494
  this.normalPass.texture.needsUpdate = true;
5380
5495
  this.gaussGrainEffect.uniforms.time.value = timeManager.time;
5381
5496
  this.effectComposer.render();
5382
5497
  this.renderer.clearDepth();
5383
- this.renderer.render(this.postPostScene, this.camera);
5498
+ this.renderer.render(this.postPostScene, this.cameraManager.activeCamera);
5384
5499
  }
5385
5500
  updateSkyboxRotation() {
5386
5501
  this.scene.backgroundRotation = new Euler3(
@@ -5522,11 +5637,13 @@ var Composer = class {
5522
5637
  }
5523
5638
  if (typeof ((_e = (_d = this.environmentConfiguration) == null ? void 0 : _d.sun) == null ? void 0 : _e.azimuthalAngle) === "number") {
5524
5639
  sunValues.sunPosition.sunAzimuthalAngle = this.environmentConfiguration.sun.azimuthalAngle;
5525
- (_f = this.sun) == null ? void 0 : _f.setAzimuthalAngle(this.environmentConfiguration.sun.azimuthalAngle);
5640
+ (_f = this.sun) == null ? void 0 : _f.setAzimuthalAngle(
5641
+ this.environmentConfiguration.sun.azimuthalAngle * (Math.PI / 180)
5642
+ );
5526
5643
  }
5527
5644
  if (typeof ((_h = (_g = this.environmentConfiguration) == null ? void 0 : _g.sun) == null ? void 0 : _h.polarAngle) === "number") {
5528
5645
  sunValues.sunPosition.sunPolarAngle = this.environmentConfiguration.sun.polarAngle;
5529
- (_i = this.sun) == null ? void 0 : _i.setPolarAngle(this.environmentConfiguration.sun.polarAngle);
5646
+ (_i = this.sun) == null ? void 0 : _i.setPolarAngle(this.environmentConfiguration.sun.polarAngle * (Math.PI / 180));
5530
5647
  }
5531
5648
  }
5532
5649
  updateSkyboxAndEnvValues() {
@@ -5625,39 +5742,73 @@ var TimeManager = class {
5625
5742
  };
5626
5743
 
5627
5744
  // src/collisions/CollisionsManager.ts
5628
- import {
5629
- getRelativePositionAndRotationRelativeToObject,
5630
- MMLCollisionTrigger
5631
- } from "mml-web";
5745
+ import { MMLCollisionTrigger } from "@mml-io/mml-web";
5632
5746
  import {
5633
5747
  Box3,
5634
5748
  Color as Color8,
5635
5749
  DoubleSide,
5636
- Euler as Euler4,
5750
+ Euler as Euler5,
5637
5751
  Group as Group5,
5638
5752
  Line3 as Line32,
5639
- Matrix4 as Matrix46,
5753
+ Matrix4 as Matrix47,
5640
5754
  Mesh as Mesh5,
5641
5755
  MeshBasicMaterial as MeshBasicMaterial3,
5642
- Quaternion as Quaternion6,
5756
+ Quaternion as Quaternion7,
5643
5757
  Ray as Ray2,
5644
- Vector3 as Vector314
5758
+ Vector3 as Vector315
5645
5759
  } from "three";
5646
5760
  import { VertexNormalsHelper } from "three/examples/jsm/helpers/VertexNormalsHelper.js";
5647
5761
  import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils.js";
5648
5762
  import { MeshBVH, MeshBVHHelper } from "three-mesh-bvh";
5763
+
5764
+ // src/collisions/getRelativePositionAndRotationRelativeToObject.ts
5765
+ import { Euler as Euler4, Matrix4 as Matrix46, Quaternion as Quaternion6, Vector3 as Vector314 } from "three";
5766
+ var tempContainerMatrix = new Matrix46();
5767
+ var tempTargetMatrix = new Matrix46();
5768
+ var tempPositionVector = new Vector314();
5769
+ var tempRotationEuler = new Euler4();
5770
+ var tempRotationQuaternion = new Quaternion6();
5771
+ var tempScaleVector = new Vector314();
5772
+ function getRelativePositionAndRotationRelativeToObject(positionAndRotation, container) {
5773
+ const { x, y, z } = positionAndRotation.position;
5774
+ const { x: rx, y: ry, z: rz } = positionAndRotation.rotation;
5775
+ container.updateWorldMatrix(true, false);
5776
+ tempContainerMatrix.copy(container.matrixWorld).invert();
5777
+ tempPositionVector.set(x, y, z);
5778
+ tempRotationEuler.set(rx, ry, rz);
5779
+ tempRotationQuaternion.setFromEuler(tempRotationEuler);
5780
+ tempScaleVector.set(1, 1, 1);
5781
+ tempTargetMatrix.compose(tempPositionVector, tempRotationQuaternion, tempScaleVector);
5782
+ tempTargetMatrix.premultiply(tempContainerMatrix);
5783
+ tempTargetMatrix.decompose(tempPositionVector, tempRotationQuaternion, tempScaleVector);
5784
+ tempRotationEuler.setFromQuaternion(tempRotationQuaternion);
5785
+ return {
5786
+ position: {
5787
+ x: tempPositionVector.x,
5788
+ y: tempPositionVector.y,
5789
+ z: tempPositionVector.z
5790
+ },
5791
+ rotation: {
5792
+ x: tempRotationEuler.x,
5793
+ y: tempRotationEuler.y,
5794
+ z: tempRotationEuler.z
5795
+ }
5796
+ };
5797
+ }
5798
+
5799
+ // src/collisions/CollisionsManager.ts
5649
5800
  var CollisionsManager = class {
5650
5801
  constructor(scene) {
5651
5802
  this.debug = false;
5652
- this.tempVector = new Vector314();
5653
- this.tempVector2 = new Vector314();
5654
- this.tempVector3 = new Vector314();
5655
- this.tempQuaternion = new Quaternion6();
5803
+ this.tempVector = new Vector315();
5804
+ this.tempVector2 = new Vector315();
5805
+ this.tempVector3 = new Vector315();
5806
+ this.tempQuaternion = new Quaternion7();
5656
5807
  this.tempRay = new Ray2();
5657
- this.tempMatrix = new Matrix46();
5658
- this.tempMatrix2 = new Matrix46();
5808
+ this.tempMatrix = new Matrix47();
5809
+ this.tempMatrix2 = new Matrix47();
5659
5810
  this.tempBox = new Box3();
5660
- this.tempEuler = new Euler4();
5811
+ this.tempEuler = new Euler5();
5661
5812
  this.tempSegment = new Line32();
5662
5813
  this.tempSegment2 = new Line32();
5663
5814
  this.collisionMeshState = /* @__PURE__ */ new Map();
@@ -5667,7 +5818,7 @@ var CollisionsManager = class {
5667
5818
  raycastFirst(ray) {
5668
5819
  let minimumDistance = null;
5669
5820
  let minimumHit = null;
5670
- let minimumNormal = new Vector314();
5821
+ let minimumNormal = new Vector315();
5671
5822
  for (const [, collisionMeshState] of this.collisionMeshState) {
5672
5823
  this.tempRay.copy(ray).applyMatrix4(this.tempMatrix.copy(collisionMeshState.matrix).invert());
5673
5824
  const hit = collisionMeshState.meshBVH.raycastFirst(this.tempRay, DoubleSide);
@@ -5808,7 +5959,7 @@ var CollisionsManager = class {
5808
5959
  const realDistance = intersectionSegment.distance();
5809
5960
  if (realDistance < capsuleRadius) {
5810
5961
  if (!collisionPosition) {
5811
- collisionPosition = new Vector314().copy(closestPointOnSegment).applyMatrix4(meshState.matrix);
5962
+ collisionPosition = new Vector315().copy(closestPointOnSegment).applyMatrix4(meshState.matrix);
5812
5963
  }
5813
5964
  const ratio = realDistance / modelReferenceDistance;
5814
5965
  const realDepth = capsuleRadius - realDistance;
@@ -5910,59 +6061,134 @@ var GroundPlane = class extends Group6 {
5910
6061
  };
5911
6062
 
5912
6063
  // src/loading-screen/LoadingScreen.ts
5913
- import { LoadingProgressManager as LoadingProgressManager2 } from "mml-web";
6064
+ import { LoadingProgressManager as LoadingProgressManager2 } from "@mml-io/mml-web";
5914
6065
  var LoadingScreen = class {
5915
- constructor(loadingProgressManager) {
6066
+ constructor(loadingProgressManager, config) {
5916
6067
  this.loadingProgressManager = loadingProgressManager;
6068
+ this.config = config;
6069
+ this.overlayLayers = [];
5917
6070
  this.hasCompleted = false;
5918
6071
  this.disposed = false;
6072
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
6073
+ const defaultBackground = "linear-gradient(45deg, #28284B 0%, #303056 100%)";
5919
6074
  this.element = document.createElement("div");
6075
+ this.element.id = "loading-screen";
5920
6076
  this.element.style.position = "absolute";
5921
6077
  this.element.style.top = "0";
5922
6078
  this.element.style.left = "0";
5923
6079
  this.element.style.width = "100%";
5924
6080
  this.element.style.height = "100%";
5925
- this.element.style.background = "linear-gradient(45deg, #28284B 0%, #303056 100%)";
5926
- this.element.style.color = "white";
5927
- this.element.addEventListener("click", (event) => {
5928
- event.stopPropagation();
5929
- });
5930
- this.element.addEventListener("mousedown", (event) => {
5931
- event.stopPropagation();
5932
- });
5933
- this.element.addEventListener("mousemove", (event) => {
5934
- event.stopPropagation();
5935
- });
5936
- this.element.addEventListener("mouseup", (event) => {
5937
- event.stopPropagation();
5938
- });
5939
- this.loadingBannerText = document.createElement("div");
5940
- this.loadingBannerText.textContent = "Loading...";
5941
- this.loadingBannerText.style.position = "absolute";
5942
- this.loadingBannerText.style.display = "flex";
5943
- this.loadingBannerText.style.top = "0";
5944
- this.loadingBannerText.style.left = "0";
5945
- this.loadingBannerText.style.width = "100%";
5946
- this.loadingBannerText.style.height = "100%";
5947
- this.loadingBannerText.style.color = "white";
5948
- this.loadingBannerText.style.fontSize = "80px";
5949
- this.loadingBannerText.style.fontWeight = "bold";
5950
- this.loadingBannerText.style.fontFamily = "sans-serif";
5951
- this.loadingBannerText.style.alignItems = "center";
5952
- this.loadingBannerText.style.justifyContent = "center";
5953
- this.element.append(this.loadingBannerText);
6081
+ this.element.style.backgroundColor = ((_a = this.config) == null ? void 0 : _a.background) || defaultBackground;
6082
+ this.element.style.background = ((_b = this.config) == null ? void 0 : _b.background) || defaultBackground;
6083
+ this.element.style.zIndex = "10001";
6084
+ this.backgroundBlur = document.createElement("div");
6085
+ this.backgroundBlur.id = "loading-screen-blur";
6086
+ this.backgroundBlur.style.position = "absolute";
6087
+ this.backgroundBlur.style.top = "0";
6088
+ this.backgroundBlur.style.left = "0";
6089
+ this.backgroundBlur.style.width = "100%";
6090
+ this.backgroundBlur.style.height = "100%";
6091
+ this.backgroundBlur.style.display = "flex";
6092
+ if ((_c = this.config) == null ? void 0 : _c.backgroundBlurAmount) {
6093
+ this.backgroundBlur.style.backdropFilter = `blur(${this.config.backgroundBlurAmount}px)`;
6094
+ }
6095
+ this.element.append(this.backgroundBlur);
6096
+ if ((_d = this.config) == null ? void 0 : _d.backgroundImageUrl) {
6097
+ this.element.style.backgroundImage = `url(${this.config.backgroundImageUrl})`;
6098
+ this.element.style.backgroundPosition = "center";
6099
+ this.element.style.backgroundSize = "cover";
6100
+ }
6101
+ if ((_e = this.config) == null ? void 0 : _e.overlayLayers) {
6102
+ const logLoadError = (imageUrl) => {
6103
+ console.error(`Failed to load overlay image: ${imageUrl}`);
6104
+ };
6105
+ for (const layer of this.config.overlayLayers) {
6106
+ const overlayLayer = document.createElement("div");
6107
+ overlayLayer.style.position = "absolute";
6108
+ overlayLayer.style.background = `url(${layer.overlayImageUrl}) no-repeat`;
6109
+ overlayLayer.style.backgroundSize = "contain";
6110
+ const anchor = layer.overlayAnchor;
6111
+ const offsetX = ((_f = layer.overlayOffset) == null ? void 0 : _f.x) || 0;
6112
+ const offsetY = ((_g = layer.overlayOffset) == null ? void 0 : _g.y) || 0;
6113
+ if (anchor.includes("top")) {
6114
+ overlayLayer.style.top = `${offsetY}px`;
6115
+ } else if (anchor.includes("bottom")) {
6116
+ overlayLayer.style.bottom = `${offsetY}px`;
6117
+ }
6118
+ if (anchor.includes("left")) {
6119
+ overlayLayer.style.left = `${offsetX}px`;
6120
+ } else if (anchor.includes("right")) {
6121
+ overlayLayer.style.right = `${offsetX}px`;
6122
+ }
6123
+ const image = new Image();
6124
+ image.src = layer.overlayImageUrl;
6125
+ image.onload = () => {
6126
+ const naturalWidth = image.naturalWidth;
6127
+ const naturalHeight = image.naturalHeight;
6128
+ overlayLayer.style.width = `${naturalWidth}px`;
6129
+ overlayLayer.style.height = `${naturalHeight}px`;
6130
+ };
6131
+ image.onerror = () => logLoadError(layer.overlayImageUrl);
6132
+ this.overlayLayers.push(overlayLayer);
6133
+ this.backgroundBlur.append(overlayLayer);
6134
+ }
6135
+ }
6136
+ this.element.style.color = ((_h = this.config) == null ? void 0 : _h.color) || "white";
6137
+ this.loadingBanner = document.createElement("div");
6138
+ this.loadingBanner.style.position = "absolute";
6139
+ this.loadingBanner.style.display = "flex";
6140
+ this.loadingBanner.style.flexDirection = "column";
6141
+ this.loadingBanner.style.left = "0";
6142
+ this.loadingBanner.style.bottom = "0";
6143
+ this.loadingBanner.style.padding = "0";
6144
+ this.loadingBanner.style.width = "100%";
6145
+ this.loadingBanner.style.justifyContent = "flex-end";
6146
+ this.backgroundBlur.append(this.loadingBanner);
6147
+ if ((_i = this.config) == null ? void 0 : _i.title) {
6148
+ this.loadingBannerTitle = document.createElement("div");
6149
+ this.loadingBannerTitle.textContent = this.config.title;
6150
+ this.loadingBannerTitle.style.color = ((_j = this.config) == null ? void 0 : _j.color) || "white";
6151
+ this.loadingBannerTitle.style.paddingLeft = "40px";
6152
+ this.loadingBannerTitle.style.paddingRight = "40px";
6153
+ this.loadingBannerTitle.style.fontSize = "42px";
6154
+ this.loadingBannerTitle.style.fontWeight = "bold";
6155
+ this.loadingBannerTitle.style.fontFamily = "sans-serif";
6156
+ if ((_k = this.config) == null ? void 0 : _k.background) {
6157
+ this.loadingBannerTitle.style.textShadow = `0px 0px 80px ${this.config.background}`;
6158
+ }
6159
+ this.loadingBanner.append(this.loadingBannerTitle);
6160
+ }
6161
+ if ((_l = this.config) == null ? void 0 : _l.subtitle) {
6162
+ this.loadingBannerSubtitle = document.createElement("div");
6163
+ this.loadingBannerSubtitle.style.color = ((_m = this.config) == null ? void 0 : _m.color) || "white";
6164
+ this.loadingBannerSubtitle.style.paddingLeft = "40px";
6165
+ this.loadingBannerSubtitle.style.paddingRight = "40px";
6166
+ this.loadingBannerSubtitle.style.fontSize = "16px";
6167
+ this.loadingBannerSubtitle.style.fontWeight = "400";
6168
+ this.loadingBannerSubtitle.style.fontFamily = "sans-serif";
6169
+ this.loadingBannerSubtitle.style.marginTop = "12px";
6170
+ if ((_n = this.config) == null ? void 0 : _n.background) {
6171
+ this.loadingBannerSubtitle.style.textShadow = `0px 0px 40px ${this.config.background}`;
6172
+ }
6173
+ this.loadingBannerSubtitle.textContent = this.config.subtitle;
6174
+ this.loadingBanner.append(this.loadingBannerSubtitle);
6175
+ }
5954
6176
  this.progressDebugViewHolder = document.createElement("div");
5955
- this.progressDebugViewHolder.style.display = "flex";
6177
+ this.progressDebugViewHolder.style.display = "none";
5956
6178
  this.progressDebugViewHolder.style.position = "absolute";
5957
- this.progressDebugViewHolder.style.maxHeight = "calc(100% - 74px)";
5958
- this.progressDebugViewHolder.style.left = "0";
5959
- this.progressDebugViewHolder.style.bottom = "74px";
5960
- this.progressDebugViewHolder.style.width = "100%";
6179
+ this.progressDebugViewHolder.style.width = "calc(100% - 80px)";
6180
+ this.progressDebugViewHolder.style.maxHeight = "calc(100% - 120px)";
6181
+ this.progressDebugViewHolder.style.left = "40px";
6182
+ this.progressDebugViewHolder.style.bottom = "60px";
6183
+ this.progressDebugViewHolder.style.alignItems = "center";
5961
6184
  this.progressDebugViewHolder.style.justifyContent = "center";
6185
+ this.progressDebugViewHolder.style.zIndex = "10003";
5962
6186
  this.element.append(this.progressDebugViewHolder);
5963
6187
  this.progressDebugView = document.createElement("div");
5964
- this.progressDebugView.style.backgroundColor = "rgba(128, 128, 128, 0.25)";
6188
+ this.progressDebugView.style.backgroundColor = "rgba(128, 128, 128, 0.5)";
5965
6189
  this.progressDebugView.style.border = "1px solid black";
6190
+ this.progressDebugView.style.borderRadius = "7px";
6191
+ this.progressDebugView.style.width = "100%";
5966
6192
  this.progressDebugView.style.maxWidth = "100%";
5967
6193
  this.progressDebugView.style.overflow = "auto";
5968
6194
  this.progressDebugViewHolder.append(this.progressDebugView);
@@ -5971,6 +6197,8 @@ var LoadingScreen = class {
5971
6197
  this.debugCheckbox.checked = false;
5972
6198
  this.debugCheckbox.addEventListener("change", () => {
5973
6199
  this.progressDebugElement.style.display = this.debugCheckbox.checked ? "block" : "none";
6200
+ this.loadingBannerTitle.style.display = this.debugCheckbox.checked ? "none" : "flex";
6201
+ this.loadingBannerSubtitle.style.display = this.debugCheckbox.checked ? "none" : "flex";
5974
6202
  if (this.hasCompleted) {
5975
6203
  this.dispose();
5976
6204
  }
@@ -5989,23 +6217,36 @@ var LoadingScreen = class {
5989
6217
  this.progressDebugView.append(this.progressDebugElement);
5990
6218
  this.progressBarHolder = document.createElement("div");
5991
6219
  this.progressBarHolder.style.display = "flex";
5992
- this.progressBarHolder.style.alignItems = "center";
5993
- this.progressBarHolder.style.justifyContent = "center";
5994
- this.progressBarHolder.style.position = "absolute";
5995
- this.progressBarHolder.style.bottom = "20px";
5996
- this.progressBarHolder.style.left = "0";
6220
+ this.progressBarHolder.style.alignItems = "start";
6221
+ this.progressBarHolder.style.justifyContent = "flex-start";
5997
6222
  this.progressBarHolder.style.width = "100%";
5998
- this.element.append(this.progressBarHolder);
6223
+ this.progressBarHolder.style.marginLeft = "40px";
6224
+ this.progressBarHolder.style.marginBottom = "40px";
6225
+ this.progressBarHolder.style.cursor = "pointer";
6226
+ this.progressBarHolder.style.marginTop = "24px";
6227
+ this.loadingBanner.append(this.progressBarHolder);
5999
6228
  this.progressBarBackground = document.createElement("div");
6000
6229
  this.progressBarBackground.style.position = "relative";
6001
- this.progressBarBackground.style.width = "500px";
6002
- this.progressBarBackground.style.maxWidth = "80%";
6003
- this.progressBarBackground.style.backgroundColor = "gray";
6004
- this.progressBarBackground.style.height = "50px";
6005
- this.progressBarBackground.style.lineHeight = "50px";
6006
- this.progressBarBackground.style.borderRadius = "25px";
6007
- this.progressBarBackground.style.border = "2px solid white";
6230
+ this.progressBarBackground.style.width = "80%";
6231
+ this.progressBarBackground.style.maxWidth = "400px";
6232
+ this.progressBarBackground.style.minWidth = "240px";
6233
+ this.progressBarBackground.style.backgroundColor = "rgba(32,32,32, 0.25)";
6234
+ this.progressBarBackground.style.backdropFilter = "blur(4px)";
6235
+ this.progressBarBackground.style.height = "16px";
6236
+ this.progressBarBackground.style.lineHeight = "16px";
6237
+ this.progressBarBackground.style.borderRadius = "16px";
6008
6238
  this.progressBarBackground.style.overflow = "hidden";
6239
+ this.progressBarBackground.addEventListener("click", () => {
6240
+ const display = this.progressDebugViewHolder.style.display;
6241
+ if (display === "none") {
6242
+ this.progressDebugViewHolder.style.display = "flex";
6243
+ } else {
6244
+ this.progressDebugViewHolder.style.display = "none";
6245
+ this.debugCheckbox.checked = false;
6246
+ this.progressDebugElement.style.display = this.debugCheckbox.checked ? "block" : "none";
6247
+ this.loadingBannerTitle.style.display = this.debugCheckbox.checked ? "none" : "flex";
6248
+ }
6249
+ });
6009
6250
  this.progressBarHolder.append(this.progressBarBackground);
6010
6251
  this.progressBar = document.createElement("div");
6011
6252
  this.progressBar.style.position = "absolute";
@@ -6013,7 +6254,8 @@ var LoadingScreen = class {
6013
6254
  this.progressBar.style.left = "0";
6014
6255
  this.progressBar.style.width = "0";
6015
6256
  this.progressBar.style.height = "100%";
6016
- this.progressBar.style.backgroundColor = "#0050a4";
6257
+ this.progressBar.style.pointerEvents = "none";
6258
+ this.progressBar.style.backgroundColor = ((_o = this.config) == null ? void 0 : _o.color) || "#0050a4";
6017
6259
  this.progressBarBackground.append(this.progressBar);
6018
6260
  this.loadingStatusText = document.createElement("div");
6019
6261
  this.loadingStatusText.style.position = "absolute";
@@ -6021,11 +6263,14 @@ var LoadingScreen = class {
6021
6263
  this.loadingStatusText.style.left = "0";
6022
6264
  this.loadingStatusText.style.width = "100%";
6023
6265
  this.loadingStatusText.style.height = "100%";
6024
- this.loadingStatusText.style.color = "white";
6266
+ this.loadingStatusText.style.color = "rgba(200,200,200,0.9)";
6267
+ this.loadingStatusText.style.fontSize = "10px";
6025
6268
  this.loadingStatusText.style.textAlign = "center";
6026
6269
  this.loadingStatusText.style.verticalAlign = "middle";
6270
+ this.loadingStatusText.style.mixBlendMode = "difference";
6027
6271
  this.loadingStatusText.style.fontFamily = "sans-serif";
6028
6272
  this.loadingStatusText.style.fontWeight = "bold";
6273
+ this.loadingStatusText.style.userSelect = "none";
6029
6274
  this.loadingStatusText.textContent = "Loading...";
6030
6275
  this.progressBarBackground.append(this.loadingStatusText);
6031
6276
  this.loadingCallback = () => {
@@ -6040,7 +6285,7 @@ var LoadingScreen = class {
6040
6285
  this.loadingStatusText.textContent = "Completed";
6041
6286
  this.progressBar.style.width = "100%";
6042
6287
  } else {
6043
- this.loadingStatusText.textContent = `Loading... ${(loadingRatio * 100).toFixed(2)}%`;
6288
+ this.loadingStatusText.textContent = `${(loadingRatio * 100).toFixed(2)}%`;
6044
6289
  this.progressBar.style.width = `${loadingRatio * 100}%`;
6045
6290
  }
6046
6291
  this.progressDebugElement.textContent = LoadingProgressManager2.LoadingProgressSummaryToString(
@@ -6100,6 +6345,7 @@ export {
6100
6345
  Composer,
6101
6346
  ErrorScreen,
6102
6347
  GroundPlane,
6348
+ Key,
6103
6349
  KeyInputManager,
6104
6350
  LoadingScreen,
6105
6351
  MMLCompositionScene,