ui/scene: replace 2d labels
This commit is contained in:
@@ -27,6 +27,7 @@ export class MachineManager {
|
|||||||
machinesQueryResult: MachinesQueryResult,
|
machinesQueryResult: MachinesQueryResult,
|
||||||
selectedIds: Accessor<Set<string>>,
|
selectedIds: Accessor<Set<string>>,
|
||||||
setMachinePos: (id: string, position: [number, number] | null) => void,
|
setMachinePos: (id: string, position: [number, number] | null) => void,
|
||||||
|
camera: THREE.Camera,
|
||||||
) {
|
) {
|
||||||
this.machinePositionsSignal = machinePositionsSignal;
|
this.machinePositionsSignal = machinePositionsSignal;
|
||||||
|
|
||||||
@@ -82,6 +83,7 @@ export class MachineManager {
|
|||||||
id,
|
id,
|
||||||
selectedIds,
|
selectedIds,
|
||||||
highlightGroups,
|
highlightGroups,
|
||||||
|
camera,
|
||||||
);
|
);
|
||||||
this.machines.set(id, repr);
|
this.machines.set(id, repr);
|
||||||
scene.add(repr.group);
|
scene.add(repr.group);
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import { ObjectRegistry } from "./ObjectRegistry";
|
|||||||
import { CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer.js";
|
import { CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer.js";
|
||||||
import { Accessor, createEffect, createRoot, on } from "solid-js";
|
import { Accessor, createEffect, createRoot, on } from "solid-js";
|
||||||
import { renderLoop } from "./RenderLoop";
|
import { renderLoop } from "./RenderLoop";
|
||||||
|
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js";
|
||||||
|
import { FontLoader, FontData } from "three/examples/jsm/Addons";
|
||||||
|
import font from "../../.fonts/CommitMono_Regular.json";
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const BASE_SIZE = 0.9;
|
const BASE_SIZE = 0.9;
|
||||||
@@ -28,6 +31,7 @@ export class MachineRepr {
|
|||||||
private baseMesh: THREE.Mesh;
|
private baseMesh: THREE.Mesh;
|
||||||
private geometry: THREE.BoxGeometry;
|
private geometry: THREE.BoxGeometry;
|
||||||
private material: THREE.MeshPhongMaterial;
|
private material: THREE.MeshPhongMaterial;
|
||||||
|
private camera: THREE.Camera;
|
||||||
|
|
||||||
private disposeRoot: () => void;
|
private disposeRoot: () => void;
|
||||||
|
|
||||||
@@ -38,8 +42,10 @@ export class MachineRepr {
|
|||||||
id: string,
|
id: string,
|
||||||
selectedSignal: Accessor<Set<string>>,
|
selectedSignal: Accessor<Set<string>>,
|
||||||
highlightGroups: Record<string, Set<string>>, // Reactive store
|
highlightGroups: Record<string, Set<string>>, // Reactive store
|
||||||
|
camera: THREE.Camera,
|
||||||
) {
|
) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.camera = camera;
|
||||||
this.geometry = new THREE.BoxGeometry(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE);
|
this.geometry = new THREE.BoxGeometry(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE);
|
||||||
this.material = new THREE.MeshPhongMaterial({
|
this.material = new THREE.MeshPhongMaterial({
|
||||||
color: CUBE_COLOR,
|
color: CUBE_COLOR,
|
||||||
@@ -62,7 +68,7 @@ export class MachineRepr {
|
|||||||
this.baseMesh.name = "base";
|
this.baseMesh.name = "base";
|
||||||
|
|
||||||
const label = this.createLabel(id);
|
const label = this.createLabel(id);
|
||||||
this.cubeMesh.add(label);
|
// this.cubeMesh.add(label);
|
||||||
|
|
||||||
const shadowPlaneMaterial = new THREE.MeshStandardMaterial({
|
const shadowPlaneMaterial = new THREE.MeshStandardMaterial({
|
||||||
color: BASE_COLOR, // any color you like
|
color: BASE_COLOR, // any color you like
|
||||||
@@ -82,6 +88,7 @@ export class MachineRepr {
|
|||||||
shadowPlane.position.set(0, BASE_HEIGHT + 0.0001, 0);
|
shadowPlane.position.set(0, BASE_HEIGHT + 0.0001, 0);
|
||||||
|
|
||||||
this.group = new THREE.Group();
|
this.group = new THREE.Group();
|
||||||
|
this.group.add(label);
|
||||||
this.group.add(this.cubeMesh);
|
this.group.add(this.cubeMesh);
|
||||||
this.group.add(this.baseMesh);
|
this.group.add(this.baseMesh);
|
||||||
this.group.add(shadowPlane);
|
this.group.add(shadowPlane);
|
||||||
@@ -161,12 +168,40 @@ export class MachineRepr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private createLabel(id: string) {
|
private createLabel(id: string) {
|
||||||
const div = document.createElement("div");
|
// const div = document.createElement("div");
|
||||||
div.className = "machine-label";
|
// div.className = "machine-label";
|
||||||
div.textContent = id;
|
// div.textContent = id;
|
||||||
const label = new CSS2DObject(div);
|
// const label = new CSS2DObject(div);
|
||||||
label.position.set(0, CUBE_SIZE + 0.1, 0);
|
// label.position.set(0, CUBE_SIZE + 0.1, 0);
|
||||||
return label;
|
// return label;
|
||||||
|
const loader = new FontLoader();
|
||||||
|
const final = loader.parse(font as unknown as FontData);
|
||||||
|
|
||||||
|
const geometry = new TextGeometry(id, {
|
||||||
|
font: final,
|
||||||
|
size: 0.1,
|
||||||
|
depth: 0.01,
|
||||||
|
curveSegments: 12,
|
||||||
|
bevelEnabled: false,
|
||||||
|
bevelThickness: 0.01,
|
||||||
|
bevelSize: 0.01,
|
||||||
|
bevelOffset: 0,
|
||||||
|
bevelSegments: 5,
|
||||||
|
});
|
||||||
|
|
||||||
|
const textMaterial = new THREE.MeshPhongMaterial({ color: 0x000000 });
|
||||||
|
const textMesh = new THREE.Mesh(geometry, textMaterial);
|
||||||
|
|
||||||
|
geometry.computeBoundingBox();
|
||||||
|
if (geometry.boundingBox) {
|
||||||
|
const xMid =
|
||||||
|
-0.5 * (geometry.boundingBox.max.x - geometry.boundingBox.min.x);
|
||||||
|
geometry.translate(xMid, 0, 0); // shift so it's centered on X
|
||||||
|
}
|
||||||
|
textMesh.position.set(0, CUBE_SIZE + 0.15, 0); // above the cube
|
||||||
|
textMesh.quaternion.copy(this.camera.quaternion);
|
||||||
|
textMesh.userData.isLabel = true;
|
||||||
|
return textMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(scene: THREE.Scene) {
|
dispose(scene: THREE.Scene) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Scene, Camera, WebGLRenderer } from "three";
|
import { Scene, Camera, WebGLRenderer } from "three";
|
||||||
import { MapControls } from "three/examples/jsm/controls/MapControls.js";
|
import { MapControls } from "three/examples/jsm/controls/MapControls.js";
|
||||||
import { CSS2DRenderer } from "three/examples/jsm/renderers/CSS2DRenderer.js";
|
import { CSS2DRenderer } from "three/examples/jsm/renderers/CSS2DRenderer.js";
|
||||||
|
import * as THREE from "three";
|
||||||
/**
|
/**
|
||||||
* Private class to manage the render loop
|
* Private class to manage the render loop
|
||||||
* @internal
|
* @internal
|
||||||
@@ -93,6 +93,13 @@ class RenderLoop {
|
|||||||
|
|
||||||
this.renderer.render(this.bgScene, this.bgCamera);
|
this.renderer.render(this.bgScene, this.bgCamera);
|
||||||
this.renderer.render(this.scene, this.camera);
|
this.renderer.render(this.scene, this.camera);
|
||||||
|
|
||||||
|
this.scene.traverse((obj) => {
|
||||||
|
if (obj.userData.isLabel) {
|
||||||
|
(obj as THREE.Mesh).quaternion.copy(this.camera.quaternion);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.labelRenderer.render(this.scene, this.camera);
|
this.labelRenderer.render(this.scene, this.camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -433,6 +433,7 @@ export function CubeScene(props: {
|
|||||||
props.cubesQuery,
|
props.cubesQuery,
|
||||||
props.selectedIds,
|
props.selectedIds,
|
||||||
props.setMachinePos,
|
props.setMachinePos,
|
||||||
|
camera,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Click handler:
|
// Click handler:
|
||||||
|
|||||||
Reference in New Issue
Block a user