@mml-io/3d-web-client-core 0.8.0 → 0.9.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
@@ -41,6 +41,47 @@ var remap = (value, minValue, maxValue, minScaledValue, maxScaledValue) => {
41
41
  return minScaledValue + (maxScaledValue - minScaledValue) * (value - minValue) / (maxValue - minValue);
42
42
  };
43
43
 
44
+ // src/input/EventHandlerCollection.ts
45
+ var EventHandlerCollection = class _EventHandlerCollection {
46
+ constructor() {
47
+ this.eventsByTarget = /* @__PURE__ */ new Map();
48
+ }
49
+ add(target, key, listener, options) {
50
+ target.addEventListener(key, listener, options);
51
+ let existingTarget = this.eventsByTarget.get(target);
52
+ if (existingTarget === void 0) {
53
+ existingTarget = /* @__PURE__ */ new Map();
54
+ this.eventsByTarget.set(target, existingTarget);
55
+ }
56
+ let existingKey = existingTarget.get(key);
57
+ if (existingKey === void 0) {
58
+ existingKey = /* @__PURE__ */ new Set();
59
+ existingTarget.set(key, existingKey);
60
+ }
61
+ existingKey.add(listener);
62
+ return this;
63
+ }
64
+ clear() {
65
+ this.eventsByTarget.forEach((keyMap, target) => {
66
+ keyMap.forEach((listenerSet, key) => {
67
+ listenerSet.forEach((listenerFunc) => {
68
+ target.removeEventListener(key, listenerFunc);
69
+ });
70
+ });
71
+ });
72
+ this.eventsByTarget.clear();
73
+ }
74
+ static create(initial) {
75
+ const instance = new _EventHandlerCollection();
76
+ if (initial !== void 0) {
77
+ initial.forEach(([target, key, listenerFunc, options]) => {
78
+ instance.add(target, key, listenerFunc, options);
79
+ });
80
+ }
81
+ return instance;
82
+ }
83
+ };
84
+
44
85
  // src/tweakpane/tweakPaneActivity.ts
45
86
  var isTweakpaneActive = false;
