@mml-io/3d-web-client-core 0.0.0-experimental-74874a9-20230815 → 0.0.0-experimental-9432cd6-20230816
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.
@@ -0,0 +1,32 @@
|
|
1
|
+
import * as THREE from "three";
|
2
|
+
type RGBA = {
|
3
|
+
r: number;
|
4
|
+
g: number;
|
5
|
+
b: number;
|
6
|
+
a: number;
|
7
|
+
};
|
8
|
+
type CanvasTextOptions = {
|
9
|
+
fontSize: number;
|
10
|
+
textColorRGB255A1: RGBA;
|
11
|
+
backgroundColorRGB255A1?: RGBA;
|
12
|
+
font?: string;
|
13
|
+
bold?: boolean;
|
14
|
+
paddingPx?: number;
|
15
|
+
alignment?: string;
|
16
|
+
dimensions?: {
|
17
|
+
width: number;
|
18
|
+
height: number;
|
19
|
+
};
|
20
|
+
};
|
21
|
+
export declare function CanvasText(message: string, options: CanvasTextOptions): HTMLCanvasElement;
|
22
|
+
export declare function THREECanvasTextTexture(text: string, options: CanvasTextOptions): {
|
23
|
+
texture: THREE.Texture;
|
24
|
+
width: number;
|
25
|
+
height: number;
|
26
|
+
};
|
27
|
+
export declare function THREECanvasTextMaterial(text: string, options: CanvasTextOptions): {
|
28
|
+
material: THREE.MeshBasicMaterial;
|
29
|
+
width: number;
|
30
|
+
height: number;
|
31
|
+
};
|
32
|
+
export {};
|
@@ -4,6 +4,7 @@ import { CollisionsManager } from "../collisions/CollisionsManager";
|
|
4
4
|
import { KeyInputManager } from "../input/KeyInputManager";
|
5
5
|
import { TimeManager } from "../time/TimeManager";
|
6
6
|
import { CharacterModel } from "./CharacterModel";
|
7
|
+
import { CharacterTooltip } from "./CharacterTooltip";
|
7
8
|
import { LocalController } from "./LocalController";
|
8
9
|
export type CharacterDescription = {
|
9
10
|
meshFileUrl: string;
|
@@ -27,6 +28,7 @@ export declare class Character {
|
|
27
28
|
model: CharacterModel | null;
|
28
29
|
color: Color;
|
29
30
|
position: Vector3;
|
31
|
+
tooltip: CharacterTooltip | null;
|
30
32
|
constructor(characterDescription: CharacterDescription, id: number, isLocal: boolean, modelLoadedCallback: () => void, collisionsManager: CollisionsManager, keyInputManager: KeyInputManager, cameraManager: CameraManager, timeManager: TimeManager);
|
31
33
|
private load;
|
32
34
|
update(time: number): void;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Camera, Object3D } from "three";
|
2
|
+
export declare class CharacterTooltip {
|
3
|
+
private texture;
|
4
|
+
private geometry;
|
5
|
+
private material;
|
6
|
+
private mesh;
|
7
|
+
private visibleOpacity;
|
8
|
+
private targetOpacity;
|
9
|
+
private fadingSpeed;
|
10
|
+
private secondsToFadeOut;
|
11
|
+
private props;
|
12
|
+
constructor(parentModel: Object3D);
|
13
|
+
private redrawText;
|
14
|
+
setText(text: string, temporary?: boolean): void;
|
15
|
+
hide(): void;
|
16
|
+
update(camera: Camera): void;
|
17
|
+
}
|
package/build/index.js
CHANGED
@@ -168,7 +168,7 @@ var CameraManager = class {
|
|
168
168
|
};
|
169
169
|
|
170
170
|
// src/character/Character.ts
|
171
|
-
import { Color as
|
171
|
+
import { Color as Color3, Vector3 as Vector34 } from "three";
|
172
172
|
|
173
173
|
// src/character/CharacterModel.ts
|
174
174
|
import {
|
@@ -724,6 +724,247 @@ var CharacterModel = class {
|
|
724
724
|
}
|
725
725
|
};
|
726
726
|
|
727
|
+
// src/character/CharacterTooltip.ts
|
728
|
+
import {
|
729
|
+
Color as Color2,
|
730
|
+
FrontSide,
|
731
|
+
LinearFilter as LinearFilter2,
|
732
|
+
Mesh as Mesh2,
|
733
|
+
MeshBasicMaterial as MeshBasicMaterial2,
|
734
|
+
PlaneGeometry
|
735
|
+
} from "three";
|
736
|
+
|
737
|
+
// src/character/CanvasText.ts
|
738
|
+
import * as THREE from "three";
|
739
|
+
function getTextAlignOffset(textAlign, width) {
|
740
|
+
switch (textAlign) {
|
741
|
+
case "center":
|
742
|
+
return width / 2;
|
743
|
+
case "right":
|
744
|
+
return width;
|
745
|
+
default:
|
746
|
+
return 0;
|
747
|
+
}
|
748
|
+
}
|
749
|
+
function printAtWordWrap(context, fullText, x, y, lineHeight, fitWidth, padding, alignment) {
|
750
|
+
const lines = fullText.split("\n");
|
751
|
+
let currentLine = 0;
|
752
|
+
for (const text of lines) {
|
753
|
+
fitWidth = fitWidth || 0;
|
754
|
+
if (fitWidth <= 0) {
|
755
|
+
context.fillText(text, x, y + lineHeight * currentLine);
|
756
|
+
currentLine++;
|
757
|
+
continue;
|
758
|
+
}
|
759
|
+
let words = text.split(" ");
|
760
|
+
let lastWordIndex = 1;
|
761
|
+
while (words.length > 0 && lastWordIndex <= words.length) {
|
762
|
+
const str = words.slice(0, lastWordIndex).join(" ");
|
763
|
+
const textWidth = context.measureText(str).width;
|
764
|
+
if (textWidth + padding * 2 > fitWidth) {
|
765
|
+
if (lastWordIndex === 1) {
|
766
|
+
lastWordIndex = 2;
|
767
|
+
}
|
768
|
+
context.fillText(
|
769
|
+
words.slice(0, lastWordIndex - 1).join(" "),
|
770
|
+
x + padding,
|
771
|
+
y + lineHeight * currentLine + padding
|
772
|
+
);
|
773
|
+
currentLine++;
|
774
|
+
words = words.splice(lastWordIndex - 1);
|
775
|
+
lastWordIndex = 1;
|
776
|
+
} else {
|
777
|
+
lastWordIndex++;
|
778
|
+
}
|
779
|
+
}
|
780
|
+
if (lastWordIndex > 0 && words.length > 0) {
|
781
|
+
const xOffset = alignment === "center" ? 0 : padding;
|
782
|
+
context.fillText(words.join(" "), x + xOffset, y + lineHeight * currentLine + padding);
|
783
|
+
currentLine++;
|
784
|
+
}
|
785
|
+
}
|
786
|
+
}
|
787
|
+
function CanvasText(message, options) {
|
788
|
+
const fontsize = options.fontSize;
|
789
|
+
const textColor = options.textColorRGB255A1;
|
790
|
+
const backgroundColor = options.backgroundColorRGB255A1 || { r: 255, g: 255, b: 255, a: 1 };
|
791
|
+
const padding = options.paddingPx || 0;
|
792
|
+
const font = options.font || "Arial";
|
793
|
+
const fontString = (options.bold ? "bold " : "") + fontsize + "px " + font;
|
794
|
+
const canvas = document.createElement("canvas");
|
795
|
+
const ct = canvas.getContext("2d");
|
796
|
+
const textAlign = options.alignment ?? "left";
|
797
|
+
if (options.dimensions) {
|
798
|
+
canvas.width = options.dimensions.width;
|
799
|
+
canvas.height = options.dimensions.height;
|
800
|
+
ct.clearRect(0, 0, canvas.width, canvas.height);
|
801
|
+
ct.font = fontString;
|
802
|
+
ct.textAlign = textAlign;
|
803
|
+
ct.fillStyle = `rgba(${backgroundColor.r}, ${backgroundColor.g}, ${backgroundColor.b}, ${backgroundColor.a})`;
|
804
|
+
ct.lineWidth = 0;
|
805
|
+
ct.fillRect(0, 0, canvas.width, canvas.height);
|
806
|
+
ct.fillStyle = `rgba(${textColor.r}, ${textColor.g}, ${textColor.b}, ${textColor.a})`;
|
807
|
+
ct.font = fontString;
|
808
|
+
printAtWordWrap(
|
809
|
+
ct,
|
810
|
+
message,
|
811
|
+
getTextAlignOffset(textAlign, canvas.width),
|
812
|
+
fontsize,
|
813
|
+
fontsize,
|
814
|
+
canvas.width,
|
815
|
+
padding,
|
816
|
+
textAlign
|
817
|
+
);
|
818
|
+
} else {
|
819
|
+
ct.font = fontString;
|
820
|
+
const metrics = ct.measureText(message);
|
821
|
+
const textWidth = metrics.width;
|
822
|
+
const textHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
|
823
|
+
canvas.width = textWidth + padding * 2;
|
824
|
+
canvas.height = textHeight + padding;
|
825
|
+
ct.clearRect(0, 0, canvas.width, canvas.height);
|
826
|
+
ct.font = fontString;
|
827
|
+
ct.textAlign = textAlign;
|
828
|
+
ct.fillStyle = `rgba(${backgroundColor.r}, ${backgroundColor.g}, ${backgroundColor.b}, ${backgroundColor.a})`;
|
829
|
+
ct.lineWidth = 0;
|
830
|
+
ct.fillRect(0, 0, canvas.width, canvas.height);
|
831
|
+
ct.fillStyle = `rgba(${textColor.r}, ${textColor.g}, ${textColor.b}, ${textColor.a})`;
|
832
|
+
ct.font = fontString;
|
833
|
+
ct.fillText(message, padding + getTextAlignOffset(textAlign, textWidth), textHeight);
|
834
|
+
}
|
835
|
+
return canvas;
|
836
|
+
}
|
837
|
+
function THREECanvasTextTexture(text, options) {
|
838
|
+
const canvas = CanvasText(text, options);
|
839
|
+
const texture = new THREE.Texture(canvas);
|
840
|
+
texture.minFilter = THREE.LinearFilter;
|
841
|
+
texture.magFilter = THREE.LinearFilter;
|
842
|
+
texture.format = THREE.RGBAFormat;
|
843
|
+
texture.needsUpdate = true;
|
844
|
+
return { texture, width: canvas.width, height: canvas.height };
|
845
|
+
}
|
846
|
+
|
847
|
+
// src/character/CharacterTooltip.ts
|
848
|
+
var fontScale = 5;
|
849
|
+
var defaultLabelColor = new Color2(0);
|
850
|
+
var defaultFontColor = new Color2(16777215);
|
851
|
+
var defaultLabelAlignment = "center" /* center */;
|
852
|
+
var defaultLabelFontSize = 9;
|
853
|
+
var defaultLabelPadding = 0;
|
854
|
+
var defaultLabelWidth = 0.25;
|
855
|
+
var defaultLabelHeight = 0.125;
|
856
|
+
var defaultLabelCastShadows = true;
|
857
|
+
var CharacterTooltip = class {
|
858
|
+
constructor(parentModel) {
|
859
|
+
__publicField(this, "texture");
|
860
|
+
__publicField(this, "geometry");
|
861
|
+
__publicField(this, "material");
|
862
|
+
__publicField(this, "mesh");
|
863
|
+
__publicField(this, "visibleOpacity", 0.85);
|
864
|
+
__publicField(this, "targetOpacity", 0);
|
865
|
+
__publicField(this, "fadingSpeed", 0.02);
|
866
|
+
__publicField(this, "secondsToFadeOut", 15);
|
867
|
+
__publicField(this, "props", {
|
868
|
+
content: "",
|
869
|
+
alignment: defaultLabelAlignment,
|
870
|
+
width: defaultLabelWidth,
|
871
|
+
height: defaultLabelHeight,
|
872
|
+
fontSize: defaultLabelFontSize,
|
873
|
+
padding: defaultLabelPadding,
|
874
|
+
color: defaultLabelColor,
|
875
|
+
fontColor: defaultFontColor,
|
876
|
+
castShadows: defaultLabelCastShadows
|
877
|
+
});
|
878
|
+
this.setText = this.setText.bind(this);
|
879
|
+
this.material = new MeshBasicMaterial2({
|
880
|
+
map: this.texture,
|
881
|
+
transparent: true,
|
882
|
+
opacity: 0
|
883
|
+
});
|
884
|
+
this.material.side = FrontSide;
|
885
|
+
this.geometry = new PlaneGeometry(1, 1, 1, 1);
|
886
|
+
this.mesh = new Mesh2(this.geometry, this.material);
|
887
|
+
this.mesh.position.set(0, 1.6, 0);
|
888
|
+
this.mesh.visible = false;
|
889
|
+
parentModel.add(this.mesh);
|
890
|
+
}
|
891
|
+
redrawText(content) {
|
892
|
+
if (!this.material) {
|
893
|
+
return;
|
894
|
+
}
|
895
|
+
if (this.material.map) {
|
896
|
+
this.material.map.dispose();
|
897
|
+
}
|
898
|
+
const { texture, width, height } = THREECanvasTextTexture(content, {
|
899
|
+
bold: true,
|
900
|
+
fontSize: this.props.fontSize * fontScale,
|
901
|
+
paddingPx: this.props.padding,
|
902
|
+
textColorRGB255A1: {
|
903
|
+
r: this.props.fontColor.r * 255,
|
904
|
+
g: this.props.fontColor.g * 255,
|
905
|
+
b: this.props.fontColor.b * 255,
|
906
|
+
a: 1
|
907
|
+
},
|
908
|
+
backgroundColorRGB255A1: {
|
909
|
+
r: this.props.color.r * 255,
|
910
|
+
g: this.props.color.g * 255,
|
911
|
+
b: this.props.color.b * 255,
|
912
|
+
a: 1
|
913
|
+
},
|
914
|
+
dimensions: {
|
915
|
+
width: this.props.width * (100 * fontScale),
|
916
|
+
height: this.props.height * (100 * fontScale)
|
917
|
+
},
|
918
|
+
alignment: this.props.alignment
|
919
|
+
});
|
920
|
+
this.material.map = texture;
|
921
|
+
this.material.map.magFilter = LinearFilter2;
|
922
|
+
this.material.map.minFilter = LinearFilter2;
|
923
|
+
this.material.needsUpdate = true;
|
924
|
+
this.mesh.scale.x = width / (100 * fontScale);
|
925
|
+
this.mesh.scale.y = height / (100 * fontScale);
|
926
|
+
this.mesh.position.y = 1.6;
|
927
|
+
}
|
928
|
+
setText(text, temporary = false) {
|
929
|
+
this.redrawText(text);
|
930
|
+
this.mesh.visible = true;
|
931
|
+
this.targetOpacity = this.visibleOpacity;
|
932
|
+
if (temporary) {
|
933
|
+
setTimeout(() => {
|
934
|
+
this.hide();
|
935
|
+
}, this.secondsToFadeOut * 1e3);
|
936
|
+
}
|
937
|
+
}
|
938
|
+
hide() {
|
939
|
+
this.targetOpacity = 0;
|
940
|
+
}
|
941
|
+
update(camera) {
|
942
|
+
this.mesh.lookAt(camera.position);
|
943
|
+
const opacity = this.mesh.material.opacity;
|
944
|
+
if (opacity < this.targetOpacity) {
|
945
|
+
this.mesh.material.opacity = Math.min(
|
946
|
+
this.mesh.material.opacity + this.fadingSpeed,
|
947
|
+
this.targetOpacity
|
948
|
+
);
|
949
|
+
} else if (opacity > this.targetOpacity) {
|
950
|
+
this.mesh.material.opacity = Math.max(
|
951
|
+
this.mesh.material.opacity - this.fadingSpeed,
|
952
|
+
this.targetOpacity
|
953
|
+
);
|
954
|
+
if (opacity >= 1 && this.mesh.material.transparent === true) {
|
955
|
+
this.mesh.material.transparent = false;
|
956
|
+
this.mesh.material.needsUpdate = true;
|
957
|
+
} else if (opacity > 0 && opacity < 1 && this.mesh.material.transparent === false) {
|
958
|
+
this.mesh.material.transparent = true;
|
959
|
+
this.mesh.material.needsUpdate = true;
|
960
|
+
}
|
961
|
+
if (this.mesh.material.opacity <= 0) {
|
962
|
+
this.mesh.visible = false;
|
963
|
+
}
|
964
|
+
}
|
965
|
+
}
|
966
|
+
};
|
967
|
+
|
727
968
|
// src/character/LocalController.ts
|
728
969
|
import { Box3, Line3, Matrix4, Quaternion, Raycaster as Raycaster2, Vector3 as Vector33 } from "three";
|
729
970
|
var LocalController = class {
|
@@ -997,13 +1238,17 @@ var Character = class {
|
|
997
1238
|
__publicField(this, "controller", null);
|
998
1239
|
__publicField(this, "name", null);
|
999
1240
|
__publicField(this, "model", null);
|
1000
|
-
__publicField(this, "color", new
|
1241
|
+
__publicField(this, "color", new Color3());
|
1001
1242
|
__publicField(this, "position", new Vector34());
|
1243
|
+
__publicField(this, "tooltip", null);
|
1002
1244
|
this.load();
|
1003
1245
|
}
|
1004
1246
|
async load() {
|
1005
1247
|
this.model = new CharacterModel(this.characterDescription);
|
1006
1248
|
await this.model.init();
|
1249
|
+
if (this.tooltip === null) {
|
1250
|
+
this.tooltip = new CharacterTooltip(this.model.mesh);
|
1251
|
+
}
|
1007
1252
|
this.color = this.model.material.colorsCube216[this.id];
|
1008
1253
|
if (this.isLocal) {
|
1009
1254
|
this.controller = new LocalController(
|
@@ -1020,6 +1265,9 @@ var Character = class {
|
|
1020
1265
|
update(time) {
|
1021
1266
|
if (!this.model)
|
1022
1267
|
return;
|
1268
|
+
if (this.tooltip) {
|
1269
|
+
this.tooltip.update(this.cameraManager.camera);
|
1270
|
+
}
|
1023
1271
|
this.model.mesh.getWorldPosition(this.position);
|
1024
1272
|
if (typeof this.model.material.uniforms.time !== "undefined") {
|
1025
1273
|
this.model.material.uniforms.time.value = time;
|
@@ -1035,7 +1283,7 @@ import { Group, Vector3 as Vector36 } from "three";
|
|
1035
1283
|
// src/character/RemoteController.ts
|
1036
1284
|
import {
|
1037
1285
|
AnimationMixer as AnimationMixer2,
|
1038
|
-
Object3D as
|
1286
|
+
Object3D as Object3D4,
|
1039
1287
|
Quaternion as Quaternion2,
|
1040
1288
|
Vector3 as Vector35
|
1041
1289
|
} from "three";
|
@@ -1045,7 +1293,7 @@ var RemoteController = class {
|
|
1045
1293
|
this.id = id;
|
1046
1294
|
__publicField(this, "modelLoader", ModelLoader_default);
|
1047
1295
|
__publicField(this, "characterModel", null);
|
1048
|
-
__publicField(this, "animationMixer", new AnimationMixer2(new
|
1296
|
+
__publicField(this, "animationMixer", new AnimationMixer2(new Object3D4()));
|
1049
1297
|
__publicField(this, "animations", /* @__PURE__ */ new Map());
|
1050
1298
|
__publicField(this, "currentAnimation", 0 /* idle */);
|
1051
1299
|
__publicField(this, "networkState", {
|
@@ -1187,6 +1435,7 @@ var CharacterManager = class {
|
|
1187
1435
|
this.group.add(character.model.mesh);
|
1188
1436
|
if (isLocal) {
|
1189
1437
|
this.character = character;
|
1438
|
+
this.character.tooltip?.setText(`${id}`);
|
1190
1439
|
} else {
|
1191
1440
|
this.remoteCharacters.set(id, character);
|
1192
1441
|
const remoteController = new RemoteController(character, id);
|
@@ -1212,6 +1461,7 @@ var CharacterManager = class {
|
|
1212
1461
|
spawnPosition.z
|
1213
1462
|
);
|
1214
1463
|
this.remoteCharacterControllers.set(id, remoteController);
|
1464
|
+
character.tooltip?.setText(`${id}`);
|
1215
1465
|
}
|
1216
1466
|
resolve(character);
|
1217
1467
|
},
|
@@ -1441,7 +1691,7 @@ import {
|
|
1441
1691
|
NormalPass
|
1442
1692
|
} from "postprocessing";
|
1443
1693
|
import {
|
1444
|
-
Color as
|
1694
|
+
Color as Color5,
|
1445
1695
|
HalfFloatType,
|
1446
1696
|
LinearSRGBColorSpace,
|
1447
1697
|
LoadingManager as LoadingManager2,
|
@@ -1602,7 +1852,7 @@ var statsData = {
|
|
1602
1852
|
import {
|
1603
1853
|
BlendFunction as BlendFunction2
|
1604
1854
|
} from "postprocessing";
|
1605
|
-
import { Color as
|
1855
|
+
import { Color as Color4 } from "three";
|
1606
1856
|
import { Pane } from "tweakpane";
|
1607
1857
|
var TweakPane = class {
|
1608
1858
|
constructor(renderer, scene, composer) {
|
@@ -1868,7 +2118,7 @@ var TweakPane = class {
|
|
1868
2118
|
return;
|
1869
2119
|
}
|
1870
2120
|
if (e.presetKey === "color") {
|
1871
|
-
ssaoEffect.color = new
|
2121
|
+
ssaoEffect.color = new Color4().setRGB(e.value.r, e.value.g, e.value.b);
|
1872
2122
|
return;
|
1873
2123
|
}
|
1874
2124
|
ssaoEffect[preset] = e.value;
|
@@ -2232,7 +2482,7 @@ var Composer = class {
|
|
2232
2482
|
bias: composerValues.ssao.bias,
|
2233
2483
|
fade: composerValues.ssao.fade,
|
2234
2484
|
resolutionScale: composerValues.ssao.resolutionScale,
|
2235
|
-
color: new
|
2485
|
+
color: new Color5().setRGB(composerValues.ssao.color.r, composerValues.ssao.color.g, composerValues.ssao.color.b),
|
2236
2486
|
worldDistanceThreshold: composerValues.ssao.worldDistanceThreshold,
|
2237
2487
|
worldDistanceFalloff: composerValues.ssao.worldDistanceFalloff,
|
2238
2488
|
worldProximityThreshold: composerValues.ssao.worldProximityThreshold,
|
@@ -2392,11 +2642,11 @@ import {
|
|
2392
2642
|
getRelativePositionAndRotationRelativeToObject
|
2393
2643
|
} from "mml-web";
|
2394
2644
|
import {
|
2395
|
-
Color as
|
2645
|
+
Color as Color6,
|
2396
2646
|
DoubleSide,
|
2397
2647
|
Euler,
|
2398
|
-
FrontSide,
|
2399
|
-
Mesh as
|
2648
|
+
FrontSide as FrontSide2,
|
2649
|
+
Mesh as Mesh3,
|
2400
2650
|
MeshStandardMaterial as MeshStandardMaterial2,
|
2401
2651
|
Vector3 as Vector37
|
2402
2652
|
} from "three";
|
@@ -2451,13 +2701,13 @@ var CollisionsManager = class {
|
|
2451
2701
|
if (!this.debug) {
|
2452
2702
|
return { source: group, visualizer: null, meshBVH };
|
2453
2703
|
}
|
2454
|
-
const mergedMesh = new
|
2704
|
+
const mergedMesh = new Mesh3(
|
2455
2705
|
newBufferGeometry,
|
2456
|
-
new MeshStandardMaterial2({ color: 16711680, side:
|
2706
|
+
new MeshStandardMaterial2({ color: 16711680, side: FrontSide2, wireframe: true })
|
2457
2707
|
);
|
2458
2708
|
mergedMesh.geometry.boundsTree = meshBVH;
|
2459
2709
|
const visualizer = new MeshBVHVisualizer(mergedMesh, 3);
|
2460
|
-
visualizer.edgeMaterial.color = new
|
2710
|
+
visualizer.edgeMaterial.color = new Color6(255);
|
2461
2711
|
visualizer.update();
|
2462
2712
|
return { source: group, visualizer, meshBVH };
|
2463
2713
|
}
|