@mml-io/3d-web-client-core 0.12.1 → 0.13.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
@@ -82,6 +82,169 @@ var EventHandlerCollection = class _EventHandlerCollection {
82
82
  }
83
83
  };
84
84
 
85
+ // src/input/VirtualJoystick.ts
86
+ var _VirtualJoystick = class _VirtualJoystick {
87
+ constructor(attrs) {
88
+ this.left = false;
89
+ this.right = false;
90
+ this.up = false;
91
+ this.down = false;
92
+ this.hasDirection = false;
93
+ this.clearFlags = () => {
94
+ this.left = false;
95
+ this.right = false;
96
+ this.up = false;
97
+ this.down = false;
98
+ this.hasDirection = false;
99
+ this.control.style.left = `${this.width / 2 - this.inner_radius}px`;
100
+ this.control.style.top = `${this.height / 2 - this.inner_radius}px`;
101
+ };
102
+ this.radius = attrs.radius || 50;
103
+ this.inner_radius = attrs.inner_radius || this.radius / 2;
104
+ this.anchor = attrs.anchor || "left";
105
+ this.x = attrs.x || 0;
106
+ this.y = attrs.y || 0;
107
+ this.width = attrs.width || this.radius * 2 + this.inner_radius * 2;
108
+ this.height = attrs.height || this.radius * 2 + this.inner_radius * 2;
109
+ this.mouse_support = this.checkTouch() || attrs.mouse_support === true;
110
+ this.initializeJoystick();
111
+ }
112
+ static checkForTouch() {
113
+ try {
114
+ document.createEvent("TouchEvent");
115
+ return true;
116
+ } catch (e) {
117
+ return false;
118
+ }
119
+ }
120
+ static isTouchOnJoystick(touch) {
121
+ if (!_VirtualJoystick.JOYSTICK_DIV) {
122
+ return false;
123
+ }
124
+ const divRect = _VirtualJoystick.JOYSTICK_DIV.getBoundingClientRect();
125
+ return touch.clientX >= divRect.left && touch.clientX <= divRect.right && touch.clientY >= divRect.top && touch.clientY <= divRect.bottom;
126
+ }
127
+ checkTouch() {
128
+ return _VirtualJoystick.checkForTouch();
129
+ }
130
+ initializeJoystick() {
131
+ if (!_VirtualJoystick.JOYSTICK_DIV) {
132
+ this.div = document.createElement("div");
133
+ const divStyle = this.div.style;
134
+ divStyle.display = this.checkTouch() || this.mouse_support ? "visible" : "none";
135
+ divStyle.position = "fixed";
136
+ if (this.anchor === "left") {
137
+ divStyle.left = `${this.x}px`;
138
+ } else {
139
+ divStyle.right = `${this.x}px`;
140
+ }
141
+ divStyle.bottom = `${this.y}px`;
142
+ divStyle.width = `${this.width}px`;
143
+ divStyle.height = `${this.height}px`;
144
+ divStyle.zIndex = "10000";
145
+ divStyle.overflow = "hidden";
146
+ document.body.appendChild(this.div);
147
+ _VirtualJoystick.JOYSTICK_DIV = this.div;
148
+ }
149
+ this.setupBaseAndControl();
150
+ this.bindEvents();
151
+ }
152
+ setupBaseAndControl() {
153
+ this.base = document.createElement("span");
154
+ let divStyle = this.base.style;
155
+ divStyle.width = `${this.radius * 2}px`;
156
+ divStyle.height = `${this.radius * 2}px`;
157
+ divStyle.position = "absolute";
158
+ divStyle.left = `${this.width / 2 - this.radius}px`;
159
+ divStyle.bottom = `${this.height / 2 - this.radius}px`;
160
+ divStyle.borderRadius = "50%";
161
+ divStyle.borderColor = "rgba(200,200,200,0.5)";
162
+ divStyle.borderWidth = "2px";
163
+ divStyle.borderStyle = "solid";
164
+ this.div.appendChild(this.base);
165
+ this.control = document.createElement("span");
166
+ divStyle = this.control.style;
167
+ divStyle.width = `${this.inner_radius * 2}px`;
168
+ divStyle.height = `${this.inner_radius * 2}px`;
169
+ divStyle.position = "absolute";
170
+ divStyle.left = `${this.width / 2 - this.inner_radius}px`;
171
+ divStyle.bottom = `${this.height / 2 - this.inner_radius}px`;
172
+ divStyle.borderRadius = "50%";
173
+ divStyle.backgroundColor = "rgba(200,200,200,0.3)";
174
+ divStyle.borderWidth = "1px";
175
+ divStyle.borderColor = "rgba(200,200,200,0.8)";
176
+ divStyle.borderStyle = "solid";
177
+ this.div.appendChild(this.control);
178
+ }
179
+ bindEvents() {
180
+ this.div.addEventListener("touchstart", this.handleTouchStart.bind(this), false);
181
+ this.div.addEventListener("touchmove", this.handleTouchMove.bind(this), false);
182
+ this.div.addEventListener("touchend", this.clearFlags.bind(this), false);
183
+ if (this.mouse_support) {
184
+ this.div.addEventListener("mousedown", this.handleMouseDown.bind(this));
185
+ this.div.addEventListener("mousemove", this.handleMouseMove.bind(this));
186
+ this.div.addEventListener("mouseup", this.handleMouseUp.bind(this));
187
+ }
188
+ }
189
+ handleTouchStart(evt) {
190
+ evt.preventDefault();
191
+ if (evt.touches) {
192
+ const touch = evt.touches[0];
193
+ this.updateControlAndDirection(touch);
194
+ }
195
+ }
196
+ handleTouchMove(evt) {
197
+ evt.preventDefault();
198
+ if (evt.touches.length > 0) {
199
+ const touch = evt.touches[0];
200
+ this.updateControlAndDirection(touch);
201
+ }
202
+ }
203
+ handleMouseDown(evt) {
204
+ evt.preventDefault();
205
+ this.updateControlAndDirection(evt);
206
+ }
207
+ handleMouseMove(evt) {
208
+ if (evt.buttons === 1) {
209
+ evt.preventDefault();
210
+ this.updateControlAndDirection(evt);
211
+ }
212
+ }
213
+ handleMouseUp(evt) {
214
+ this.clearFlags();
215
+ }
216
+ updateControlAndDirection(input) {
217
+ const rect = this.div.getBoundingClientRect();
218
+ const dx = input.clientX - (rect.left + this.div.offsetWidth / 2);
219
+ const dy = input.clientY - (rect.top + this.div.offsetHeight / 2);
220
+ const distance = Math.min(Math.sqrt(dx * dx + dy * dy), this.radius);
221
+ const angle = Math.atan2(dy, dx);
222
+ const constrainedX = distance * Math.cos(angle);
223
+ const constrainedY = distance * Math.sin(angle);
224
+ this.control.style.left = `${constrainedX + this.width / 2 - this.inner_radius}px`;
225
+ this.control.style.top = `${constrainedY + this.height / 2 - this.inner_radius}px`;
226
+ this.up = this.isUp(dx, dy);
227
+ this.down = this.isDown(dx, dy);
228
+ this.left = this.isLeft(dx, dy);
229
+ this.right = this.isRight(dx, dy);
230
+ this.hasDirection = this.up || this.down || this.left || this.right;
231
+ }
232
+ isUp(dx, dy) {
233
+ return dy < 0 && Math.abs(dx) <= 2 * Math.abs(dy);
234
+ }
235
+ isDown(dx, dy) {
236
+ return dy > 0 && Math.abs(dx) <= 2 * Math.abs(dy);
237
+ }
238
+ isLeft(dx, dy) {
239
+ return dx < 0 && Math.abs(dy) <= 2 * Math.abs(dx);
240
+ }
241
+ isRight(dx, dy) {
242
+ return dx > 0 && Math.abs(dy) <= 2 * Math.abs(dx);
243
+ }
244
+ };
245
+ _VirtualJoystick.JOYSTICK_DIV = null;
246
+ var VirtualJoystick = _VirtualJoystick;
247
+
85
248
  // src/tweakpane/tweakPaneActivity.ts
