Simplified interactions, changed menu interactions for changing entities.
This commit is contained in:
parent
727977d5c6
commit
cabc38ce09
@ -21,6 +21,7 @@ import {snapRotateVal} from "../util/functions/snapRotateVal";
|
|||||||
import {grabAndClone} from "./functions/grab";
|
import {grabAndClone} from "./functions/grab";
|
||||||
import {isDiagramEntity} from "../diagram/functions/isDiagramEntity";
|
import {isDiagramEntity} from "../diagram/functions/isDiagramEntity";
|
||||||
import {ClickMenu} from "../menus/clickMenu";
|
import {ClickMenu} from "../menus/clickMenu";
|
||||||
|
import {displayDebug} from "../util/displayDebug";
|
||||||
|
|
||||||
const CLICK_TIME = 300;
|
const CLICK_TIME = 300;
|
||||||
export class Base {
|
export class Base {
|
||||||
@ -144,11 +145,12 @@ export class Base {
|
|||||||
|
|
||||||
private grab(cloneEntity: boolean = false) {
|
private grab(cloneEntity: boolean = false) {
|
||||||
let mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);
|
let mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);
|
||||||
|
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let player = false;
|
let player = false;
|
||||||
|
displayDebug(mesh);
|
||||||
if (!isDiagramEntity(mesh)) {
|
if (!isDiagramEntity(mesh)) {
|
||||||
if (this.handleWasGrabbed(mesh)) {
|
if (this.handleWasGrabbed(mesh)) {
|
||||||
mesh && mesh.setParent(this.controller.motionController.rootMesh);
|
mesh && mesh.setParent(this.controller.motionController.rootMesh);
|
||||||
@ -215,7 +217,12 @@ export class Base {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.handleWasGrabbed(mesh)) {
|
if (this.handleWasGrabbed(mesh)) {
|
||||||
mesh.setParent(this.scene.getMeshByName("platform"))
|
mesh.setParent(this.scene.getMeshByName("platform"));
|
||||||
|
const location = {
|
||||||
|
position: {x: mesh.position.x, y: mesh.position.y, z: mesh.position.z},
|
||||||
|
rotation: {x: mesh.rotation.x, y: mesh.rotation.y, z: mesh.rotation.z}
|
||||||
|
}
|
||||||
|
localStorage.setItem(mesh.id, JSON.stringify(location));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
reparent(mesh, this.previousParentId, this.grabbedMeshParentId);
|
reparent(mesh, this.previousParentId, this.grabbedMeshParentId);
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import {toDiagramEntity} from "./functions/toDiagramEntity";
|
|||||||
import {v4 as uuidv4} from 'uuid';
|
import {v4 as uuidv4} from 'uuid';
|
||||||
import {buildEntityActionManager} from "./functions/buildEntityActionManager";
|
import {buildEntityActionManager} from "./functions/buildEntityActionManager";
|
||||||
import {isDiagramEntity} from "./functions/isDiagramEntity";
|
import {isDiagramEntity} from "./functions/isDiagramEntity";
|
||||||
|
import {InputTextView} from "../information/inputTextView";
|
||||||
|
|
||||||
|
|
||||||
export class DiagramManager {
|
export class DiagramManager {
|
||||||
@ -21,6 +22,7 @@ export class DiagramManager {
|
|||||||
private readonly _controllers: Controllers;
|
private readonly _controllers: Controllers;
|
||||||
private readonly diagramEntityActionManager: ActionManager;
|
private readonly diagramEntityActionManager: ActionManager;
|
||||||
private presentationManager: PresentationManager;
|
private presentationManager: PresentationManager;
|
||||||
|
private readonly inputTextView: InputTextView;
|
||||||
|
|
||||||
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
|
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
|
||||||
private readonly logger = log.getLogger('DiagramManager');
|
private readonly logger = log.getLogger('DiagramManager');
|
||||||
@ -31,6 +33,21 @@ export class DiagramManager {
|
|||||||
constructor(scene: Scene) {
|
constructor(scene: Scene) {
|
||||||
this._config = new AppConfig();
|
this._config = new AppConfig();
|
||||||
this._controllers = new Controllers();
|
this._controllers = new Controllers();
|
||||||
|
this.inputTextView = new InputTextView(scene, this._controllers);
|
||||||
|
this.inputTextView.onTextObservable.add((evt) => {
|
||||||
|
const mesh = scene.getMeshById(evt.id);
|
||||||
|
if (mesh) {
|
||||||
|
const entity = toDiagramEntity(mesh);
|
||||||
|
entity.text = evt.text;
|
||||||
|
this.onDiagramEventObservable.notifyObservers({
|
||||||
|
type: DiagramEventType.MODIFY,
|
||||||
|
entity: entity
|
||||||
|
}, -1);
|
||||||
|
} else {
|
||||||
|
this.logger.error("mesh not found", evt.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.sounds = new DiaSounds(scene);
|
this.sounds = new DiaSounds(scene);
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.toolbox = new Toolbox(scene);
|
this.toolbox = new Toolbox(scene);
|
||||||
@ -67,6 +84,10 @@ export class DiagramManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public editText(mesh: AbstractMesh) {
|
||||||
|
this.inputTextView.show(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
public get controllers(): Controllers {
|
public get controllers(): Controllers {
|
||||||
return this._controllers;
|
return this._controllers;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,63 +1,84 @@
|
|||||||
import {MeshBuilder, Observable, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
|
import {AbstractMesh, MeshBuilder, Observable, Scene, Vector3} from "@babylonjs/core";
|
||||||
import log, {Logger} from "loglevel";
|
import log, {Logger} from "loglevel";
|
||||||
import {AdvancedDynamicTexture, Control, InputText, VirtualKeyboard} from "@babylonjs/gui";
|
import {AdvancedDynamicTexture, Control, InputText, VirtualKeyboard} from "@babylonjs/gui";
|
||||||
import {ControllerEventType, Controllers} from "../controllers/controllers";
|
import {ControllerEventType, Controllers} from "../controllers/controllers";
|
||||||
import {setMenuPosition} from "../util/functions/setMenuPosition";
|
|
||||||
import {DiaSounds} from "../util/diaSounds";
|
import {DiaSounds} from "../util/diaSounds";
|
||||||
import {Handle} from "../objects/handle";
|
import {Handle} from "../objects/handle";
|
||||||
|
|
||||||
export type TextEvent = {
|
export type TextEvent = {
|
||||||
|
id: string;
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InputTextView {
|
export class InputTextView {
|
||||||
public readonly onTextObservable: Observable<TextEvent> = new Observable<TextEvent>();
|
public readonly onTextObservable: Observable<TextEvent> = new Observable<TextEvent>();
|
||||||
private readonly text: string = "";
|
|
||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
|
private readonly inputMesh: AbstractMesh;
|
||||||
private sounds: DiaSounds;
|
private sounds: DiaSounds;
|
||||||
private readonly controllers: Controllers;
|
private readonly controllers: Controllers;
|
||||||
private readonly xr: WebXRDefaultExperience;
|
|
||||||
private readonly logger: Logger = log.getLogger('InputTextView');
|
private readonly logger: Logger = log.getLogger('InputTextView');
|
||||||
|
private readonly handle: Handle;
|
||||||
|
private inputText: InputText;
|
||||||
|
private diagramMesh: AbstractMesh;
|
||||||
|
|
||||||
constructor(text: string, xr: WebXRDefaultExperience, scene: Scene, controllers: Controllers) {
|
constructor(scene: Scene, controllers: Controllers) {
|
||||||
this.text = text ? text : "";
|
|
||||||
this.xr = xr;
|
|
||||||
this.controllers = controllers;
|
this.controllers = controllers;
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.sounds = new DiaSounds(scene);
|
this.sounds = new DiaSounds(scene);
|
||||||
|
this.inputMesh = MeshBuilder.CreatePlane("input", {width: 1, height: .5}, this.scene);
|
||||||
|
this.handle = new Handle(this.inputMesh);
|
||||||
|
this.createKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
public show() {
|
public show(mesh: AbstractMesh) {
|
||||||
this.showVirtualKeyboard();
|
this.inputText.text = mesh.metadata?.label || "";
|
||||||
/*if ((this.xr as WebXRDefaultExperience).baseExperience?.sessionManager?.inXRSession) {
|
this.handle.mesh.setEnabled(true);
|
||||||
this.showXr();
|
this.diagramMesh = mesh;
|
||||||
|
console.log(mesh.metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createKeyboard() {
|
||||||
|
const platform = this.scene.getMeshById('platform');
|
||||||
|
let position = new Vector3(0, 1.66, .5);
|
||||||
|
let rotation = new Vector3(0, .9, 0);
|
||||||
|
const handle = this.handle;
|
||||||
|
if (handle.mesh.position.x != 0 && handle.mesh.position.y != 0 && handle.mesh.position.z != 0) {
|
||||||
|
position = handle.mesh.position;
|
||||||
|
}
|
||||||
|
if (handle.mesh.rotation.x != 0 && handle.mesh.rotation.y != 0 && handle.mesh.rotation.z != 0) {
|
||||||
|
rotation = handle.mesh.rotation;
|
||||||
|
}
|
||||||
|
if (!platform) {
|
||||||
|
this.scene.onNewMeshAddedObservable.add((mesh) => {
|
||||||
|
if (mesh.id == 'platform') {
|
||||||
|
this.logger.debug("platform added");
|
||||||
|
handle.mesh.setParent(platform);
|
||||||
|
|
||||||
|
handle.mesh.position = position;
|
||||||
|
handle.mesh.rotation = rotation;
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.showWeb();
|
handle.mesh.parent = platform;
|
||||||
}*/
|
handle.mesh.position = position;
|
||||||
}
|
handle.mesh.rotation = rotation;
|
||||||
|
}
|
||||||
public showVirtualKeyboard() {
|
|
||||||
const inputMesh = MeshBuilder.CreatePlane("input", {width: 1, height: .5}, this.scene);
|
|
||||||
const handle = new Handle(inputMesh);
|
|
||||||
setMenuPosition(handle.mesh, this.scene, new Vector3(0, .4, 0));
|
|
||||||
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(inputMesh, 2048, 1024, false);
|
|
||||||
|
|
||||||
|
//setMenuPosition(handle.mesh, this.scene, new Vector3(0, .4, 0));
|
||||||
|
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(this.inputMesh, 2048, 1024, false);
|
||||||
const input = new InputText();
|
const input = new InputText();
|
||||||
|
|
||||||
input.width = 0.5;
|
input.width = 0.5;
|
||||||
input.maxWidth = 0.5;
|
input.maxWidth = 0.5;
|
||||||
input.height = "64px";
|
input.height = "64px";
|
||||||
input.text = this.text;
|
input.text = "";
|
||||||
|
|
||||||
input.fontSize = "32px";
|
input.fontSize = "32px";
|
||||||
input.color = "white";
|
input.color = "white";
|
||||||
input.background = "black";
|
input.background = "black";
|
||||||
input.thickness = 3;
|
input.thickness = 3;
|
||||||
input.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
|
input.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
|
||||||
advancedTexture.addControl(input);
|
this.inputText = input;
|
||||||
|
advancedTexture.addControl(this.inputText);
|
||||||
const keyboard = VirtualKeyboard.CreateDefaultLayout();
|
const keyboard = VirtualKeyboard.CreateDefaultLayout();
|
||||||
|
|
||||||
keyboard.scaleY = 2;
|
keyboard.scaleY = 2;
|
||||||
keyboard.scaleX = 2;
|
keyboard.scaleX = 2;
|
||||||
keyboard.transformCenterY = 0;
|
keyboard.transformCenterY = 0;
|
||||||
@ -84,77 +105,21 @@ export class InputTextView {
|
|||||||
}, -1, false, this, false);
|
}, -1, false, this, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
keyboard.onPointerDownObservable.add(() => {
|
keyboard.onPointerDownObservable.add(() => {
|
||||||
this.sounds.tick.play();
|
this.sounds.tick.play();
|
||||||
});
|
});
|
||||||
keyboard.onKeyPressObservable.add((key) => {
|
keyboard.onKeyPressObservable.add((key) => {
|
||||||
if (key === '↵') {
|
if (key === '↵') {
|
||||||
this.onTextObservable.notifyObservers({text: input.text});
|
this.logger.error(this.inputText.text);
|
||||||
input.dispose();
|
this.onTextObservable.notifyObservers({id: this.diagramMesh.id, text: this.inputText.text});
|
||||||
keyboard.dispose();
|
this.hide();
|
||||||
advancedTexture.dispose();
|
|
||||||
inputMesh.dispose();
|
|
||||||
this.sounds.exit.play();
|
|
||||||
}
|
}
|
||||||
});
|
}, -1, false, this, false);
|
||||||
|
this.handle.mesh.setEnabled(false);
|
||||||
|
|
||||||
this.sounds.enter.play();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public showWeb() {
|
private hide() {
|
||||||
const textInput = new InputText('identity', this.text);
|
this.handle.mesh.setEnabled(false);
|
||||||
textInput.width = 0.2;
|
this.diagramMesh = null;
|
||||||
textInput.height = "40px";
|
|
||||||
textInput.color = "white";
|
|
||||||
textInput.background = "black";
|
|
||||||
textInput.focusedBackground = "black";
|
|
||||||
|
|
||||||
const advancedTexture = AdvancedDynamicTexture.CreateFullscreenUI("myUI");
|
|
||||||
advancedTexture.addControl(textInput);
|
|
||||||
textInput.onKeyboardEventProcessedObservable.add((evt) => {
|
|
||||||
if (evt.key === 'Enter') {
|
|
||||||
this.onTextObservable.notifyObservers({text: textInput.text});
|
|
||||||
textInput.dispose();
|
|
||||||
advancedTexture.dispose();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private showXr() {
|
|
||||||
const textInput = document.createElement("input");
|
|
||||||
textInput.type = "text";
|
|
||||||
document.body.appendChild(textInput);
|
|
||||||
textInput.value = this.text;
|
|
||||||
this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.HIDE});
|
|
||||||
|
|
||||||
/*if (this.xr?.baseExperience?.sessionManager?.inXRSession) {
|
|
||||||
this.xr.input.controllers.forEach((controller) => {
|
|
||||||
controller.motionController.rootMesh.setEnabled(false);
|
|
||||||
controller.pointer.setEnabled(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
textInput.addEventListener('blur', () => {
|
|
||||||
log.getLogger('bmenu').debug("blur");
|
|
||||||
this.onTextObservable.notifyObservers({text: textInput.value});
|
|
||||||
this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.SHOW});
|
|
||||||
|
|
||||||
/*if (this.xr?.baseExperience?.sessionManager?.inXRSession) {
|
|
||||||
this.xr.input.controllers.forEach((controller) => {
|
|
||||||
controller.motionController.rootMesh.setEnabled(true);
|
|
||||||
controller.pointer.setEnabled(true);
|
|
||||||
});
|
|
||||||
}*/
|
|
||||||
textInput.blur();
|
|
||||||
textInput.remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
textInput.focus();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,6 +63,9 @@ export class ClickMenu {
|
|||||||
this.dispose();
|
this.dispose();
|
||||||
break;
|
break;
|
||||||
case "label":
|
case "label":
|
||||||
|
this.diagramManager.editText(this.entity);
|
||||||
|
this.dispose();
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,13 +13,23 @@ export class Handle {
|
|||||||
private buildHandle() {
|
private buildHandle() {
|
||||||
const scene: Scene = this.transformNode.getScene();
|
const scene: Scene = this.transformNode.getScene();
|
||||||
const handle = getHandleMesh("handle-" + this.transformNode.id + "-mesh", scene);
|
const handle = getHandleMesh("handle-" + this.transformNode.id + "-mesh", scene);
|
||||||
|
|
||||||
handle.position = Vector3.Zero();
|
|
||||||
handle.metadata = {handle: true};
|
|
||||||
if (this.transformNode) {
|
if (this.transformNode) {
|
||||||
this.transformNode.setParent(handle);
|
this.transformNode.setParent(handle);
|
||||||
//this.transformNode.rotation.y = Math.PI;
|
|
||||||
}
|
}
|
||||||
|
const stored = localStorage.getItem(handle.id);
|
||||||
|
if (stored) {
|
||||||
|
try {
|
||||||
|
const locationdata = JSON.parse(stored);
|
||||||
|
handle.position = new Vector3(locationdata.position.x, locationdata.position.y, locationdata.position.z);
|
||||||
|
handle.rotation = new Vector3(locationdata.rotation.x, locationdata.rotation.y, locationdata.rotation.z);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
handle.position = Vector3.Zero();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handle.position = Vector3.Zero();
|
||||||
|
}
|
||||||
|
handle.metadata = {handle: true};
|
||||||
this.mesh = handle;
|
this.mesh = handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,6 +50,6 @@ function getHandleMesh(name: string, scene: Scene): InstancedMesh {
|
|||||||
handle.material = buildStandardMaterial('base-handle-material', scene, "#CCCCDD");
|
handle.material = buildStandardMaterial('base-handle-material', scene, "#CCCCDD");
|
||||||
handle.id = "base-handle-mesh";
|
handle.id = "base-handle-mesh";
|
||||||
const instance = new InstancedMesh(name, (handle as Mesh));
|
const instance = new InstancedMesh(name, (handle as Mesh));
|
||||||
instance.setParent(scene.getMeshByName("platform"));
|
instance.setParent(scene.getMeshById("platform"));
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -11,6 +11,7 @@ const colors: string[] = [
|
|||||||
"#1e90ff", "#98fb98", "#ffe4b5", "#ff69b4"
|
"#1e90ff", "#98fb98", "#ffe4b5", "#ff69b4"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
export class Toolbox {
|
export class Toolbox {
|
||||||
private readonly logger = log.getLogger('Toolbox');
|
private readonly logger = log.getLogger('Toolbox');
|
||||||
private index = 0;
|
private index = 0;
|
||||||
@ -18,6 +19,7 @@ export class Toolbox {
|
|||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
private colorPicker: TransformNode;
|
private colorPicker: TransformNode;
|
||||||
private changing = false;
|
private changing = false;
|
||||||
|
private readonly handle: Handle;
|
||||||
private readonly manager: GUI3DManager;
|
private readonly manager: GUI3DManager;
|
||||||
private readonly addPanel: StackPanel3D;
|
private readonly addPanel: StackPanel3D;
|
||||||
public readonly colorChangeObservable: Observable<{ oldColor: string, newColor: string }> =
|
public readonly colorChangeObservable: Observable<{ oldColor: string, newColor: string }> =
|
||||||
@ -30,7 +32,7 @@ export class Toolbox {
|
|||||||
this.manager = new GUI3DManager(scene);
|
this.manager = new GUI3DManager(scene);
|
||||||
this.manager.addControl(this.addPanel);
|
this.manager.addControl(this.addPanel);
|
||||||
this.toolboxBaseNode = new TransformNode("toolbox", this.scene);
|
this.toolboxBaseNode = new TransformNode("toolbox", this.scene);
|
||||||
new Handle(this.toolboxBaseNode);
|
this.handle = new Handle(this.toolboxBaseNode);
|
||||||
this.toolboxBaseNode.position.y = .2;
|
this.toolboxBaseNode.position.y = .2;
|
||||||
//this.toolboxBaseNode.position.z = .05;
|
//this.toolboxBaseNode.position.z = .05;
|
||||||
/*this.axes = new AxesViewer(this.scene);
|
/*this.axes = new AxesViewer(this.scene);
|
||||||
@ -91,19 +93,36 @@ export class Toolbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//this.toolboxBaseNode.parent.setEnabled(false);
|
//this.toolboxBaseNode.parent.setEnabled(false);
|
||||||
const offset = new Vector3(0, 1, 1);
|
let offset = new Vector3(-.50, 1.6, .38);
|
||||||
|
let rotation = new Vector3(.5, -.6, .18);
|
||||||
|
|
||||||
if (this.toolboxBaseNode.parent) {
|
if (this.toolboxBaseNode.parent) {
|
||||||
const platform = this.scene.getNodeById("platform");
|
const platform = this.scene.getNodeById("platform");
|
||||||
|
|
||||||
if (platform) {
|
if (platform) {
|
||||||
const handle = (this.toolboxBaseNode.parent as TransformNode);
|
const handle = this.handle;
|
||||||
handle.parent = platform;
|
if (handle.mesh.position.x != 0 && handle.mesh.position.y != 0 && handle.mesh.position.z != 0) {
|
||||||
handle.position = offset;
|
offset = handle.mesh.position;
|
||||||
|
}
|
||||||
|
if (handle.mesh.rotation.x != 0 && handle.mesh.rotation.y != 0 && handle.mesh.rotation.z != 0) {
|
||||||
|
rotation = handle.mesh.rotation;
|
||||||
|
}
|
||||||
|
handle.mesh.parent = platform;
|
||||||
|
handle.mesh.position = offset;
|
||||||
|
handle.mesh.rotation = rotation;
|
||||||
} else {
|
} else {
|
||||||
this.scene.onNewMeshAddedObservable.add((mesh: AbstractMesh) => {
|
this.scene.onNewMeshAddedObservable.add((mesh: AbstractMesh) => {
|
||||||
if (mesh.id == "platform") {
|
if (mesh.id == "platform") {
|
||||||
const handle = (this.toolboxBaseNode.parent as TransformNode);
|
const handle = this.handle;
|
||||||
handle.parent = mesh;
|
if (handle.mesh.position.x != 0 && handle.mesh.position.y != 0 && handle.mesh.position.z != 0) {
|
||||||
handle.position = offset;
|
offset = handle.mesh.position;
|
||||||
|
}
|
||||||
|
if (handle.mesh.rotation.x != 0 && handle.mesh.rotation.y != 0 && handle.mesh.rotation.z != 0) {
|
||||||
|
rotation = handle.mesh.rotation;
|
||||||
|
}
|
||||||
|
handle.mesh.parent = mesh;
|
||||||
|
handle.mesh.position = offset;
|
||||||
|
handle.mesh.rotation = rotation;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
77
src/util/displayDebug.ts
Normal file
77
src/util/displayDebug.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import {
|
||||||
|
AbstractMesh,
|
||||||
|
DynamicTexture,
|
||||||
|
Material,
|
||||||
|
MeshBuilder,
|
||||||
|
StandardMaterial,
|
||||||
|
TransformNode,
|
||||||
|
Vector3
|
||||||
|
} from "@babylonjs/core";
|
||||||
|
|
||||||
|
const debug = false;
|
||||||
|
|
||||||
|
export function displayDebug(transform: TransformNode) {
|
||||||
|
if (debug) {
|
||||||
|
const position = `position: (${transform.position.x.toFixed(2)}, ${transform.position.y.toFixed(2)}, ${transform.position.z.toFixed(2)})`;
|
||||||
|
const rotation = `rotation: (${transform.rotation.x.toFixed(2)}, ${transform.rotation.y.toFixed(2)}, ${transform.rotation.z.toFixed(2)})`;
|
||||||
|
buildText(position, transform, new Vector3(0, 1.5, 1));
|
||||||
|
buildText(rotation, transform, new Vector3(0, 1.4, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildText(text: string, transform: TransformNode, position) {
|
||||||
|
const height = 0.05;
|
||||||
|
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, transform.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;
|
||||||
|
|
||||||
|
//Create dynamic texture and write the text
|
||||||
|
const dynamicTexture = new DynamicTexture("DynamicTexture", {
|
||||||
|
width: DTWidth,
|
||||||
|
height: DTHeight
|
||||||
|
}, transform.getScene(), false);
|
||||||
|
const mat = new StandardMaterial("mat", transform.getScene());
|
||||||
|
mat.diffuseTexture = dynamicTexture;
|
||||||
|
//mat.emissiveColor = Color3.White();
|
||||||
|
dynamicTexture.drawText(text, null, null, font, "#000000", "#ffffff", true);
|
||||||
|
//Create plane and set dynamic texture as material
|
||||||
|
//const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
|
||||||
|
const plane1 = createPlane(mat, transform, text, planeWidth, height, position);
|
||||||
|
const plane2 = createPlane(mat, transform, text, planeWidth, height, position);
|
||||||
|
plane2.rotation.y = Math.PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPlane(mat: Material, transform: TransformNode, text: string, planeWidth: number, height: number, position): AbstractMesh {
|
||||||
|
const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, transform.getScene());
|
||||||
|
|
||||||
|
plane.material = mat;
|
||||||
|
//plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
||||||
|
plane.metadata = {exportable: false, label: false};
|
||||||
|
|
||||||
|
//const yOffset = mesh.getBoundingInfo().boundingSphere.maximum.y;
|
||||||
|
//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.position = transform.position.y = yOffset + (height * plane.scaling.y);
|
||||||
|
plane.position = position;
|
||||||
|
window.setTimeout(() => {
|
||||||
|
plane.dispose();
|
||||||
|
}, 5000);
|
||||||
|
return plane;
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user