46
87
  function setTweakpaneActive(status) {
@@ -52,7 +93,7 @@ function getTweakpaneActive() {
52
93
 
53
94
  // src/camera/CameraManager.ts
54
95
  var CameraManager = class {
55
- constructor(collisionsManager) {
96
+ constructor(targetElement, collisionsManager, initialPhi = Math.PI / 2, initialTheta = -Math.PI / 2) {
56
97
  this.collisionsManager = collisionsManager;
57
98
  this.initialDistance = 3.3;
58
99
  this.minDistance = 0.1;
@@ -68,42 +109,38 @@ var CameraManager = class {
68
109
  this.targetDistance = this.initialDistance;
69
110
  this.distance = this.initialDistance;
70
111
  this.desiredDistance = this.initialDistance;
71
- this.targetPhi = Math.PI / 2;
72
- this.phi = Math.PI / 2;
73
- this.targetTheta = -Math.PI / 2;
74
- this.theta = -Math.PI / 2;
75
112
  this.dragging = false;
76
113
  this.target = new Vector32(0, 1.55, 0);
77
114
  this.hadTarget = false;
115
+ this.phi = initialPhi;
116
+ this.targetPhi = initialPhi;
117
+ this.theta = initialTheta;
118
+ this.targetTheta = initialTheta;
78
119
  this.camera = new PerspectiveCamera(this.fov, window.innerWidth / window.innerHeight, 0.1, 400);
79
120
  this.camera.position.set(0, 1.4, -this.initialDistance);
80
121
  this.rayCaster = new Raycaster();
81
- document.addEventListener("mousedown", this.onMouseDown.bind(this));
82
- document.addEventListener("mouseup", this.onMouseUp.bind(this));
83
- document.addEventListener("mousemove", this.onMouseMove.bind(this));
84
- document.addEventListener("wheel", this.onMouseWheel.bind(this));
85
- window.addEventListener("resize", this.onResize.bind(this));
86
- }
87
- onResize() {
88
- const width = window.innerWidth;
89
- const height = window.innerHeight;
90
- this.camera.aspect = width / height;
91
- this.camera.updateProjectionMatrix();
92
- }
93
- onMouseDown(_event) {
122
+ this.eventHandlerCollection = EventHandlerCollection.create([
123
+ [targetElement, "mousedown", this.onMouseDown.bind(this)],
124
+ [document, "mouseup", this.onMouseUp.bind(this)],
125
+ [document, "mousemove", this.onMouseMove.bind(this)],
126
+ [targetElement, "wheel", this.onMouseWheel.bind(this)]
127
+ ]);
128
+ }
129
+ onMouseDown() {
94
130
  this.dragging = true;
95
131
  }
96
132
  onMouseUp(_event) {
97
133
  this.dragging = false;
98
134
  }
99
135
  onMouseMove(event) {
100
- if (!this.dragging || getTweakpaneActive() === true)
136
+ if (!this.dragging || getTweakpaneActive())
101
137
  return;
102
138
  if (this.targetTheta === null || this.targetPhi === null)
103
139
  return;
104
140
  this.targetTheta += event.movementX * 0.01;
105
141
  this.targetPhi -= event.movementY * 0.01;
106
142
  this.targetPhi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.targetPhi));
143
+ event.preventDefault();
107
144
  }
108
145
  onMouseWheel(event) {
109
146
  const scrollAmount = event.deltaY * 1e-3;
@@ -113,6 +150,7 @@ var CameraManager = class {
113
150
  Math.min(this.maxDistance, this.targetDistance)
114
151
  );
115
152
  this.desiredDistance = this.targetDistance;
153
+ event.preventDefault();
116
154
  }
117
155
  setTarget(target) {
118
156
  this.target.copy(target);
@@ -148,6 +186,9 @@ var CameraManager = class {
148
186
  this.targetDistance += (this.desiredDistance - this.targetDistance) * this.dampingFactor * 4;
149
187
  }
150
188
  }
189
+ dispose() {
190
+ this.eventHandlerCollection.clear();
191
+ }
151
192
  update() {
152
193
  if (this.target === null)
153
194
  return;
@@ -181,11 +222,11 @@ import { Color as Color3, Vector3 as Vector35 } from "three";
181
222
 
182
223
  // src/character/CharacterModel.ts
183
224
  import {
184
- AnimationClip as AnimationClip2,
225
+ AnimationClip,
185
226
  AnimationMixer,
186
227
  LoopRepeat,
187
228
  MeshStandardMaterial,
188
- Object3D as Object3D2
229
+ Object3D
189
230
  } from "three";
190
231
 
191
232
  // src/character/CharacterMaterial.ts
@@ -560,126 +601,11 @@ var AnimationState = /* @__PURE__ */ ((AnimationState2) => {
560
601
  return AnimationState2;
561
602
  })(AnimationState || {});
562
603
 
563
- // src/character/ModelLoader.ts
564
- import { LoadingManager } from "three";
565
- import { GLTFLoader as ThreeGLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
566
- var CachedGLTFLoader = class extends ThreeGLTFLoader {
567
- constructor(manager) {
568
- super(manager);
569
- this.blobCache = /* @__PURE__ */ new Map();
570
- }
571
- setBlobUrl(originalUrl, blobUrl) {
572
- this.blobCache.set(originalUrl, blobUrl);
573
- }
574
- getBlobUrl(originalUrl) {
575
- return this.blobCache.get(originalUrl);
576
- }
577
- load(url, onLoad, onProgress, onError) {
578
- const blobUrl = this.getBlobUrl(url);
579
- if (blobUrl) {
580
- console.log(`Loading cached ${url.split("/").pop()}`);
581
- super.load(blobUrl, onLoad, onProgress, onError);
582
- } else {
583
- super.load(url, onLoad, onProgress, onError);
584
- }
585
- }
586
- };
587
- var LRUCache = class {
588
- constructor(maxSize = 100) {
589
- this.maxSize = maxSize;
590
- this.cache = /* @__PURE__ */ new Map();
591
- }
592
- get(key) {
593
- const item = this.cache.get(key);
594
- if (item) {
595
- this.cache.delete(key);
596
- this.cache.set(key, item);
597
- }
598
- return item;
599
- }
600
- set(key, value) {
601
- if (this.cache.size >= this.maxSize) {
602
- const oldestKey = this.cache.keys().next().value;
603
- this.cache.delete(oldestKey);
604
- }
605
- this.cache.set(key, value);
606
- }
607
- };
608
- var _ModelLoader = class _ModelLoader {
609
- constructor(maxCacheSize = 100) {
610
- this.ongoingLoads = /* @__PURE__ */ new Map();
611
- this.loadingManager = new LoadingManager();
612
- this.gltfLoader = new CachedGLTFLoader(this.loadingManager);
613
- this.modelCache = new LRUCache(maxCacheSize);
614
- }
615
- /* TODO: decide between below lazy initialization or eager on this file's bottom export */
616
- static getInstance() {
617
- if (!_ModelLoader.instance) {
618
- _ModelLoader.instance = new _ModelLoader();
619
- }
620
- return _ModelLoader.instance;
621
- }
622
- async load(fileUrl, fileType) {
623
- const cachedModel = this.modelCache.get(fileUrl);
624
- if (cachedModel) {
625
- const blobURL = URL.createObjectURL(cachedModel.blob);
626
- this.gltfLoader.setBlobUrl(fileUrl, blobURL);
627
- return this.loadFromUrl(fileUrl, fileType, cachedModel.originalExtension);
628
- } else {
629
- console.log(`Loading ${fileUrl} from server`);
630
- const ongoingLoad = this.ongoingLoads.get(fileUrl);
631
- if (ongoingLoad)
632
- return ongoingLoad;
633
- const loadPromise = fetch(fileUrl).then((response) => response.blob()).then((blob) => {
634
- const originalExtension = fileUrl.split(".").pop() || "";
635
- this.modelCache.set(fileUrl, { blob, originalExtension });
636
- const blobURL = URL.createObjectURL(blob);
637
- this.ongoingLoads.delete(fileUrl);
638
- return this.loadFromUrl(blobURL, fileType, originalExtension);
639
- });
640
- this.ongoingLoads.set(fileUrl, loadPromise);
641
- return loadPromise;
642
- }
643
- }
644
- async loadFromUrl(url, fileType, extension) {
645
- if (["gltf", "glb"].includes(extension)) {
646
- return new Promise((resolve, reject) => {
647
- this.gltfLoader.load(
648
- url,
649
- (object) => {
650
- if (fileType === "model") {
651
- resolve(object.scene);
652
- } else if (fileType === "animation") {
653
- resolve(object.animations[0]);
654
- } else {
655
- const error = `Trying to load unknown ${fileType} type of element from file ${url}`;
656
- console.error(error);
657
- reject(error);
658
- }
659
- },
660
- void 0,
661
- (error) => {
662
- console.error(`Error loading GL(B|TF) from ${url}: ${error}`);
663
- reject(error);
664
- }
665
- );
666
- });
667
- } else {
668
- console.error(`Error: can't recognize ${url} extension: ${extension}`);
669
- }
670
- }
671
- };
672
- _ModelLoader.instance = null;
673
- var ModelLoader = _ModelLoader;
674
- var MODEL_LOADER = ModelLoader.getInstance();
675
- var ModelLoader_default = MODEL_LOADER;
676
-
677
604
  // src/character/CharacterModel.ts
678
605
  var CharacterModel = class {
679
- constructor(characterDescription) {
606
+ constructor(characterDescription, characterModelLoader) {
680
607
  this.characterDescription = characterDescription;
681
- /* TODO: pick between below eager instantiation or ModelLoader.getInstance() lazy one */
682
- this.modelLoader = ModelLoader_default;
608
+ this.characterModelLoader = characterModelLoader;
683
609
  this.mesh = null;
684
610
  this.material = new CharacterMaterial();
685
611
  this.headBone = null;
@@ -757,9 +683,9 @@ var CharacterModel = class {
757
683
  const scale = this.characterDescription.modelScale;
758
684
  const extension = mainMeshUrl.split(".").pop();
759
685
  const name = mainMeshUrl.split("/").pop().replace(`.${extension}`, "");
760
- const mainMesh = await this.modelLoader.load(mainMeshUrl, "model");
686
+ const mainMesh = await this.characterModelLoader.load(mainMeshUrl, "model");
761
687
  if (typeof mainMesh !== "undefined") {
762
- this.mesh = new Object3D2();
688
+ this.mesh = new Object3D();
763
689
  const model = mainMesh;
764
690
  model.position.set(0, -0.4, 0);
765
691
  this.mesh.add(model);
@@ -771,8 +697,8 @@ var CharacterModel = class {
771
697
  async setAnimationFromFile(animationFileUrl, animationType) {
772
698
  return new Promise(async (resolve, reject) => {
773
699
  this.initAnimationMixer();
774
- const animation = await this.modelLoader.load(animationFileUrl, "animation");
775
- if (typeof animation !== "undefined" && animation instanceof AnimationClip2) {
700
+ const animation = await this.characterModelLoader.load(animationFileUrl, "animation");
701
+ if (typeof animation !== "undefined" && animation instanceof AnimationClip) {
776
702
  this.animations[animationType] = this.animationMixer.clipAction(animation);
777
703
  this.animations[animationType].stop();
778
704
  if (animationType === 0 /* idle */) {
@@ -1304,7 +1230,6 @@ var LocalController = class {
1304
1230
  this.characterVelocity.y = deltaTime * this.gravity;
1305
1231
  }
1306
1232
  } else if (this.jump && this.coyoteTime) {
1307
- console.log("coyoteJump");
1308
1233
  this.characterVelocity.y = this.jumpForce;
1309
1234
  this.canJump = false;
1310
1235
  } else {
@@ -1394,8 +1319,9 @@ var LocalController = class {
1394
1319
 
1395
1320
  // src/character/Character.ts
1396
1321
  var Character = class {
1397
- constructor(characterDescription, id, isLocal, modelLoadedCallback, collisionsManager, keyInputManager, cameraManager, timeManager, composer) {
1322
+ constructor(characterDescription, characterModelLoader, id, isLocal, modelLoadedCallback, collisionsManager, keyInputManager, cameraManager, timeManager, composer) {
1398
1323
  this.characterDescription = characterDescription;
1324
+ this.characterModelLoader = characterModelLoader;
1399
1325
  this.id = id;
1400
1326
  this.isLocal = isLocal;
1401
1327
  this.modelLoadedCallback = modelLoadedCallback;
@@ -1414,7 +1340,7 @@ var Character = class {
1414
1340
  this.load();
1415
1341
  }
1416
1342
  async load() {
1417
- this.model = new CharacterModel(this.characterDescription);
1343
+ this.model = new CharacterModel(this.characterDescription, this.characterModelLoader);
1418
1344
  await this.model.init();
1419
1345
  if (this.tooltip === null) {
1420
1346
  this.tooltip = new CharacterTooltip(this.model.mesh);
@@ -1461,22 +1387,22 @@ var Character = class {
1461
1387
  };
1462
1388
 
1463
1389
  // src/character/CharacterManager.ts
1464
- import { Group, Vector3 as Vector37 } from "three";
1390
+ import { Euler, Group, Quaternion as Quaternion4, Vector3 as Vector37 } from "three";
1465
1391
 
1466
1392
  // src/character/RemoteController.ts
1467
1393
  import {
1468
1394
  AnimationMixer as AnimationMixer2,
1469
- Object3D as Object3D5,
1395
+ Object3D as Object3D4,
1470
1396
  Quaternion as Quaternion3,
1471
1397
  Vector3 as Vector36
1472
1398
  } from "three";
1473
1399
  var RemoteController = class {
1474
- constructor(character, id) {
1400
+ constructor(character, characterModelLoader, id) {
1475
1401
  this.character = character;
1402
+ this.characterModelLoader = characterModelLoader;
1476
1403
  this.id = id;
1477
- this.modelLoader = ModelLoader_default;
1478
1404
  this.characterModel = null;
1479
- this.animationMixer = new AnimationMixer2(new Object3D5());
1405
+ this.animationMixer = new AnimationMixer2(new Object3D4());
1480
1406
  this.animations = /* @__PURE__ */ new Map();
1481
1407
  this.currentAnimation = 0 /* idle */;
1482
1408
  this.characterModel = this.character.model.mesh;
@@ -1497,7 +1423,7 @@ var RemoteController = class {
1497
1423
  this.animationMixer.update(deltaTime);
1498
1424
  }
1499
1425
  async setAnimationFromFile(animationType, fileName) {
1500
- const animation = await this.modelLoader.load(fileName, "animation");
1426
+ const animation = await this.characterModelLoader.load(fileName, "animation");
1501
1427
  const animationAction = this.animationMixer.clipAction(animation);
1502
1428
  this.animations.set(animationType, animationAction);
1503
1429
  if (animationType === 0 /* idle */) {
@@ -1550,8 +1476,9 @@ function decodeCharacterAndCamera(hash, character, camera) {
1550
1476
  camera.quaternion.fromArray(values.slice(10, 14));
1551
1477
  }
1552
1478
  var CharacterManager = class {
1553
- constructor(composer, collisionsManager, cameraManager, timeManager, inputManager, clientStates, sendUpdate) {
1479
+ constructor(composer, characterModelLoader, collisionsManager, cameraManager, timeManager, inputManager, clientStates, sendUpdate) {
1554
1480
  this.composer = composer;
1481
+ this.characterModelLoader = characterModelLoader;
1555
1482
  this.collisionsManager = collisionsManager;
1556
1483
  this.cameraManager = cameraManager;
1557
1484
  this.timeManager = timeManager;
@@ -1581,11 +1508,12 @@ var CharacterManager = class {
1581
1508
  the mesh loading async (would allow us to show a nameplate where a remote
1582
1509
  user is before the asset loads).
1583
1510
  */
1584
- spawnCharacter(characterDescription, id, isLocal = false, spawnPosition = new Vector37()) {
1511
+ spawnCharacter(characterDescription, id, isLocal = false, spawnPosition = new Vector37(), spawnRotation = new Euler()) {
1585
1512
  this.characterDescription = characterDescription;
1586
1513
  const characterLoadingPromise = new Promise((resolve) => {
1587
1514
  const character = new Character(
1588
1515
  characterDescription,
1516
+ this.characterModelLoader,
1589
1517
  id,
1590
1518
  isLocal,
1591
1519
  () => {
@@ -1597,9 +1525,12 @@ var CharacterManager = class {
1597
1525
  this.cameraManager.camera
1598
1526
  );
1599
1527
  } else {
1600
- spawnPosition = getSpawnPositionInsideCircle(3, 30, id, 0.4);
1528
+ spawnPosition = spawnPosition || getSpawnPositionInsideCircle(3, 30, id, 0.4);
1601
1529
  character.model.mesh.position.set(spawnPosition.x, spawnPosition.y, spawnPosition.z);
1530
+ character.model.mesh.rotation.set(spawnRotation.x, spawnRotation.y, spawnRotation.z);
1531
+ character.position.set(spawnPosition.x, spawnPosition.y, spawnPosition.z);
1602
1532
  character.model.mesh.updateMatrixWorld();
1533
+ const quaternion = new Quaternion4().setFromEuler(character.model.mesh.rotation);
1603
1534
  this.sendUpdate({
1604
1535
  id,
1605
1536
  position: {
@@ -1607,7 +1538,7 @@ var CharacterManager = class {
1607
1538
  y: spawnPosition.y,
1608
1539
  z: spawnPosition.z
1609
1540
  },
1610
- rotation: { quaternionY: 0, quaternionW: 1 },
1541
+ rotation: { quaternionY: quaternion.y, quaternionW: quaternion.w },
1611
1542
  state: 0 /* idle */
1612
1543
  });
1613
1544
  }
@@ -1624,7 +1555,7 @@ var CharacterManager = class {
1624
1555
  (_e = this.character.tooltip) == null ? void 0 : _e.setText(`${id}`);
1625
1556
  } else {
1626
1557
  this.remoteCharacters.set(id, character);
1627
- const remoteController = new RemoteController(character, id);
1558
+ const remoteController = new RemoteController(character, this.characterModelLoader, id);
1628
1559
  remoteController.setAnimationFromFile(
1629
1560
  0 /* idle */,
1630
1561
  characterDescription.idleAnimationFileUrl
@@ -1747,19 +1678,143 @@ var CharacterManager = class {
1747
1678
  }
1748
1679
  };
1749
1680
 
1681
+ // src/character/CharacterModelLoader.ts
1682
+ import { LoadingManager } from "three";
1683
+ import { GLTFLoader as ThreeGLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
1684
+ var CachedGLTFLoader = class extends ThreeGLTFLoader {
1685
+ constructor(manager) {
1686
+ super(manager);
1687
+ this.blobCache = /* @__PURE__ */ new Map();
1688
+ }
1689
+ setBlobUrl(originalUrl, blobUrl) {
1690
+ this.blobCache.set(originalUrl, blobUrl);
1691
+ }
1692
+ getBlobUrl(originalUrl) {
1693
+ return this.blobCache.get(originalUrl);
1694
+ }
1695
+ load(url, onLoad, onProgress, onError) {
1696
+ const blobUrl = this.getBlobUrl(url);
1697
+ if (blobUrl) {
1698
+ console.log(`Loading cached ${url.split("/").pop()}`);
1699
+ super.load(blobUrl, onLoad, onProgress, onError);
1700
+ } else {
1701
+ super.load(url, onLoad, onProgress, onError);
1702
+ }
1703
+ }
1704
+ };
1705
+ var LRUCache = class {
1706
+ constructor(maxSize = 100) {
1707
+ this.maxSize = maxSize;
1708
+ this.cache = /* @__PURE__ */ new Map();
1709
+ }
1710
+ get(key) {
1711
+ const item = this.cache.get(key);
1712
+ if (item) {
1713
+ this.cache.delete(key);
1714
+ this.cache.set(key, item);
1715
+ }
1716
+ return item;
1717
+ }
1718
+ set(key, value) {
1719
+ if (this.cache.size >= this.maxSize) {
1720
+ const oldestKey = this.cache.keys().next().value;
1721
+ this.cache.delete(oldestKey);
1722
+ }
1723
+ this.cache.set(key, value);
1724
+ }
1725
+ };
1726
+ var _CharacterModelLoader = class _CharacterModelLoader {
1727
+ constructor(maxCacheSize = 100) {
1728
+ this.ongoingLoads = /* @__PURE__ */ new Map();
1729
+ this.loadingManager = new LoadingManager();
1730
+ this.gltfLoader = new CachedGLTFLoader(this.loadingManager);
1731
+ this.modelCache = new LRUCache(maxCacheSize);
1732
+ }
1733
+ /* TODO: decide between below lazy initialization or eager on this file's bottom export */
1734
+ static getInstance() {
1735
+ if (!_CharacterModelLoader.instance) {
1736
+ _CharacterModelLoader.instance = new _CharacterModelLoader();
1737
+ }
1738
+ return _CharacterModelLoader.instance;
1739
+ }
1740
+ async load(fileUrl, fileType) {
1741
+ const cachedModel = this.modelCache.get(fileUrl);
1742
+ if (cachedModel) {
1743
+ const blobURL = URL.createObjectURL(cachedModel.blob);
1744
+ this.gltfLoader.setBlobUrl(fileUrl, blobURL);
1745
+ return this.loadFromUrl(fileUrl, fileType, cachedModel.originalExtension);
1746
+ } else {
1747
+ console.log(`Loading ${fileUrl} from server`);
1748
+ const ongoingLoad = this.ongoingLoads.get(fileUrl);
1749
+ if (ongoingLoad)
1750
+ return ongoingLoad;
1751
+ const loadPromise = fetch(fileUrl).then((response) => response.blob()).then((blob) => {
1752
+ const originalExtension = fileUrl.split(".").pop() || "";
1753
+ this.modelCache.set(fileUrl, { blob, originalExtension });
1754
+ const blobURL = URL.createObjectURL(blob);
1755
+ this.ongoingLoads.delete(fileUrl);
1756
+ return this.loadFromUrl(blobURL, fileType, originalExtension);
1757
+ });
1758
+ this.ongoingLoads.set(fileUrl, loadPromise);
1759
+ return loadPromise;
1760
+ }
1761
+ }
1762
+ async loadFromUrl(url, fileType, extension) {
1763
+ if (["gltf", "glb"].includes(extension)) {
1764
+ return new Promise((resolve, reject) => {
1765
+ this.gltfLoader.load(
1766
+ url,
1767
+ (object) => {
1768
+ if (fileType === "model") {
1769
+ resolve(object.scene);
1770
+ } else if (fileType === "animation") {
1771
+ resolve(object.animations[0]);
1772
+ } else {
1773
+ const error = `Trying to load unknown ${fileType} type of element from file ${url}`;
1774
+ console.error(error);
1775
+ reject(error);
1776
+ }
1777
+ },
1778
+ void 0,
1779
+ (error) => {
1780
+ console.error(`Error loading GL(B|TF) from ${url}: ${error}`);
1781
+ reject(error);
1782
+ }
1783
+ );
1784
+ });
1785
+ } else {
1786
+ console.error(`Error: can't recognize ${url} extension: ${extension}`);
1787
+ }
1788
+ }
1789
+ };
1790
+ _CharacterModelLoader.instance = null;
1791
+ var CharacterModelLoader = _CharacterModelLoader;
1792
+ var MODEL_LOADER = CharacterModelLoader.getInstance();
1793
+
1750
1794
  // src/input/KeyInputManager.ts
1751
1795
  var KeyInputManager = class {
1752
- constructor() {
1796
+ constructor(shouldCaptureKeyPress = () => true) {
1797
+ this.shouldCaptureKeyPress = shouldCaptureKeyPress;
1753
1798
  this.keys = /* @__PURE__ */ new Map();
1754
- document.addEventListener("keydown", this.onKeyDown.bind(this));
1755
- document.addEventListener("keyup", this.onKeyUp.bind(this));
1756
- window.addEventListener("blur", this.handleUnfocus.bind(this));
1799
+ this.eventHandlerCollection = new EventHandlerCollection();
1800
+ this.eventHandlerCollection.add(document, "keydown", this.onKeyDown.bind(this));
1801
+ this.eventHandlerCollection.add(document, "keyup", this.onKeyUp.bind(this));
1802
+ this.eventHandlerCollection.add(window, "blur", this.handleUnfocus.bind(this));
1757
1803
  }
1758
1804
  handleUnfocus(_event) {
1759
1805
  this.keys.clear();
1760
1806
  }
1761
1807
  onKeyDown(event) {
1762
- this.keys.set(event.key.toLowerCase(), true);
1808
+ if (this.shouldCaptureKeyPress()) {
1809
+ if (event.key.length === 2 && event.key[0] === "F") {
1810
+ return;
1811
+ }
1812
+ if (event.metaKey) {
1813
+ return;
1814
+ }
1815
+ this.keys.set(event.key.toLowerCase(), true);
1816
+ event.preventDefault();
1817
+ }
1763
1818
  }
1764
1819
  onKeyUp(event) {
1765
1820
  this.keys.set(event.key.toLowerCase(), false);
@@ -1768,36 +1823,34 @@ var KeyInputManager = class {
1768
1823
  return this.keys.get(key) || false;
1769
1824
  }
1770
1825
  isMovementKeyPressed() {
1771
- return ["w", "a", "s", "d"].some((key) => this.isKeyPressed(key));
1826
+ return ["w" /* W */, "a" /* A */, "s" /* S */, "d" /* D */].some((key) => this.isKeyPressed(key));
1772
1827
  }
1773
1828
  get forward() {
1774
- return this.isKeyPressed("w");
1829
+ return this.isKeyPressed("w" /* W */);
1775
1830
  }
1776
1831
  get backward() {
1777
- return this.isKeyPressed("s");
1832
+ return this.isKeyPressed("s" /* S */);
1778
1833
  }
1779
1834
  get left() {
1780
- return this.isKeyPressed("a");
1835
+ return this.isKeyPressed("a" /* A */);
1781
1836
  }
1782
1837
  get right() {
1783
- return this.isKeyPressed("d");
1838
+ return this.isKeyPressed("d" /* D */);
1784
1839
  }
1785
1840
  get run() {
1786
- return this.isKeyPressed("shift");
1841
+ return this.isKeyPressed("shift" /* SHIFT */);
1787
1842
  }
1788
1843
  get jump() {
1789
- return this.isKeyPressed(" ");
1844
+ return this.isKeyPressed(" " /* SPACE */);
1790
1845
  }
1791
1846
  get anyDirection() {
1792
1847
  return this.isMovementKeyPressed();
1793
1848
  }
1794
1849
  get conflictingDirection() {
1795
- return this.isKeyPressed("w") && this.isKeyPressed("s") || this.isKeyPressed("a") && this.isKeyPressed("d");
1850
+ return this.isKeyPressed("w" /* W */) && this.isKeyPressed("s" /* S */) || this.isKeyPressed("a" /* A */) && this.isKeyPressed("d" /* D */);
1796
1851
  }
1797
1852
  dispose() {
1798
- document.removeEventListener("keydown", this.onKeyDown.bind(this));
1799
- document.removeEventListener("keyup", this.onKeyDown.bind(this));
1800
- window.removeEventListener("blur", this.handleUnfocus.bind(this));
1853
+ this.eventHandlerCollection.clear();
1801
1854
  }
1802
1855
  };
1803
1856
 
@@ -1805,23 +1858,25 @@ var KeyInputManager = class {
1805
1858
  import {
1806
1859
  InteractionManager,
1807
1860
  MMLClickTrigger,
1808
- PromptManager,
1809
- registerCustomElementsToWindow,
1810
- setGlobalMScene
1861
+ PromptManager
1811
1862
  } from "mml-web";
1812
1863
  import { Group as Group2 } from "three";
1813
1864
  var MMLCompositionScene = class {
1814
- constructor(renderer, scene, camera, audioListener, collisionsManager, getUserPositionAndRotation, documentAddresses) {
1865
+ constructor(targetElement, renderer, scene, camera, audioListener, collisionsManager, getUserPositionAndRotation) {
1815
1866
  this.renderer = renderer;
1816
1867
  this.scene = scene;
1817
1868
  this.camera = camera;
1818
1869
  this.audioListener = audioListener;
1819
1870
  this.collisionsManager = collisionsManager;
1820
1871
  this.getUserPositionAndRotation = getUserPositionAndRotation;
1821
- this.debug = false;
1822
1872
  this.group = new Group2();
1823
- this.promptManager = PromptManager.init(document.body);
1824
- const { interactionListener } = InteractionManager.init(document.body, this.camera, this.scene);
1873
+ this.promptManager = PromptManager.init(targetElement);
1874
+ const { interactionListener, interactionManager } = InteractionManager.init(
1875
+ targetElement,
1876
+ this.camera,
1877
+ this.scene
1878
+ );
1879
+ this.interactionManager = interactionManager;
1825
1880
  this.interactionListener = interactionListener;
1826
1881
  this.mmlScene = {
1827
1882
  getAudioListener: () => this.audioListener,
@@ -1852,55 +1907,65 @@ var MMLCompositionScene = class {
1852
1907
  this.promptManager.prompt(promptProps, callback);
1853
1908
  }
1854
1909
  };
1855
- setGlobalMScene(this.mmlScene);
1856
- registerCustomElementsToWindow(window);
1857
- this.clickTrigger = MMLClickTrigger.init(document, this.mmlScene);
1858
- if (this.debug) {
1859
- console.log(this.clickTrigger);
1860
- }
1861
- for (const address of documentAddresses) {
1862
- const frameElement = document.createElement("m-frame");
1863
- frameElement.setAttribute("src", address);
1864
- document.body.appendChild(frameElement);
1865
- }
1910
+ this.clickTrigger = MMLClickTrigger.init(targetElement, this.mmlScene);
1911
+ }
1912
+ dispose() {
1913
+ this.promptManager.dispose();
1914
+ this.clickTrigger.dispose();
1915
+ this.interactionManager.dispose();
1866
1916
  }
1867
1917
  };
1868
1918
 
1869
- // src/rendering/composer.ts
1870
- import { N8AOPostPass } from "n8ao";
1871
- import {
1872
- EffectComposer as EffectComposer2,
1873
- RenderPass,
1874
- EffectPass as EffectPass2,
1875
- FXAAEffect,
1876
- ShaderPass,
1877
- BloomEffect,
1878
- SSAOEffect as SSAOEffect2,
1879
- BlendFunction as BlendFunction2,
1880
- TextureEffect,
1881
- ToneMappingEffect,
1882
- SMAAEffect,
1883
- SMAAPreset,
1884
- EdgeDetectionMode,
1885
- PredicationMode,
1886
- NormalPass as NormalPass2
1887
- } from "postprocessing";
1888
- import {
1889
- AmbientLight,
1890
- Color as Color6,
1891
- Fog,
1892
- HalfFloatType,
1893
- LinearSRGBColorSpace,
1894
- LoadingManager as LoadingManager2,
1895
- PMREMGenerator,
1896
- Scene as Scene3,
1897
- Vector2 as Vector22,
1898
- WebGLRenderer as WebGLRenderer2
1899
- } from "three";
1900
- import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
1919
+ // src/tweakpane/TweakPane.ts
1920
+ import * as EssentialsPlugin from "@tweakpane/plugin-essentials";
1921
+ import { Pane } from "tweakpane";
1901
1922
 
1902
- // src/sun/Sun.ts
1903
- import { CameraHelper, Color as Color4, DirectionalLight, Group as Group3, OrthographicCamera, Vector3 as Vector38 } from "three";
1923
+ // src/tweakpane/blades/bcsFolder.ts
1924
+ var bcsValues = {
1925
+ brightness: 0,
1926
+ contrast: 1.25,
1927
+ saturation: 1
1928
+ };
1929
+ var bcsOptions = {
1930
+ brightness: {
1931
+ amount: { min: -1, max: 1, step: 0.01 }
1932
+ },
1933
+ contrast: {
1934
+ amount: { min: 0, max: 2, step: 0.01 }
1935
+ },
1936
+ saturation: {
1937
+ amount: { min: 0, max: 2, step: 0.01 }
1938
+ }
1939
+ };
1940
+ var BrightnessContrastSaturationFolder = class {
1941
+ constructor(parentFolder, expand = false) {
1942
+ this.folder = parentFolder.addFolder({
1943
+ title: "brightness / contrast / sat",
1944
+ expanded: expand
1945
+ });
1946
+ this.folder.addBinding(bcsValues, "brightness", bcsOptions.brightness.amount);
1947
+ this.folder.addBinding(bcsValues, "contrast", bcsOptions.contrast.amount);
1948
+ this.folder.addBinding(bcsValues, "saturation", bcsOptions.saturation.amount);
1949
+ }
1950
+ setupChangeEvent(brightnessContrastSaturation) {
1951
+ this.folder.on("change", (e) => {
1952
+ const target = e.target.key;
1953
+ if (!target)
1954
+ return;
1955
+ switch (target) {
1956
+ case "brightness":
1957
+ brightnessContrastSaturation.uniforms.brightness.value = e.value;
1958
+ break;
1959
+ case "contrast":
1960
+ brightnessContrastSaturation.uniforms.contrast.value = e.value;
1961
+ break;
1962
+ case "saturation":
1963
+ brightnessContrastSaturation.uniforms.saturation.value = e.value;
1964
+ break;
1965
+ }
1966
+ });
1967
+ }
1968
+ };
1904
1969
 
1905
1970
  // src/tweakpane/blades/environmentFolder.ts
1906
1971
  var sunValues = {
@@ -2057,135 +2122,6 @@ var EnvironmentFolder = class {
2057
2122
  }
2058
2123
  };
2059
2124
 
2060
- // src/sun/Sun.ts
2061
- var Sun = class extends Group3 {
2062
- constructor() {
2063
- super();
2064
- this.debug = false;
2065
- this.sunOffset = new Vector38(
2066
- 39 * (Math.PI / 180),
2067
- 50 * (Math.PI / 180),
2068
- 100
2069
- );
2070
- this.shadowResolution = 8192;
2071
- this.shadowCamFrustum = 50;
2072
- this.camHelper = null;
2073
- this.target = null;
2074
- this.shadowCamera = new OrthographicCamera(
2075
- -this.shadowCamFrustum,
2076
- this.shadowCamFrustum,
2077
- this.shadowCamFrustum,
2078
- -this.shadowCamFrustum,
2079
- 0.1,
2080
- 200
2081
- );
2082
- if (this.debug === true) {
2083
- this.camHelper = new CameraHelper(this.shadowCamera);
2084
- }
2085
- this.directionalLight = new DirectionalLight(16777215, 0.5);
2086
- this.directionalLight.shadow.normalBias = 0.05;
2087
- this.directionalLight.shadow.radius = 1.5;
2088
- this.directionalLight.shadow.camera = this.shadowCamera;
2089
- this.directionalLight.shadow.mapSize.set(this.shadowResolution, this.shadowResolution);
2090
- this.directionalLight.castShadow = true;
2091
- this.setColor();
2092
- this.updateCharacterPosition(new Vector38(0, 0, 0));
2093
- this.add(this.directionalLight);
2094
- if (this.debug === true && this.camHelper instanceof CameraHelper) {
2095
- this.add(this.camHelper);
2096
- }
2097
- }
2098
- updateCharacterPosition(position) {
2099
- if (!position)
2100
- return;
2101
- this.target = position;
2102
- this.setSunPosition(this.sunOffset.x, this.sunOffset.y);
2103
- }
2104
- setAzimuthalAngle(angle) {
2105
- if (this.sunOffset)
2106
- this.sunOffset.x = angle;
2107
- if (this.target)
2108
- this.updateCharacterPosition(this.target);
2109
- }
2110
- setPolarAngle(angle) {
2111
- if (this.sunOffset)
2112
- this.sunOffset.y = angle;
2113
- if (this.target)
2114
- this.updateCharacterPosition(this.target);
2115
- }
2116
- setIntensity(intensity) {
2117
- this.directionalLight.intensity = intensity;
2118
- }
2119
- setColor() {
2120
- this.directionalLight.color = new Color4().setRGB(
2121
- sunValues.sunColor.r,
2122
- sunValues.sunColor.g,
2123
- sunValues.sunColor.b
2124
- );
2125
- }
2126
- setSunPosition(azimuthalAngle, polarAngle) {
2127
- if (!this.target)
2128
- return;
2129
- const distance = this.sunOffset.z;
2130
- const sphericalPosition = new Vector38(
2131
- distance * Math.sin(polarAngle) * Math.cos(azimuthalAngle),
2132
- distance * Math.cos(polarAngle),
2133
- distance * Math.sin(polarAngle) * Math.sin(azimuthalAngle)
2134
- );
2135
- const newSunPosition = this.target.clone().add(sphericalPosition);
2136
- this.directionalLight.position.set(newSunPosition.x, newSunPosition.y, newSunPosition.z);
2137
- this.directionalLight.target.position.copy(this.target.clone());
2138
- this.directionalLight.target.updateMatrixWorld();
2139
- }
2140
- };
2141
-
2142
- // src/tweakpane/blades/bcsFolder.ts
2143
- var bcsValues = {
2144
- brightness: 0,
2145
- contrast: 1.25,
2146
- saturation: 1
2147
- };
2148
- var bcsOptions = {
2149
- brightness: {
2150
- amount: { min: -1, max: 1, step: 0.01 }
2151
- },
2152
- contrast: {
2153
- amount: { min: 0, max: 2, step: 0.01 }
2154
- },
2155
- saturation: {
2156
- amount: { min: 0, max: 2, step: 0.01 }
2157
- }
2158
- };
2159
- var BrightnessContrastSaturationFolder = class {
2160
- constructor(parentFolder, expand = false) {
2161
- this.folder = parentFolder.addFolder({
2162
- title: "brightness / contrast / sat",
2163
- expanded: expand
2164
- });
2165
- this.folder.addBinding(bcsValues, "brightness", bcsOptions.brightness.amount);
2166
- this.folder.addBinding(bcsValues, "contrast", bcsOptions.contrast.amount);
2167
- this.folder.addBinding(bcsValues, "saturation", bcsOptions.saturation.amount);
2168
- }
2169
- setupChangeEvent(brightnessContrastSaturation) {
2170
- this.folder.on("change", (e) => {
2171
- const target = e.target.key;
2172
- if (!target)
2173
- return;
2174
- switch (target) {
2175
- case "brightness":
2176
- brightnessContrastSaturation.uniforms.brightness.value = e.value;
2177
- break;
2178
- case "contrast":
2179
- brightnessContrastSaturation.uniforms.contrast.value = e.value;
2180
- break;
2181
- case "saturation":
2182
- brightnessContrastSaturation.uniforms.saturation.value = e.value;
2183
- break;
2184
- }
2185
- });
2186
- }
2187
- };
2188
-
2189
2125
  // src/tweakpane/blades/postExtrasFolder.ts
2190
2126
  var extrasValues = {
2191
2127
  grain: 0.055,
@@ -2310,9 +2246,52 @@ var RendererFolder = class {
2310
2246
  }
2311
2247
  };
2312
2248
 
2249
+ // src/tweakpane/blades/rendererStatsFolder.ts
2250
+ var RendererStatsFolder = class {
2251
+ constructor(parentFolder, expanded = true) {
2252
+ this.statsData = {
2253
+ triangles: "0",
2254
+ geometries: "0",
2255
+ textures: "0",
2256
+ shaders: "0",
2257
+ postPasses: "0",
2258
+ drawCalls: "0",
2259
+ rawDeltaTime: "0",
2260
+ deltaTime: "0",
2261
+ FPS: "0"
2262
+ };
2263
+ this.folder = parentFolder.addFolder({ title: "renderStats", expanded });
2264
+ this.performance = this.folder.addFolder({ title: "performance", expanded: true });
2265
+ this.defails = this.folder.addFolder({ title: "pipeline details", expanded: false });
2266
+ this.folder.addBlade({ view: "separator" });
2267
+ this.performance.addBinding(this.statsData, "FPS", { readonly: true });
2268
+ this.performance.addBinding(this.statsData, "deltaTime", { readonly: true });
2269
+ this.performance.addBinding(this.statsData, "rawDeltaTime", { readonly: true });
2270
+ this.defails.addBinding(this.statsData, "triangles", { readonly: true });
2271
+ this.defails.addBinding(this.statsData, "geometries", { readonly: true });
2272
+ this.defails.addBinding(this.statsData, "textures", { readonly: true });
2273
+ this.defails.addBinding(this.statsData, "shaders", { readonly: true });
2274
+ this.defails.addBinding(this.statsData, "postPasses", { readonly: true });
2275
+ this.defails.addBinding(this.statsData, "drawCalls", { readonly: true });
2276
+ }
2277
+ update(renderer, composer, timeManager) {
2278
+ const { geometries, textures } = renderer.info.memory;
2279
+ const { triangles, calls } = renderer.info.render;
2280
+ this.statsData.triangles = triangles.toString();
2281
+ this.statsData.geometries = geometries.toString();
2282
+ this.statsData.textures = textures.toString();
2283
+ this.statsData.shaders = renderer.info.programs.length.toString();
2284
+ this.statsData.postPasses = composer.passes.length.toString();
2285
+ this.statsData.drawCalls = calls.toString();
2286
+ this.statsData.rawDeltaTime = (Math.round(timeManager.rawDeltaTime * 1e5) / 1e5).toString();
2287
+ this.statsData.deltaTime = (Math.round(timeManager.deltaTime * 1e5) / 1e5).toString();
2288
+ this.statsData.FPS = timeManager.fps.toString();
2289
+ }
2290
+ };
2291
+
2313
2292
  // src/tweakpane/blades/ssaoFolder.ts
2314
2293
  import { BlendFunction } from "postprocessing";
2315
- import { Color as Color5 } from "three";
2294
+ import { Color as Color4 } from "three";
2316
2295
  var ppssaoValues = {
2317
2296
  enabled: false,
2318
2297
  blendFunction: BlendFunction.MULTIPLY,
@@ -2504,7 +2483,7 @@ var SSAOFolder = class {
2504
2483
  }
2505
2484
  case "color": {
2506
2485
  const value = e.value;
2507
- ppssaoEffect.color = new Color5().setRGB(value.r, value.g, value.b);
2486
+ ppssaoEffect.color = new Color4().setRGB(value.r, value.g, value.b);
2508
2487
  break;
2509
2488
  }
2510
2489
  default: {
@@ -2544,7 +2523,7 @@ var SSAOFolder = class {
2544
2523
  break;
2545
2524
  case "color":
2546
2525
  const value = e.value;
2547
- n8aopass.configuration.color = new Color5().setRGB(value.r, value.g, value.b);
2526
+ n8aopass.configuration.color = new Color4().setRGB(value.r, value.g, value.b);
2548
2527
  break;
2549
2528
  default:
2550
2529
  break;
@@ -2637,53 +2616,6 @@ var ToneMappingFolder = class {
2637
2616
  }
2638
2617
  };
2639
2618
 
2640
- // src/tweakpane/TweakPane.ts
2641
- import * as EssentialsPlugin from "@tweakpane/plugin-essentials";
2642
- import { Pane } from "tweakpane";
2643
-
2644
- // src/tweakpane/blades/rendererStatsFolder.ts
2645
- var RendererStatsFolder = class {
2646
- constructor(parentFolder, expanded = true) {
2647
- this.statsData = {
2648
- triangles: "0",
2649
- geometries: "0",
2650
- textures: "0",
2651
- shaders: "0",
2652
- postPasses: "0",
2653
- drawCalls: "0",
2654
- rawDeltaTime: "0",
2655
- deltaTime: "0",
2656
- FPS: "0"
2657
- };
2658
- this.folder = parentFolder.addFolder({ title: "renderStats", expanded });
2659
- this.performance = this.folder.addFolder({ title: "performance", expanded: true });
2660
- this.defails = this.folder.addFolder({ title: "pipeline details", expanded: false });
2661
- this.folder.addBlade({ view: "separator" });
2662
- this.performance.addBinding(this.statsData, "FPS", { readonly: true });
2663
- this.performance.addBinding(this.statsData, "deltaTime", { readonly: true });
2664
- this.performance.addBinding(this.statsData, "rawDeltaTime", { readonly: true });
2665
- this.defails.addBinding(this.statsData, "triangles", { readonly: true });
2666
- this.defails.addBinding(this.statsData, "geometries", { readonly: true });
2667
- this.defails.addBinding(this.statsData, "textures", { readonly: true });
2668
- this.defails.addBinding(this.statsData, "shaders", { readonly: true });
2669
- this.defails.addBinding(this.statsData, "postPasses", { readonly: true });
2670
- this.defails.addBinding(this.statsData, "drawCalls", { readonly: true });
2671
- }
2672
- update(renderer, composer, timeManager) {
2673
- const { geometries, textures } = renderer.info.memory;
2674
- const { triangles, calls } = renderer.info.render;
2675
- this.statsData.triangles = triangles.toString();
2676
- this.statsData.geometries = geometries.toString();
2677
- this.statsData.textures = textures.toString();
2678
- this.statsData.shaders = renderer.info.programs.length.toString();
2679
- this.statsData.postPasses = composer.passes.length.toString();
2680
- this.statsData.drawCalls = calls.toString();
2681
- this.statsData.rawDeltaTime = (Math.round(timeManager.rawDeltaTime * 1e5) / 1e5).toString();
2682
- this.statsData.deltaTime = (Math.round(timeManager.deltaTime * 1e5) / 1e5).toString();
2683
- this.statsData.FPS = timeManager.fps.toString();
2684
- }
2685
- };
2686
-
2687
2619
  // src/tweakpane/tweakPaneStyle.ts
2688
2620
  var tweakPaneStyle = `
2689
2621
  :root {
@@ -2882,6 +2814,122 @@ var TweakPane = class {
2882
2814
  }
2883
2815
  };
2884
2816
 
2817
+ // src/rendering/composer.ts
2818
+ import { N8AOPostPass } from "n8ao";
2819
+ import {
2820
+ EffectComposer as EffectComposer2,
2821
+ RenderPass,
2822
+ EffectPass as EffectPass2,
2823
+ FXAAEffect,
2824
+ ShaderPass,
2825
+ BloomEffect,
2826
+ SSAOEffect as SSAOEffect2,
2827
+ BlendFunction as BlendFunction2,
2828
+ TextureEffect,
2829
+ ToneMappingEffect,
2830
+ SMAAEffect,
2831
+ SMAAPreset,
2832
+ EdgeDetectionMode,
2833
+ PredicationMode,
2834
+ NormalPass as NormalPass2
2835
+ } from "postprocessing";
2836
+ import {
2837
+ AmbientLight,
2838
+ Color as Color6,
2839
+ Fog,
2840
+ HalfFloatType,
2841
+ LinearSRGBColorSpace,
2842
+ LoadingManager as LoadingManager2,
2843
+ PMREMGenerator,
2844
+ Scene as Scene3,
2845
+ Vector2 as Vector22,
2846
+ WebGLRenderer as WebGLRenderer2
2847
+ } from "three";
2848
+ import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
2849
+
2850
+ // src/sun/Sun.ts
2851
+ import { CameraHelper, Color as Color5, DirectionalLight, Group as Group3, OrthographicCamera, Vector3 as Vector38 } from "three";
2852
+ var Sun = class extends Group3 {
2853
+ constructor() {
2854
+ super();
2855
+ this.debug = false;
2856
+ this.sunOffset = new Vector38(
2857
+ 39 * (Math.PI / 180),
2858
+ 50 * (Math.PI / 180),
2859
+ 100
2860
+ );
2861
+ this.shadowResolution = 8192;
2862
+ this.shadowCamFrustum = 50;
2863
+ this.camHelper = null;
2864
+ this.target = null;
2865
+ this.shadowCamera = new OrthographicCamera(
2866
+ -this.shadowCamFrustum,
2867
+ this.shadowCamFrustum,
2868
+ this.shadowCamFrustum,
2869
+ -this.shadowCamFrustum,
2870
+ 0.1,
2871
+ 200
2872
+ );
2873
+ if (this.debug === true) {
2874
+ this.camHelper = new CameraHelper(this.shadowCamera);
2875
+ }
2876
+ this.directionalLight = new DirectionalLight(16777215, 0.5);
2877
+ this.directionalLight.shadow.normalBias = 0.05;
2878
+ this.directionalLight.shadow.radius = 1.5;
2879
+ this.directionalLight.shadow.camera = this.shadowCamera;
2880
+ this.directionalLight.shadow.mapSize.set(this.shadowResolution, this.shadowResolution);
2881
+ this.directionalLight.castShadow = true;
2882
+ this.setColor();
2883
+ this.updateCharacterPosition(new Vector38(0, 0, 0));
2884
+ this.add(this.directionalLight);
2885
+ if (this.debug === true && this.camHelper instanceof CameraHelper) {
2886
+ this.add(this.camHelper);
2887
+ }
2888
+ }
2889
+ updateCharacterPosition(position) {
2890
+ if (!position)
2891
+ return;
2892
+ this.target = position;
2893
+ this.setSunPosition(this.sunOffset.x, this.sunOffset.y);
2894
+ }
2895
+ setAzimuthalAngle(angle) {
2896
+ if (this.sunOffset)
2897
+ this.sunOffset.x = angle;
2898
+ if (this.target)
2899
+ this.updateCharacterPosition(this.target);
2900
+ }
2901
+ setPolarAngle(angle) {
2902
+ if (this.sunOffset)
2903
+ this.sunOffset.y = angle;
2904
+ if (this.target)
2905
+ this.updateCharacterPosition(this.target);
2906
+ }
2907
+ setIntensity(intensity) {
2908
+ this.directionalLight.intensity = intensity;
2909
+ }
2910
+ setColor() {
2911
+ this.directionalLight.color = new Color5().setRGB(
2912
+ sunValues.sunColor.r,
2913
+ sunValues.sunColor.g,
2914
+ sunValues.sunColor.b
2915
+ );
2916
+ }
2917
+ setSunPosition(azimuthalAngle, polarAngle) {
2918
+ if (!this.target)
2919
+ return;
2920
+ const distance = this.sunOffset.z;
2921
+ const sphericalPosition = new Vector38(
2922
+ distance * Math.sin(polarAngle) * Math.cos(azimuthalAngle),
2923
+ distance * Math.cos(polarAngle),
2924
+ distance * Math.sin(polarAngle) * Math.sin(azimuthalAngle)
2925
+ );
2926
+ const newSunPosition = this.target.clone().add(sphericalPosition);
2927
+ this.directionalLight.position.set(newSunPosition.x, newSunPosition.y, newSunPosition.z);
2928
+ this.directionalLight.target.position.copy(this.target.clone());
2929
+ this.directionalLight.target.updateMatrixWorld();
2930
+ }
2931
+ };
2932
+
2885
2933
  // src/rendering/post-effects/bright-contrast-sat.ts
2886
2934
  import { ShaderMaterial, Uniform } from "three";
2887
2935
 
@@ -3029,8 +3077,8 @@ var GaussGrainEffect = new ShaderMaterial2({
3029
3077
  // src/rendering/composer.ts
3030
3078
  var Composer = class {
3031
3079
  constructor(scene, camera, spawnSun = false) {
3032
- this.width = window.innerWidth;
3033
- this.height = window.innerHeight;
3080
+ this.width = 1;
3081
+ this.height = 1;
3034
3082
  this.resolution = new Vector22(this.width, this.height);
3035
3083
  this.isEnvHDRI = false;
3036
3084
  this.bcs = BrightnessContrastSaturation;
@@ -3055,11 +3103,9 @@ var Composer = class {
3055
3103
  this.renderer.toneMappingExposure = rendererValues.exposure;
3056
3104
  this.setAmbientLight();
3057
3105
  this.setFog();
3058
- document.body.appendChild(this.renderer.domElement);
3059
- this.composer = new EffectComposer2(this.renderer, {
3106
+ this.effectComposer = new EffectComposer2(this.renderer, {
3060
3107
  frameBufferType: HalfFloatType
3061
3108
  });
3062
- this.tweakPane = new TweakPane(this.renderer, this.scene, this.composer);
3063
3109
  this.renderPass = new RenderPass(this.scene, this.camera);
3064
3110
  this.normalPass = new NormalPass2(this.scene, this.camera);
3065
3111
  this.normalPass.enabled = ppssaoValues.enabled;
@@ -3128,26 +3174,33 @@ var Composer = class {
3128
3174
  this.bcs.uniforms.saturation.value = bcsValues.saturation;
3129
3175
  this.gaussGrainPass = new ShaderPass(this.gaussGrainEffect, "tDiffuse");
3130
3176
  this.smaaPass = new EffectPass2(this.camera, this.smaaEffect);
3131
- this.composer.addPass(this.renderPass);
3177
+ this.effectComposer.addPass(this.renderPass);
3132
3178
  if (ppssaoValues.enabled) {
3133
- this.composer.addPass(this.normalPass);
3134
- this.composer.addPass(this.ppssaoPass);
3179
+ this.effectComposer.addPass(this.normalPass);
3180
+ this.effectComposer.addPass(this.ppssaoPass);
3135
3181
  }
3136
3182
  if (n8ssaoValues.enabled) {
3137
- this.composer.addPass(this.n8aopass);
3138
- }
3139
- this.composer.addPass(this.fxaaPass);
3140
- this.composer.addPass(this.smaaPass);
3141
- this.composer.addPass(this.bloomPass);
3142
- this.composer.addPass(this.toneMappingPass);
3143
- this.composer.addPass(this.bcsPass);
3144
- this.composer.addPass(this.gaussGrainPass);
3183
+ this.effectComposer.addPass(this.n8aopass);
3184
+ }
3185
+ this.effectComposer.addPass(this.fxaaPass);
3186
+ this.effectComposer.addPass(this.smaaPass);
3187
+ this.effectComposer.addPass(this.bloomPass);
3188
+ this.effectComposer.addPass(this.toneMappingPass);
3189
+ this.effectComposer.addPass(this.bcsPass);
3190
+ this.effectComposer.addPass(this.gaussGrainPass);
3145
3191
  if (this.spawnSun === true) {
3146
3192
  this.sun = new Sun();
3147
3193
  this.scene.add(this.sun);
3148
3194
  }
3149
- this.tweakPane.setupRenderPane(
3150
- this.composer,
3195
+ this.resizeListener = () => {
3196
+ this.fitContainer();
3197
+ };
3198
+ window.addEventListener("resize", this.resizeListener, false);
3199
+ this.fitContainer();
3200
+ }
3201
+ setupTweakPane(tweakPane) {
3202
+ tweakPane.setupRenderPane(
3203
+ this.effectComposer,
3151
3204
  this.normalPass,
3152
3205
  this.ppssaoEffect,
3153
3206
  this.ppssaoPass,
@@ -3163,14 +3216,32 @@ var Composer = class {
3163
3216
  this.setAmbientLight.bind(this),
3164
3217
  this.setFog.bind(this)
3165
3218
  );
3166
- window.addEventListener("resize", () => this.updateProjection());
3167
- this.updateProjection();
3168
3219
  }
3169
- updateProjection() {
3170
- this.width = window.innerWidth;
3171
- this.height = innerHeight;
3172
- this.resolution = new Vector22(this.width, this.height);
3173
- this.composer.setSize(this.width, this.height);
3220
+ dispose() {
3221
+ window.removeEventListener("resize", this.resizeListener);
3222
+ }
3223
+ fitContainer() {
3224
+ if (!this) {
3225
+ console.error("Composer not initialized");
3226
+ return;
3227
+ }
3228
+ const parentElement = this.renderer.domElement.parentNode;
3229
+ if (!parentElement) {
3230
+ return;
3231
+ }
3232
+ this.width = parentElement.clientWidth;
3233
+ this.height = parentElement.clientHeight;
3234
+ this.camera.aspect = this.width / this.height;
3235
+ this.camera.updateProjectionMatrix();
3236
+ this.renderer.setPixelRatio(window.devicePixelRatio);
3237
+ this.resolution.set(
3238
+ this.width * window.devicePixelRatio,
3239
+ this.height * window.devicePixelRatio
3240
+ );
3241
+ this.effectComposer.setSize(
3242
+ this.width / window.devicePixelRatio,
3243
+ this.height / window.devicePixelRatio
3244
+ );
3174
3245
  this.renderPass.setSize(this.width, this.height);
3175
3246
  if (ppssaoValues.enabled) {
3176
3247
  this.normalPass.setSize(this.width, this.height);
@@ -3187,20 +3258,14 @@ var Composer = class {
3187
3258
  this.gaussGrainPass.setSize(this.width, this.height);
3188
3259
  this.renderer.setSize(this.width, this.height);
3189
3260
  }
3190
- isTweakPaneVisible() {
3191
- return this.tweakPane.guiVisible;
3192
- }
3193
3261
  render(timeManager) {
3194
3262
  this.renderer.info.reset();
3195
3263
  this.normalPass.texture.needsUpdate = true;
3196
3264
  this.gaussGrainEffect.uniforms.resolution.value = this.resolution;
3197
3265
  this.gaussGrainEffect.uniforms.time.value = timeManager.time;
3198
3266
  this.gaussGrainEffect.uniforms.alpha.value = 1;
3199
- this.composer.render();
3267
+ this.effectComposer.render();
3200
3268
  this.renderer.render(this.postPostScene, this.camera);
3201
- if (this.tweakPane.guiVisible) {
3202
- this.tweakPane.updateStats(timeManager);
3203
- }
3204
3269
  }
3205
3270
  useHDRI(url, fromFile = false) {
3206
3271
  if (this.isEnvHDRI && fromFile === false || !this.renderer)
@@ -3332,7 +3397,7 @@ import {
3332
3397
  Box3,
3333
3398
  Color as Color7,
3334
3399
  DoubleSide,
3335
- Euler,
3400
+ Euler as Euler2,
3336
3401
  Group as Group4,
3337
3402
  Line3 as Line32,
3338
3403
  Matrix4 as Matrix42,
@@ -3354,7 +3419,7 @@ var CollisionsManager = class {
3354
3419
  this.tempMatrix = new Matrix42();
3355
3420
  this.tempMatrix2 = new Matrix42();
3356
3421
  this.tempBox = new Box3();
3357
- this.tempEuler = new Euler();
3422
+ this.tempEuler = new Euler2();
3358
3423
  this.tempSegment = new Line32();
3359
3424
  this.tempSegment2 = new Line32();
3360
3425
  this.collisionMeshState = /* @__PURE__ */ new Map();
@@ -3547,11 +3612,13 @@ export {
3547
3612
  AnimationState,
3548
3613
  CameraManager,
3549
3614
  CharacterManager,
3615
+ CharacterModelLoader,
3550
3616
  CollisionsManager,
3551
3617
  Composer,
3552
3618
  KeyInputManager,
3553
3619
  MMLCompositionScene,
3554
3620
  Sun,
3555
- TimeManager
3621
+ TimeManager,
3622
+ TweakPane
3556
3623
  };
3557
3624
  //# sourceMappingURL=index.js.map