86
249
  var isTweakpaneActive = false;
87
250
  function setTweakpaneActive(status) {
@@ -100,8 +263,8 @@ var CameraManager = class {
100
263
  this.maxDistance = 8;
101
264
  this.initialFOV = 60;
102
265
  this.fov = this.initialFOV;
103
- this.minFOV = 50;
104
- this.maxFOV = 70;
266
+ this.minFOV = 85;
267
+ this.maxFOV = 60;
105
268
  this.targetFOV = this.initialFOV;
106
269
  this.minPolarAngle = Math.PI * 0.25;
107
270
  this.maxPolarAngle = Math.PI * 0.95;
@@ -119,6 +282,9 @@ var CameraManager = class {
119
282
  this.lerpTarget = new Vector32();
120
283
  this.lerpFactor = 0;
121
284
  this.lerpDuration = 2.1;
285
+ this.hasTouchControl = false;
286
+ this.lastTouchX = 0;
287
+ this.lastTouchY = 0;
122
288
  this.phi = initialPhi;
123
289
  this.targetPhi = initialPhi;
124
290
  this.theta = initialTheta;
@@ -126,12 +292,61 @@ var CameraManager = class {
126
292
  this.camera = new PerspectiveCamera(this.fov, window.innerWidth / window.innerHeight, 0.1, 400);
127
293
  this.camera.position.set(0, 1.4, -this.initialDistance);
128
294
  this.rayCaster = new Raycaster();
295
+ this.hasTouchControl = VirtualJoystick.checkForTouch();
129
296
  this.eventHandlerCollection = EventHandlerCollection.create([
130
297
  [targetElement, "mousedown", this.onMouseDown.bind(this)],
131
298
  [document, "mouseup", this.onMouseUp.bind(this)],
132
299
  [document, "mousemove", this.onMouseMove.bind(this)],
133
300
  [targetElement, "wheel", this.onMouseWheel.bind(this)]
134
301
  ]);
302
+ if (this.hasTouchControl) {
303
+ this.eventHandlerCollection.add(targetElement, "touchstart", this.onTouchStart.bind(this), {
304
+ passive: false
305
+ });
306
+ this.eventHandlerCollection.add(document, "touchmove", this.onTouchMove.bind(this), {
307
+ passive: false
308
+ });
309
+ this.eventHandlerCollection.add(document, "touchend", this.onTouchEnd.bind(this), {
310
+ passive: false
311
+ });
312
+ }
313
+ }
314
+ onTouchStart(evt) {
315
+ Array.from(evt.touches).forEach((touch) => {
316
+ if (!VirtualJoystick.isTouchOnJoystick(touch)) {
317
+ this.dragging = true;
318
+ this.lastTouchX = touch.clientX;
319
+ this.lastTouchY = touch.clientY;
320
+ }
321
+ });
322
+ }
323
+ onTouchMove(evt) {
324
+ if (!this.dragging || getTweakpaneActive()) {
325
+ return;
326
+ }
327
+ evt.preventDefault();
328
+ const touch = Array.from(evt.touches).find((t) => !VirtualJoystick.isTouchOnJoystick(t));
329
+ if (touch) {
330
+ const dx = touch.clientX - this.lastTouchX;
331
+ const dy = touch.clientY - this.lastTouchY;
332
+ this.lastTouchX = touch.clientX;
333
+ this.lastTouchY = touch.clientY;
334
+ if (this.targetTheta !== null && this.targetPhi !== null) {
335
+ this.targetTheta += dx * 0.01;
336
+ this.targetPhi -= dy * 0.01;
337
+ this.targetPhi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.targetPhi));
338
+ }
339
+ }
340
+ }
341
+ onTouchEnd(evt) {
342
+ if (this.dragging) {
343
+ const touchEnded = Array.from(evt.changedTouches).some(
344
+ (t) => !VirtualJoystick.isTouchOnJoystick(t)
345
+ );
346
+ if (touchEnded) {
347
+ this.dragging = false;
348
+ }
349
+ }
135
350
  }
136
351
  onMouseDown() {
137
352
  this.dragging = true;
@@ -199,10 +414,12 @@ var CameraManager = class {
199
414
  this.fov = this.targetFOV;
200
415
  }
201
416
  adjustCameraPosition() {
202
- this.rayCaster.set(
203
- this.camera.position,
204
- this.target.clone().sub(this.camera.position).normalize()
205
- );
417
+ const offsetDistance = 0.5;
418
+ const offset = new Vector32(0, 0, offsetDistance);
419
+ offset.applyEuler(this.camera.rotation);
420
+ const rayOrigin = this.camera.position.clone().add(offset);
421
+ const rayDirection = this.target.clone().sub(rayOrigin).normalize();
422
+ this.rayCaster.set(rayOrigin, rayDirection);
206
423
  const firstRaycastHit = this.collisionsManager.raycastFirst(this.rayCaster.ray);
207
424
  const cameraToPlayerDistance = this.camera.position.distanceTo(this.target);
208
425
  if (firstRaycastHit !== null && firstRaycastHit[0] <= cameraToPlayerDistance) {
@@ -260,7 +477,7 @@ import { Color as Color3, Group, Vector3 as Vector34 } from "three";
260
477
 
261
478
  // src/character/CharacterModel.ts
262
479
  import {
263
- Character as MMLCharacter,
480
+ MMLCharacter,
264
481
  ModelLoader,
265
482
  parseMMLDescription
266
483
  } from "@mml-io/3d-web-avatar";
@@ -271,7 +488,7 @@ import {
271
488
  } from "three";
272
489
 
273
490
  // src/character/CharacterMaterial.ts
274
- import { Color, MeshPhysicalMaterial, UniformsUtils } from "three";
491
+ import { Color, MeshStandardMaterial, UniformsUtils } from "three";
275
492
 
276
493
  // src/rendering/shaders/bayer-dither.ts
277
494
  var bayerDither = (
@@ -365,50 +582,23 @@ ${before}
365
582
 
366
583
  // src/tweakpane/blades/characterFolder.ts
367
584
  var characterValues = {
368
- transmission: 0.01,
369
585
  metalness: 0.2,
370
586
  roughness: 0.8,
371
- ior: 1,
372
- thickness: 0.1,
373
- specularColor: { r: 1, g: 1, b: 1 },
374
- specularIntensity: 0.1,
375
587
  emissive: { r: 1, g: 1, b: 1 },
376
588
  emissiveIntensity: 0.01,
377
- envMapIntensity: 0.12,
378
- sheenColor: { r: 1, g: 1, b: 1 },
379
- sheen: 0.5,
380
- clearcoat: 0,
381
- clearcoatRoughness: 0
589
+ envMapIntensity: 0.12
382
590
  };
383
591
  var characterOptions = {
384
- transmission: { min: 0.01, max: 3, step: 0.01 },
385
592
  metalness: { min: 0, max: 1, step: 0.01 },
386
593
  roughness: { min: 0, max: 1, step: 0.01 },
387
- ior: { min: 1, max: 5, step: 0.01 },
388
- thickness: { min: 0, max: 1, step: 0.01 },
389
- specularIntensity: { min: 0, max: 1, step: 0.01 },
390
594
  emissiveIntensity: { min: 0, max: 1, step: 0.01 },
391
- envMapIntensity: { min: 0, max: 1, step: 0.01 },
392
- sheen: { min: 0, max: 1, step: 0.01 },
393
- clearcoat: { min: 0, max: 1, step: 0.01 },
394
- clearcoatRoughness: { min: 0, max: 1, step: 0.01 }
595
+ envMapIntensity: { min: 0, max: 1, step: 0.01 }
395
596
  };
396
597
  var CharacterFolder = class {
397
598
  constructor(parentFolder, expand = false) {
398
599
  this.folder = parentFolder.addFolder({ title: "characterMaterial", expanded: expand });
399
- this.folder.addBinding(characterValues, "transmission", characterOptions.transmission);
400
600
  this.folder.addBinding(characterValues, "metalness", characterOptions.metalness);
401
601
  this.folder.addBinding(characterValues, "roughness", characterOptions.roughness);
402
- this.folder.addBinding(characterValues, "ior", characterOptions.ior);
403
- this.folder.addBinding(characterValues, "thickness", characterOptions.thickness);
404
- this.folder.addBinding(characterValues, "specularColor", {
405
- color: { type: "float" }
406
- });
407
- this.folder.addBinding(
408
- characterValues,
409
- "specularIntensity",
410
- characterOptions.specularIntensity
411
- );
412
602
  this.folder.addBinding(characterValues, "emissive", {
413
603
  color: { type: "float" }
414
604
  });
@@ -418,16 +608,6 @@ var CharacterFolder = class {
418
608
  characterOptions.emissiveIntensity
419
609
  );
420
610
  this.folder.addBinding(characterValues, "envMapIntensity", characterOptions.envMapIntensity);
421
- this.folder.addBinding(characterValues, "sheenColor", {
422
- color: { type: "float" }
423
- });
424
- this.folder.addBinding(characterValues, "sheen", characterOptions.sheen);
425
- this.folder.addBinding(characterValues, "clearcoat", characterOptions.clearcoat);
426
- this.folder.addBinding(
427
- characterValues,
428
- "clearcoatRoughness",
429
- characterOptions.clearcoatRoughness
430
- );
431
611
  }
432
612
  setupChangeEvent() {
433
613
  this.folder.on("change", (e) => {
@@ -435,15 +615,6 @@ var CharacterFolder = class {
435
615
  if (!target)
436
616
  return;
437
617
  switch (target) {
438
- case "specularColor": {
439
- const value = e.value;
440
- characterValues.specularColor = {
441
- r: value.r,
442
- g: value.g,
443
- b: value.b
444
- };
445
- break;
446
- }
447
618
  case "emissive": {
448
619
  const value = e.value;
449
620
  characterValues.emissive = {
@@ -453,15 +624,6 @@ var CharacterFolder = class {
453
624
  };
454
625
  break;
455
626
  }
456
- case "sheenColor": {
457
- const value = e.value;
458
- characterValues.sheenColor = {
459
- r: value.r,
460
- g: value.g,
461
- b: value.b
462
- };
463
- break;
464
- }
465
627
  default: {
466
628
  break;
467
629
  }
@@ -471,83 +633,59 @@ var CharacterFolder = class {
471
633
  };
472
634
 
473
635
  // src/character/CharacterMaterial.ts
474
- var CharacterMaterial = class extends MeshPhysicalMaterial {
475
- constructor(color) {
636
+ var CharacterMaterial = class extends MeshStandardMaterial {
637
+ constructor(isLocal, cameraManager, characterId, originalMaterial, colorOverride) {
476
638
  super();
477
- this.uniforms = {};
639
+ this.isLocal = isLocal;
640
+ this.cameraManager = cameraManager;
641
+ this.characterId = characterId;
642
+ this.originalMaterial = originalMaterial;
643
+ this.colorOverride = colorOverride;
644
+ this.uniforms = {
645
+ discardAll: { value: 1 },
646
+ diffuseColor: { value: new Color() },
647
+ map: { value: null }
648
+ };
478
649
  this.colorsCube216 = [];
479
- if (color) {
480
- this.color = color;
481
- }
482
- this.transmission = characterValues.transmission;
483
- this.metalness = characterValues.metalness;
484
- this.roughness = characterValues.roughness;
485
- this.ior = characterValues.ior;
486
- this.thickness = characterValues.thickness;
487
- this.specularColor = new Color().setRGB(
488
- characterValues.specularColor.r,
489
- characterValues.specularColor.g,
490
- characterValues.specularColor.b
491
- );
492
- this.specularIntensity = characterValues.specularIntensity;
493
- this.emissive = new Color().setRGB(
494
- characterValues.emissive.r,
495
- characterValues.emissive.g,
496
- characterValues.emissive.b
497
- );
498
- this.emissiveIntensity = characterValues.emissiveIntensity;
650
+ this.targetAlpha = 1;
651
+ this.currentAlpha = 1;
652
+ this.copy(this.originalMaterial);
653
+ this.generateColorCube();
654
+ this.color = this.colorOverride || this.colorsCube216[this.characterId];
499
655
  this.envMapIntensity = characterValues.envMapIntensity;
500
- this.sheenColor = new Color().setRGB(
501
- characterValues.sheenColor.r,
502
- characterValues.sheenColor.g,
503
- characterValues.sheenColor.b
504
- );
505
- this.sheen = characterValues.sheen;
506
- this.clearcoat = characterValues.clearcoat;
507
- this.clearcoatRoughness = characterValues.clearcoatRoughness;
656
+ this.transparent = true;
657
+ this.side = this.originalMaterial.side;
508
658
  this.onBeforeCompile = (shader) => {
509
659
  this.uniforms = UniformsUtils.clone(shader.uniforms);
510
660
  this.uniforms.nearClip = { value: 0.01 };
511
661
  this.uniforms.farClip = { value: 1e3 };
512
- this.uniforms.ditheringNear = { value: 0.25 };
662
+ this.uniforms.ditheringNear = { value: 0.3 };
513
663
  this.uniforms.ditheringRange = { value: 0.5 };
514
664
  this.uniforms.time = { value: 0 };
515
665
  this.uniforms.diffuseRandomColor = { value: new Color() };
666
+ this.uniforms.discardAll = { value: 0 };
516
667
  shader.uniforms = this.uniforms;
668
+ shader.vertexShader = "varying vec3 vWorldPosition;\n" + shader.vertexShader;
669
+ shader.vertexShader = shader.vertexShader.replace(
670
+ "#include <worldpos_vertex>",
671
+ "vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\nvWorldPosition = worldPosition.xyz;"
672
+ );
517
673
  shader.vertexShader = injectBeforeMain(shader.vertexShader, "varying vec2 vUv;");
518
674
  shader.vertexShader = injectInsideMain(shader.vertexShader, "vUv = uv;");
519
675
  shader.fragmentShader = injectBeforeMain(
520
676
  shader.fragmentShader,
521
677
  /* glsl */
522
678
  `
523
- //#define showPattern
524
679
  varying vec2 vUv;
680
+ varying vec3 vWorldPosition;
525
681
  uniform float nearClip;
526
682
  uniform float farClip;
527
683
  uniform float ditheringNear;
528
684
  uniform float ditheringRange;
529
685
  uniform float time;
530
686
  uniform vec3 diffuseRandomColor;
687
+ uniform int discardAll;
531
688
  ${bayerDither}
532
-
533
- #ifdef showPattern
534
- vec2 rand2(vec2 p) {
535
- return fract(vec2(sin(p.x * 591.32 + p.y * 154.077), cos(p.x * 391.32 + p.y * 49.077)));
536
- }
537
- float voronoi(in vec2 x) {
538
- vec2 p = floor(x);
539
- vec2 f = fract(x);
540
- float minDistance = 1.0;
541
- for(int j = -1; j <= 1; j ++)
542
- for(int i = -1; i <= 1; i ++) {
543
- vec2 b = vec2(i, j);
544
- vec2 rand = 0.5 + 0.5 * sin(time * 1.5 + 12.0 * rand2(p + b));
545
- vec2 r = vec2(b) - f + rand;
546
- minDistance = min(minDistance, length(r));
547
- }
548
- return minDistance;
549
- }
550
- #endif
551
689
  `
552
690
  );
553
691
  shader.fragmentShader = injectBefore(
@@ -555,42 +693,32 @@ var CharacterMaterial = class extends MeshPhysicalMaterial {
555
693
  "#include <output_fragment>",
556
694
  /* glsl */
557
695
  `
558
- float distance = length(vWorldPosition - cameraPosition);
559
- float normalizedDistance = (distance - nearClip) / (farClip - nearClip);
560
- ivec2 p = ivec2(mod(gl_FragCoord.xy, 8.0));
561
- float d = 0.0;
562
- if (p.x <= 3 && p.y <= 3) {
563
- d = bayerDither(bayertl, p);
564
- } else if (p.x > 3 && p.y <= 3) {
565
- d = bayerDither(bayertr, p - ivec2(4, 0));
566
- } else if (p.x <= 3 && p.y > 3) {
567
- d = bayerDither(bayerbl, p - ivec2(0, 4));
568
- } else if (p.x > 3 && p.y > 3) {
569
- d = bayerDither(bayerbr, p - ivec2(4, 4));
696
+ if (discardAll == 1) {
697
+ discard;
698
+ } else {
699
+ float distance = length(vWorldPosition - cameraPosition);
700
+ float normalizedDistance = (distance - nearClip) / (farClip - nearClip);
701
+ ivec2 p = ivec2(mod(gl_FragCoord.xy, 8.0));
702
+ float d = 0.0;
703
+ if (p.x <= 3 && p.y <= 3) {
704
+ d = bayerDither(bayertl, p);
705
+ } else if (p.x > 3 && p.y <= 3) {
706
+ d = bayerDither(bayertr, p - ivec2(4, 0));
707
+ } else if (p.x <= 3 && p.y > 3) {
708
+ d = bayerDither(bayerbl, p - ivec2(0, 4));
709
+ } else if (p.x > 3 && p.y > 3) {
710
+ d = bayerDither(bayerbr, p - ivec2(4, 4));
711
+ }
712
+ if (distance <= ditheringNear + d * ditheringRange) discard;
713
+ outgoingLight *= diffuseRandomColor;
570
714
  }
571
- if (distance <= ditheringNear + d * ditheringRange) discard;
572
-
573
- vec2 uv = vUv;
574
- float s = clamp(0.35 + 0.35 * sin(5.0 * -time + vUv.y * 600.0), 0.0, 1.0);
575
- float scanLines = pow(s, 1.33);
576
-
577
- outgoingLight *= diffuseRandomColor;
578
-
579
- #ifdef showPattern
580
- float val = pow(voronoi(uv * 8.0) * 1.2, 0.5);
581
- float thickness = 1.0 / 500.0;
582
- vec2 g = step(mod(uv, 0.015), vec2(thickness));
583
- float a = 1.0 - clamp(val * (g.x + g.y), 0.0, 1.0);
584
- vec3 grid = vec3(smoothstep(0.01, 0.0, a) * 1.15) * diffuseRandomColor;
585
- outgoingLight += grid;
586
- #endif
587
715
  `
588
716
  );
589
717
  };
590
- this.generateColorCube();
718
+ this.needsUpdate = true;
591
719
  }
592
720
  generateColorCube() {
593
- const saturation = 0.5;
721
+ const saturation = 1;
594
722
  const lightness = 0.9;
595
723
  const goldenRatioConjugate = 0.618033988749895;
596
724
  let hue = 0;
@@ -602,17 +730,24 @@ var CharacterMaterial = class extends MeshPhysicalMaterial {
602
730
  }
603
731
  }
604
732
  update() {
605
- this.transmission = characterValues.transmission;
733
+ if (this.isLocal) {
734
+ this.targetAlpha = this.cameraManager.targetDistance < 0.4 ? 0 : 1;
735
+ this.currentAlpha += ease(this.targetAlpha, this.currentAlpha, 0.07);
736
+ if (this.currentAlpha > 0.999) {
737
+ this.currentAlpha = 1;
738
+ this.cameraManager.minPolarAngle = Math.PI * 0.25;
739
+ }
740
+ if (this.currentAlpha < 1e-3) {
741
+ this.currentAlpha = 0;
742
+ this.cameraManager.minPolarAngle = Math.PI * 0.35;
743
+ }
744
+ this.uniforms.discardAll.value = this.currentAlpha === 0 ? 1 : 0;
745
+ if (this.currentAlpha !== this.opacity) {
746
+ this.opacity = this.currentAlpha;
747
+ }
748
+ }
606
749
  this.metalness = characterValues.metalness;
607
750
  this.roughness = characterValues.roughness;
608
- this.ior = characterValues.ior;
609
- this.thickness = characterValues.thickness;
610
- this.specularColor = new Color().setRGB(
611
- characterValues.specularColor.r,
612
- characterValues.specularColor.g,
613
- characterValues.specularColor.b
614
- );
615
- this.specularIntensity = characterValues.specularIntensity;
616
751
  this.emissive = new Color().setRGB(
617
752
  characterValues.emissive.r,
618
753
  characterValues.emissive.g,
@@ -620,14 +755,6 @@ var CharacterMaterial = class extends MeshPhysicalMaterial {
620
755
  );
621
756
  this.emissiveIntensity = characterValues.emissiveIntensity;
622
757
  this.envMapIntensity = characterValues.envMapIntensity;
623
- this.sheenColor = new Color().setRGB(
624
- characterValues.sheenColor.r,
625
- characterValues.sheenColor.g,
626
- characterValues.sheenColor.b
627
- );
628
- this.sheen = characterValues.sheen;
629
- this.clearcoat = characterValues.clearcoat;
630
- this.clearcoatRoughness = characterValues.clearcoatRoughness;
631
758
  }
632
759
  };
633
760
 
@@ -644,13 +771,16 @@ var AnimationState = /* @__PURE__ */ ((AnimationState2) => {
644
771
 
645
772
  // src/character/CharacterModel.ts
646
773
  var CharacterModel = class {
647
- constructor(characterDescription, animationConfig, characterModelLoader) {
774
+ constructor(characterDescription, animationConfig, characterModelLoader, cameraManager, characterId, isLocal) {
648
775
  this.characterDescription = characterDescription;
649
776
  this.animationConfig = animationConfig;
650
777
  this.characterModelLoader = characterModelLoader;
778
+ this.cameraManager = cameraManager;
779
+ this.characterId = characterId;
780
+ this.isLocal = isLocal;
651
781
  this.mesh = null;
652
- this.material = new CharacterMaterial();
653
782
  this.headBone = null;
783
+ this.materials = /* @__PURE__ */ new Map();
654
784
  this.animations = {};
655
785
  this.animationMixer = null;
656
786
  this.currentAnimation = 0 /* idle */;
@@ -667,22 +797,32 @@ var CharacterModel = class {
667
797
  2 /* running */
668
798
  );
669
799
  await this.setAnimationFromFile(this.animationConfig.airAnimationFileUrl, 4 /* air */);
670
- if (this.characterDescription.meshFileUrl) {
671
- this.applyCustomMaterial(this.material);
672
- }
800
+ this.applyCustomMaterials();
673
801
  }
674
- applyCustomMaterial(material) {
802
+ applyCustomMaterials() {
675
803
  if (!this.mesh)
676
804
  return;
677
805
  this.mesh.traverse((child) => {
678
- const asSkinnedMesh = child;
679
- if (asSkinnedMesh.isSkinnedMesh) {
680
- const mat = asSkinnedMesh.material;
681
- if (!mat.name.includes("joints")) {
682
- asSkinnedMesh.material = material;
806
+ if (child.isMesh || child.isSkinnedMesh) {
807
+ const asMesh = child;
808
+ const originalMaterial = asMesh.material;
809
+ if (this.materials.has(originalMaterial.name)) {
810
+ asMesh.material = this.materials.get(originalMaterial.name);
683
811
  } else {
684
- const color = mat.color;
685
- asSkinnedMesh.material = new CharacterMaterial(color);
812
+ const material = originalMaterial.name === "body_replaceable_color" ? new CharacterMaterial(
813
+ this.isLocal,
814
+ this.cameraManager,
815
+ this.characterId,
816
+ originalMaterial
817
+ ) : new CharacterMaterial(
818
+ this.isLocal,
819
+ this.cameraManager,
820
+ this.characterId,
821
+ originalMaterial,
822
+ originalMaterial.color
823
+ );
824
+ this.materials.set(originalMaterial.name, material);
825
+ asMesh.material = material;
686
826
  }
687
827
  }
688
828
  });
@@ -704,7 +844,7 @@ var CharacterModel = class {
704
844
  this.animationMixer = new AnimationMixer(this.mesh);
705
845
  }
706
846
  async composeMMLCharacter(mmlCharacterDescription) {
707
- var _a, _b, _c;
847
+ var _a, _b;
708
848
  if (((_a = mmlCharacterDescription.base) == null ? void 0 : _a.url.length) === 0) {
709
849
  throw new Error(
710
850
  "ERROR: An MML Character Description was provided but it's not a valid <m-character> string, or a valid URL"
@@ -713,14 +853,13 @@ var CharacterModel = class {
713
853
  let mergedCharacter = null;
714
854
  if (mmlCharacterDescription) {
715
855
  const characterBase = ((_b = mmlCharacterDescription.base) == null ? void 0 : _b.url) || null;
716
- const parts = [];
717
- (_c = mmlCharacterDescription.parts) == null ? void 0 : _c.forEach((part) => {
718
- if (part.url)
719
- parts.push(part.url);
720
- });
721
856
  if (characterBase) {
857
+ this.mmlCharacterDescription = mmlCharacterDescription;
722
858
  const mmlCharacter = new MMLCharacter(new ModelLoader());
723
- mergedCharacter = await mmlCharacter.mergeBodyParts(characterBase, parts);
859
+ mergedCharacter = await mmlCharacter.mergeBodyParts(
860
+ characterBase,
861
+ mmlCharacterDescription.parts
862
+ );
724
863
  if (mergedCharacter) {
725
864
  return mergedCharacter.children[0].children[0];
726
865
  }
@@ -812,6 +951,7 @@ var CharacterModel = class {
812
951
  update(time) {
813
952
  if (this.animationMixer) {
814
953
  this.animationMixer.update(time);
954
+ this.materials.forEach((material) => material.update());
815
955
  }
816
956
  }
817
957
  };
@@ -820,7 +960,7 @@ var CharacterModel = class {
820
960
  import {
821
961
  CircleGeometry,
822
962
  GLSL3,
823
- Mesh,
963
+ Mesh as Mesh2,
824
964
  RawShaderMaterial
825
965
  } from "three";
826
966
  var CharacterSpeakingIndicator = class {
@@ -884,7 +1024,7 @@ var CharacterSpeakingIndicator = class {
884
1024
  transparent: true,
885
1025
  glslVersion: GLSL3
886
1026
  });
887
- this.mesh = new Mesh(this.geometry, this.material);
1027
+ this.mesh = new Mesh2(this.geometry, this.material);
888
1028
  this.currentAlpha = 0;
889
1029
  this.targetAlpha = 0;
890
1030
  this.scene.add(this.mesh);
@@ -913,13 +1053,13 @@ import {
913
1053
  Color as Color2,
914
1054
  FrontSide,
915
1055
  LinearFilter as LinearFilter2,
916
- Mesh as Mesh2,
1056
+ Mesh as Mesh3,
917
1057
  MeshBasicMaterial as MeshBasicMaterial2,
918
1058
  PlaneGeometry
919
1059
  } from "three";
920
1060
 
921
1061
  // src/character/CanvasText.ts
922
- import { Texture, LinearFilter, RGBAFormat, MeshBasicMaterial } from "three";
1062
+ import { Texture as Texture2, LinearFilter, RGBAFormat, MeshBasicMaterial } from "three";
923
1063
  function getTextAlignOffset(textAlign, width) {
924
1064
  switch (textAlign) {
925
1065
  case "center":
@@ -1020,7 +1160,7 @@ function CanvasText(message, options) {
1020
1160
  }
1021
1161
  function THREECanvasTextTexture(text, options) {
1022
1162
  const canvas = CanvasText(text, options);
1023
- const texture = new Texture(canvas);
1163
+ const texture = new Texture2(canvas);
1024
1164
  texture.minFilter = LinearFilter;
1025
1165
  texture.magFilter = LinearFilter;
1026
1166
  texture.format = RGBAFormat;
@@ -1039,7 +1179,7 @@ var defaultLabelWidth = 0.25;
1039
1179
  var defaultLabelHeight = 0.125;
1040
1180
  var defaultLabelCastShadows = true;
1041
1181
  var tooltipGeometry = new PlaneGeometry(1, 1, 1, 1);
1042
- var CharacterTooltip = class extends Mesh2 {
1182
+ var CharacterTooltip = class extends Mesh3 {
1043
1183
  constructor() {
1044
1184
  super(tooltipGeometry);
1045
1185
  this.visibleOpacity = 0.85;
@@ -1146,7 +1286,7 @@ var CharacterTooltip = class extends Mesh2 {
1146
1286
 
1147
1287
  // src/character/Character.ts
1148
1288
  var Character = class extends Group {
1149
- constructor(characterDescription, animationConfig, characterModelLoader, characterId, modelLoadedCallback, cameraManager, composer) {
1289
+ constructor(characterDescription, animationConfig, characterModelLoader, characterId, modelLoadedCallback, cameraManager, composer, isLocal) {
1150
1290
  super();
1151
1291
  this.characterDescription = characterDescription;
1152
1292
  this.animationConfig = animationConfig;
@@ -1155,6 +1295,7 @@ var Character = class extends Group {
1155
1295
  this.modelLoadedCallback = modelLoadedCallback;
1156
1296
  this.cameraManager = cameraManager;
1157
1297
  this.composer = composer;
1298
+ this.isLocal = isLocal;
1158
1299
  this.model = null;
1159
1300
  this.color = new Color3();
1160
1301
  this.tooltip = null;
@@ -1167,14 +1308,16 @@ var Character = class extends Group {
1167
1308
  this.model = new CharacterModel(
1168
1309
  this.characterDescription,
1169
1310
  this.animationConfig,
1170
- this.characterModelLoader
1311
+ this.characterModelLoader,
1312
+ this.cameraManager,
1313
+ this.characterId,
1314
+ this.isLocal
1171
1315
  );
1172
1316
  await this.model.init();
1173
1317
  this.add(this.model.mesh);
1174
1318
  if (this.speakingIndicator === null) {
1175
1319
  this.speakingIndicator = new CharacterSpeakingIndicator(this.composer.postPostScene);
1176
1320
  }
1177
- this.color = this.model.material.colorsCube216[this.characterId];
1178
1321
  this.modelLoadedCallback();
1179
1322
  }
1180
1323
  updateAnimation(targetAnimation) {
@@ -1197,11 +1340,6 @@ var Character = class extends Group {
1197
1340
  );
1198
1341
  }
1199
1342
  }
1200
- if (typeof this.model.material.uniforms.time !== "undefined") {
1201
- this.model.material.uniforms.time.value = time;
1202
- this.model.material.uniforms.diffuseRandomColor.value = this.color;
1203
- this.model.material.update();
1204
- }
1205
1343
  this.model.update(deltaTime);
1206
1344
  }
1207
1345
  getCurrentAnimation() {
@@ -1611,8 +1749,6 @@ var CharacterManager = class {
1611
1749
  this.remoteCharacterControllers = /* @__PURE__ */ new Map();
1612
1750
  this.localCharacterSpawned = false;
1613
1751
  this.localCharacter = null;
1614
- this.cameraOffsetTarget = 0;
1615
- this.cameraOffset = 0;
1616
1752
  this.speakingCharacters = /* @__PURE__ */ new Map();
1617
1753
  this.group = new Group2();
1618
1754
  }
@@ -1626,7 +1762,8 @@ var CharacterManager = class {
1626
1762
  () => {
1627
1763
  },
1628
1764
  this.cameraManager,
1629
- this.composer
1765
+ this.composer,
1766
+ true
1630
1767
  );
1631
1768
  const quaternion = new Quaternion5().setFromEuler(character.rotation);
1632
1769
  this.sendUpdate({
@@ -1665,7 +1802,8 @@ var CharacterManager = class {
1665
1802
  () => {
1666
1803
  },
1667
1804
  this.cameraManager,
1668
- this.composer
1805
+ this.composer,
1806
+ false
1669
1807
  );
1670
1808
  this.remoteCharacters.set(id, character);
1671
1809
  const remoteController = new RemoteController(character, id);
@@ -1712,12 +1850,9 @@ var CharacterManager = class {
1712
1850
  if (this.timeManager.frame % 2 === 0) {
1713
1851
  this.sendUpdate(this.localController.networkState);
1714
1852
  }
1715
- this.cameraOffsetTarget = this.cameraManager.targetDistance <= 0.4 ? 0.13 : 0;
1716
- this.cameraOffset += ease(this.cameraOffsetTarget, this.cameraOffset, 0.1);
1717
- const targetOffset = new Vector38(0, 0, this.cameraOffset);
1718
- targetOffset.add(this.headTargetOffset);
1719
- targetOffset.applyQuaternion(this.localCharacter.quaternion);
1720
- this.cameraManager.setTarget(targetOffset.add(this.localCharacter.position));
1853
+ const targetOffset = new Vector38();
1854
+ targetOffset.add(this.headTargetOffset).applyQuaternion(this.localCharacter.quaternion).add(this.localCharacter.position);
1855
+ this.cameraManager.setTarget(targetOffset);
1721
1856
  for (const [id, update] of this.clientStates) {
1722
1857
  if (this.remoteCharacters.has(id) && this.speakingCharacters.has(id)) {
1723
1858
  const character = this.remoteCharacters.get(id);
@@ -1875,9 +2010,17 @@ var KeyInputManager = class {
1875
2010
  this.shouldCaptureKeyPress = shouldCaptureKeyPress;
1876
2011
  this.keys = /* @__PURE__ */ new Map();
1877
2012
  this.eventHandlerCollection = new EventHandlerCollection();
2013
+ this.directionJoystick = null;
1878
2014
  this.eventHandlerCollection.add(document, "keydown", this.onKeyDown.bind(this));
1879
2015
  this.eventHandlerCollection.add(document, "keyup", this.onKeyUp.bind(this));
1880
2016
  this.eventHandlerCollection.add(window, "blur", this.handleUnfocus.bind(this));
2017
+ this.directionJoystick = new VirtualJoystick({
2018
+ radius: 70,
2019
+ inner_radius: 20,
2020
+ x: 70,
2021
+ y: 0,
2022
+ mouse_support: false
2023
+ });
1881
2024
  }
1882
2025
  handleUnfocus(_event) {
1883
2026
  this.keys.clear();
@@ -1901,19 +2044,19 @@ var KeyInputManager = class {
1901
2044
  return this.keys.get(key) || false;
1902
2045
  }
1903
2046
  isMovementKeyPressed() {
1904
- return ["w" /* W */, "a" /* A */, "s" /* S */, "d" /* D */].some((key) => this.isKeyPressed(key));
2047
+ return ["w" /* W */, "a" /* A */, "s" /* S */, "d" /* D */].some((key) => this.isKeyPressed(key)) || this.directionJoystick.hasDirection;
1905
2048
  }
1906
2049
  get forward() {
1907
- return this.isKeyPressed("w" /* W */);
2050
+ return this.isKeyPressed("w" /* W */) || this.directionJoystick.up;
1908
2051
  }
1909
2052
  get backward() {
1910
- return this.isKeyPressed("s" /* S */);
2053
+ return this.isKeyPressed("s" /* S */) || this.directionJoystick.down;
1911
2054
  }
1912
2055
  get left() {
1913
- return this.isKeyPressed("a" /* A */);
2056
+ return this.isKeyPressed("a" /* A */) || this.directionJoystick.left;
1914
2057
  }
1915
2058
  get right() {
1916
- return this.isKeyPressed("d" /* D */);
2059
+ return this.isKeyPressed("d" /* D */) || this.directionJoystick.right;
1917
2060
  }
1918
2061
  get run() {
1919
2062
  return this.isKeyPressed("shift" /* SHIFT */);
@@ -2067,8 +2210,8 @@ var BrightnessContrastSaturationFolder = class {
2067
2210
  // src/tweakpane/blades/environmentFolder.ts
2068
2211
  var sunValues = {
2069
2212
  sunPosition: {
2070
- sunAzimuthalAngle: 215,
2071
- sunPolarAngle: -39
2213
+ sunAzimuthalAngle: 214.5,
2214
+ sunPolarAngle: -41.5
2072
2215
  },
2073
2216
  sunIntensity: 1,
2074
2217
  sunColor: { r: 1, g: 1, b: 1 }
@@ -2222,14 +2365,14 @@ var EnvironmentFolder = class {
2222
2365
  // src/tweakpane/blades/postExtrasFolder.ts
2223
2366
  var extrasValues = {
2224
2367
  grain: 0.055,
2225
- bloom: 0.25
2368
+ bloom: 3
2226
2369
  };
2227
2370
  var extrasOptions = {
2228
2371
  grain: {
2229
2372
  amount: { min: 0, max: 0.2, step: 2e-3 }
2230
2373
  },
2231
2374
  bloom: {
2232
- amount: { min: 0, max: 2, step: 0.05 }
2375
+ amount: { min: 0, max: 5, step: 0.05 }
2233
2376
  }
2234
2377
  };
2235
2378
  var PostExtrasFolder = class {
@@ -2262,7 +2405,7 @@ var rendererValues = {
2262
2405
  shadowMap: 2,
2263
2406
  toneMapping: 5,
2264
2407
  exposure: 1,
2265
- bgIntensity: 0.45,
2408
+ bgIntensity: 1,
2266
2409
  bgBlurriness: 0
2267
2410
  };
2268
2411
  var rendererOptions = {
@@ -2358,18 +2501,15 @@ var RendererStatsFolder = class {
2358
2501
  FPS: "0"
2359
2502
  };
2360
2503
  this.folder = parentFolder.addFolder({ title: "renderStats", expanded });
2361
- this.performance = this.folder.addFolder({ title: "performance", expanded: true });
2362
- this.defails = this.folder.addFolder({ title: "pipeline details", expanded: false });
2363
- this.folder.addBlade({ view: "separator" });
2364
- this.performance.addBinding(this.statsData, "FPS", { readonly: true });
2365
- this.performance.addBinding(this.statsData, "deltaTime", { readonly: true });
2366
- this.performance.addBinding(this.statsData, "rawDeltaTime", { readonly: true });
2367
- this.defails.addBinding(this.statsData, "triangles", { readonly: true });
2368
- this.defails.addBinding(this.statsData, "geometries", { readonly: true });
2369
- this.defails.addBinding(this.statsData, "textures", { readonly: true });
2370
- this.defails.addBinding(this.statsData, "shaders", { readonly: true });
2371
- this.defails.addBinding(this.statsData, "postPasses", { readonly: true });
2372
- this.defails.addBinding(this.statsData, "drawCalls", { readonly: true });
2504
+ this.folder.addBinding(this.statsData, "FPS", { readonly: true });
2505
+ this.folder.addBinding(this.statsData, "deltaTime", { readonly: true });
2506
+ this.folder.addBinding(this.statsData, "rawDeltaTime", { readonly: true });
2507
+ this.folder.addBinding(this.statsData, "triangles", { readonly: true });
2508
+ this.folder.addBinding(this.statsData, "geometries", { readonly: true });
2509
+ this.folder.addBinding(this.statsData, "textures", { readonly: true });
2510
+ this.folder.addBinding(this.statsData, "shaders", { readonly: true });
2511
+ this.folder.addBinding(this.statsData, "postPasses", { readonly: true });
2512
+ this.folder.addBinding(this.statsData, "drawCalls", { readonly: true });
2373
2513
  }
2374
2514
  update(renderer, composer, timeManager) {
2375
2515
  const { geometries, textures } = renderer.info.memory;
@@ -2716,7 +2856,7 @@ var ToneMappingFolder = class {
2716
2856
  // src/tweakpane/tweakPaneStyle.ts
2717
2857
  var tweakPaneStyle = `
2718
2858
  :root {
2719
- --tp-base-background-color: rgba(0, 0, 0, 0.6);
2859
+ --tp-base-background-color: rgba(12, 12, 12, 0.6);
2720
2860
  --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
2721
2861
  --tp-button-background-color: hsla(0, 0%, 80%, 1);
2722
2862
  --tp-button-background-color-active: hsla(0, 0%, 100%, 1);
@@ -2737,6 +2877,9 @@ var tweakPaneStyle = `
2737
2877
  --tp-label-foreground-color: hsla(0, 0%, 100%, 0.6);
2738
2878
  --tp-monitor-background-color: hsla(0, 0%, 0%, 0.3);
2739
2879
  --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.3);
2880
+ -webkit-user-select: none;
2881
+ -ms-user-select: none;
2882
+ user-select: none;
2740
2883
  }
2741
2884
 
2742
2885
  .tp-brkv {
@@ -2746,28 +2889,40 @@ var tweakPaneStyle = `
2746
2889
  }
2747
2890
 
2748
2891
  .tp-dfwv {
2892
+ z-index: 100;
2749
2893
  color: white;
2750
- backdrop-filter: blur(12px);
2751
- width: 360px !important;
2894
+ width: 600px !important;
2752
2895
  display: none;
2753
2896
  -webkit-user-select: none;
2754
2897
  -ms-user-select: none;
2755
2898
  user-select: none;
2756
2899
  }
2757
2900
 
2901
+ .tp-fldv {
2902
+ margin: 1px 0px 0px 0px !important;
2903
+ }
2904
+
2905
+ .tp-fldv_b {
2906
+ overflow: visible !important;
2907
+ }
2908
+
2758
2909
  .tp-fldv_t {
2759
- font-size: 11px;
2760
- background-color: rgba(0, 0, 0, 0.1);
2910
+ font-size: 13px;
2911
+ font-weight: 900;
2912
+ color: #ffffff;
2913
+ background-color: rgba(70, 70, 70, 0.3);
2914
+ border-top: 1px solid rgba(210, 210, 210, 0.1);
2915
+ border-radius: 3px;
2761
2916
  }
2762
2917
 
2763
2918
  .tp-lblv_l {
2764
- font-size: 11px;
2919
+ font-size: 12px;
2765
2920
  padding-left: 0px !important;
2766
2921
  padding-right: 0px !important;
2767
2922
  }
2768
2923
 
2769
2924
  .tp-lblv_v {
2770
- width: 180px;
2925
+ width: 150px;
2771
2926
  }
2772
2927
 
2773
2928
  .tp-sldtxtv_t {
@@ -2775,9 +2930,13 @@ var tweakPaneStyle = `
2775
2930
  }
2776
2931
 
2777
2932
  .tp-sglv_i {
2778
- font-size: 11px;
2933
+ font-size: 12px;
2779
2934
  color: rgba(255, 255, 255, 0.7);
2780
2935
  }
2936
+
2937
+ .tp-ckbv_w {
2938
+ border: 1px solid rgba(200, 200, 250, 0.2);
2939
+ }
2781
2940
  `;
2782
2941
 
2783
2942
  // src/tweakpane/TweakPane.ts
@@ -2786,9 +2945,13 @@ var TweakPane = class {
2786
2945
  this.renderer = renderer;
2787
2946
  this.scene = scene;
2788
2947
  this.composer = composer;
2789
- this.gui = new Pane();
2790
2948
  this.saveVisibilityInLocalStorage = true;
2791
2949
  this.guiVisible = false;
2950
+ const appWrapper = document.getElementById("app");
2951
+ const tweakPaneWrapper = document.createElement("div");
2952
+ tweakPaneWrapper.id = "tweakpane-panel";
2953
+ appWrapper.appendChild(tweakPaneWrapper);
2954
+ this.gui = new Pane({ container: tweakPaneWrapper });
2792
2955
  this.gui.registerPlugin(EssentialsPlugin);
2793
2956
  if (this.saveVisibilityInLocalStorage) {
2794
2957
  const localStorageGuiVisible = localStorage.getItem("guiVisible");
@@ -2815,21 +2978,22 @@ var TweakPane = class {
2815
2978
  this.toneMappingFolder.folder.hidden = rendererValues.toneMapping === 5 ? false : true;
2816
2979
  this.export = this.gui.addFolder({ title: "import / export", expanded: false });
2817
2980
  window.addEventListener("keydown", this.processKey.bind(this));
2818
- this.setupGUIListeners.bind(this)();
2819
2981
  this.setupRenderPane = this.setupRenderPane.bind(this);
2820
- }
2821
- processKey(e) {
2822
- if (e.key === "p")
2823
- this.toggleGUI();
2982
+ this.setupGUIListeners.bind(this)();
2824
2983
  }
2825
2984
  setupGUIListeners() {
2826
2985
  const gui = this.gui;
2827
2986
  const paneElement = gui.containerElem_;
2828
- paneElement.style.display = this.guiVisible ? "unset" : "none";
2987
+ paneElement.style.right = this.guiVisible ? "0px" : "-450px";
2988
+ this.gui.element.addEventListener("mouseenter", () => setTweakpaneActive(true));
2829
2989
  this.gui.element.addEventListener("mousedown", () => setTweakpaneActive(true));
2830
2990
  this.gui.element.addEventListener("mouseup", () => setTweakpaneActive(false));
2831
2991
  this.gui.element.addEventListener("mouseleave", () => setTweakpaneActive(false));
2832
2992
  }
2993
+ processKey(e) {
2994
+ if (e.key === "p")
2995
+ this.toggleGUI();
2996
+ }
2833
2997
  setupRenderPane(composer, normalPass, ppssaoEffect, ppssaoPass, n8aopass, toneMappingEffect, toneMappingPass, brightnessContrastSaturation, bloomEffect, gaussGrainEffect, hasLighting, sun, setHDR, setAmbientLight, setFog) {
2834
2998
  this.rendererFolder.setupChangeEvent(
2835
2999
  this.scene,
@@ -2901,10 +3065,10 @@ var TweakPane = class {
2901
3065
  input.click();
2902
3066
  }
2903
3067
  toggleGUI() {
3068
+ this.guiVisible = !this.guiVisible;
2904
3069
  const gui = this.gui;
2905
3070
  const paneElement = gui.containerElem_;
2906
- paneElement.style.display = this.guiVisible ? "none" : "unset";
2907
- this.guiVisible = !this.guiVisible;
3071
+ paneElement.style.right = this.guiVisible ? "0px" : "-450px";
2908
3072
  if (this.saveVisibilityInLocalStorage) {
2909
3073
  localStorage.setItem("guiVisible", this.guiVisible === true ? "true" : "false");
2910
3074
  }
@@ -2972,8 +3136,8 @@ var Sun = class extends Group4 {
2972
3136
  }
2973
3137
  this.directionalLight = new DirectionalLight(16777215, 0.5);
2974
3138
  this.directionalLight.intensity = sunValues.sunIntensity;
2975
- this.directionalLight.shadow.normalBias = 0.05;
2976
- this.directionalLight.shadow.radius = 1.5;
3139
+ this.directionalLight.shadow.normalBias = 0.01;
3140
+ this.directionalLight.shadow.radius = 0.02;
2977
3141
  this.directionalLight.shadow.camera = this.shadowCamera;
2978
3142
  this.directionalLight.shadow.mapSize.set(this.shadowResolution, this.shadowResolution);
2979
3143
  this.directionalLight.castShadow = true;
@@ -3822,7 +3986,7 @@ var EffectShader = {
3822
3986
  import {
3823
3987
  BufferAttribute,
3824
3988
  BufferGeometry,
3825
- Mesh as Mesh3,
3989
+ Mesh as Mesh4,
3826
3990
  OrthographicCamera as OrthographicCamera2,
3827
3991
  Sphere
3828
3992
  } from "three";
@@ -3838,7 +4002,7 @@ var FullScreenTriangle = class {
3838
4002
  this.geometry.boundingSphere = new Sphere();
3839
4003
  this.geometry.computeBoundingSphere = function() {
3840
4004
  };
3841
- this.mesh = new Mesh3(this.geometry, material);
4005
+ this.mesh = new Mesh4(this.geometry, material);
3842
4006
  this.mesh.frustumCulled = false;
3843
4007
  }
3844
4008
  get material() {
@@ -4686,7 +4850,6 @@ var Composer = class {
4686
4850
  if (envMap) {
4687
4851
  envMap.colorSpace = LinearSRGBColorSpace;
4688
4852
  envMap.needsUpdate = true;
4689
- this.scene.environment = envMap;
4690
4853
  this.scene.background = envMap;
4691
4854
  this.scene.backgroundIntensity = rendererValues.bgIntensity;
4692
4855
  this.isEnvHDRI = true;
@@ -4809,7 +4972,7 @@ import {
4809
4972
  Group as Group5,
4810
4973
  Line3 as Line32,
4811
4974
  Matrix4 as Matrix46,
4812
- Mesh as Mesh4,
4975
+ Mesh as Mesh5,
4813
4976
  MeshBasicMaterial as MeshBasicMaterial3,
4814
4977
  Quaternion as Quaternion6,
4815
4978
  Ray as Ray2,
@@ -4897,7 +5060,7 @@ var CollisionsManager = class {
4897
5060
  };
4898
5061
  if (this.debug) {
4899
5062
  newBufferGeometry.boundsTree = meshBVH;
4900
- const wireframeMesh = new Mesh4(newBufferGeometry, new MeshBasicMaterial3({ wireframe: true }));
5063
+ const wireframeMesh = new Mesh5(newBufferGeometry, new MeshBasicMaterial3({ wireframe: true }));
4901
5064
  const normalsHelper = new VertexNormalsHelper(wireframeMesh, 0.25, 65280);
4902
5065
  const visualizer = new MeshBVHHelper(wireframeMesh, 4);
4903
5066
  visualizer.edgeMaterial.color = new Color8("blue");
@@ -5003,13 +5166,10 @@ var CollisionsManager = class {
5003
5166
  return collisionPosition;
5004
5167
  }
5005
5168
  applyColliders(tempSegment, radius) {
5006
- let collidedElements = null;
5169
+ const collidedElements = /* @__PURE__ */ new Map();
5007
5170
  for (const meshState of this.collisionMeshState.values()) {
5008
5171
  const collisionPosition = this.applyCollider(tempSegment, radius, meshState);
5009
5172
  if (collisionPosition && meshState.trackCollisions) {
5010
- if (collidedElements === null) {
5011
- collidedElements = /* @__PURE__ */ new Map();
5012
- }
5013
5173
  const relativePosition = getRelativePositionAndRotationRelativeToObject(
5014
5174
  {
5015
5175
  position: collisionPosition,
@@ -5022,7 +5182,16 @@ var CollisionsManager = class {
5022
5182
  });
5023
5183
  }
5024
5184
  }
5025
- this.collisionTrigger.setCurrentCollisions(collidedElements);
5185
+ const reportedCollidingElements = new Map(collidedElements);
5186
+ if (this.previouslyCollidingElements) {
5187
+ for (const [element, position] of this.previouslyCollidingElements) {
5188
+ if (!reportedCollidingElements.has(element)) {
5189
+ reportedCollidingElements.set(element, position);
5190
+ }
5191
+ }
5192
+ }
5193
+ this.previouslyCollidingElements = collidedElements;
5194
+ this.collisionTrigger.setCurrentCollisions(reportedCollidingElements);
5026
5195
  }
5027
5196
  };
5028
5197
  export {