- Remove unused createGrassGround function from customEnvironment - Remove commented HemisphericLight code - Fix deviceDetection to use proper VR detection instead of hardcoded true - Clean up whitespace in spinner.ts and animatedLineTexture.ts - Pass empty object to refreshBoundingInfo to match API signature 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
102 lines
3.6 KiB
TypeScript
102 lines
3.6 KiB
TypeScript
import {AbstractMesh, Color3, DynamicTexture, Material, MeshBuilder, StandardMaterial, TransformNode} from "@babylonjs/core";
|
|
import log from "loglevel";
|
|
|
|
|
|
const textLogger: log.Logger = log.getLogger('TextLabel');
|
|
|
|
export function updateTextNode(mesh: AbstractMesh, text: string) {
|
|
if (!mesh) {
|
|
textLogger.error("updateTextNode: mesh is null");
|
|
return null;
|
|
}
|
|
const textNodes = mesh.getChildren((node) => {
|
|
return node.metadata?.label == true;
|
|
});
|
|
if (textNodes && textNodes.length > 0) {
|
|
textNodes.forEach((node) => {
|
|
node.parent = null;
|
|
node.dispose(false, true);
|
|
});
|
|
}
|
|
|
|
if (!text) {
|
|
return null;
|
|
}
|
|
|
|
//Set font
|
|
const height = 0.08;
|
|
const font_size = 24;
|
|
const font = "bold " + font_size + "px Arial";
|
|
//Set height for dynamic texture
|
|
const DTHeight = 1.5 * font_size; //or set as wished
|
|
//Calc Ratio
|
|
const ratio = height / DTHeight;
|
|
|
|
//Use a temporary dynamic texture to calculate the length of the text on the dynamic texture canvas
|
|
const temp = new DynamicTexture("DynamicTexture", 32, mesh.getScene());
|
|
const tmpctx = temp.getContext();
|
|
tmpctx.font = font;
|
|
const DTWidth = tmpctx.measureText(text).width + 8;
|
|
|
|
//Calculate width the plane has to be
|
|
const planeWidth = DTWidth * ratio;
|
|
temp.dispose();
|
|
//Create dynamic texture and write the text
|
|
const dynamicTexture = new DynamicTexture("DynamicTexture", {
|
|
width: DTWidth,
|
|
height: DTHeight
|
|
}, mesh.getScene(), false);
|
|
dynamicTexture.drawText(text, null, null, font, "#ffffff", "#000000", true);
|
|
|
|
const mat = new StandardMaterial("mat", mesh.getScene());
|
|
mat.metadata = { isUI: true }; // Mark as UI to prevent rendering mode modifications
|
|
mat.diffuseColor = Color3.Black();
|
|
mat.disableLighting = true;
|
|
mat.backFaceCulling = false;
|
|
mat.emissiveTexture = dynamicTexture;
|
|
mat.freeze();
|
|
|
|
const plane1 = createPlane(mat, mesh, text, planeWidth, height);
|
|
//const plane2 = createPlane(mat, mesh, text, planeWidth, height);
|
|
//plane2.rotation.y = Math.PI;
|
|
}
|
|
|
|
function createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth: number, height: number): AbstractMesh {
|
|
const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
|
|
|
|
plane.parent = mesh;
|
|
plane.scaling.y = (1 / mesh.scaling.y);
|
|
plane.scaling.x = (1 / mesh.scaling.x);
|
|
plane.scaling.z = (1 / mesh.scaling.z);
|
|
plane.material = mat;
|
|
plane.metadata = {exportable: true, label: true};
|
|
|
|
if (mesh.metadata?.template == "#connection-template") {
|
|
plane.billboardMode = AbstractMesh.BILLBOARDMODE_Y;
|
|
plane.position.y = mesh.position.y + .1;
|
|
} else {
|
|
// Calculate label position using world space bounding box
|
|
// This ensures labels are positioned correctly regardless of mesh transforms
|
|
mesh.computeWorldMatrix(true);
|
|
mesh.refreshBoundingInfo({});
|
|
|
|
// Get the top of the bounding box in world space
|
|
const top = mesh.getBoundingInfo().boundingBox.maximumWorld;
|
|
|
|
// Convert world space position to mesh's local space
|
|
// Use temporary TransformNode to handle the transformation
|
|
const temp = new TransformNode("temp", mesh.getScene());
|
|
temp.position = top;
|
|
temp.setParent(mesh);
|
|
const y = temp.position.y;
|
|
temp.dispose();
|
|
|
|
// Position label above the mesh with offset
|
|
// Add additional offset for the scaled height of the label
|
|
plane.position.y = y + 0.06 + (height * plane.scaling.y / 2);
|
|
}
|
|
plane.addLODLevel(3, null);
|
|
return plane;
|
|
}
|
|
|