UNPKG

@babylonjs/gui

Version:

Babylon.js GUI module =====================

256 lines 9.93 kB
import { Observable } from "@babylonjs/core/Misc/observable.js"; import { Vector3 } from "@babylonjs/core/Maths/math.vector.js"; import { Control3D } from "./control3D.js"; import { CreateBox } from "@babylonjs/core/Meshes/Builders/boxBuilder.js"; import { PointerDragBehavior } from "@babylonjs/core/Behaviors/Meshes/pointerDragBehavior.js"; import { SceneLoader } from "@babylonjs/core/Loading/sceneLoader.js"; import { MRDLSliderBarMaterial } from "../materials/mrdl/mrdlSliderBarMaterial.js"; import { MRDLSliderThumbMaterial } from "../materials/mrdl/mrdlSliderThumbMaterial.js"; import { MRDLBackplateMaterial } from "../materials/mrdl/mrdlBackplateMaterial.js"; import { Tools } from "@babylonjs/core/Misc/tools.js"; const SLIDER_MIN = 0; const SLIDER_MAX = 100; const SLIDER_VAL = 50; const SLIDER_STEP = 0; const SLIDER_SCALING = 1.0; const SLIDER_MARGIN = 0.2; /** * Class used to create a slider in 3D */ export class Slider3D extends Control3D { /** * Creates a new slider * @param name defines the control name * @param sliderBackplateVisible defines if the control has a backplate, default is false */ constructor(name, sliderBackplateVisible) { super(name); /** Observable raised when the sldier value changes */ this.onValueChangedObservable = new Observable(); this._sliderBackplateVisible = sliderBackplateVisible || false; this._minimum = SLIDER_MIN; this._maximum = SLIDER_MAX; this._step = SLIDER_STEP; this._value = SLIDER_VAL; } /** * Gets the mesh used to render this control */ get mesh() { if (this.node) { return this._sliderThumb; } return null; } /** Gets or sets minimum value */ get minimum() { return this._minimum; } set minimum(value) { if (this._minimum === value) { return; } this._minimum = Math.max(value, SLIDER_MIN); this._value = Math.max(Math.min(this._value, this._maximum), this._minimum); } /** Gets or sets maximum value */ get maximum() { return this._maximum; } set maximum(value) { if (this._maximum === value) { return; } this._maximum = Math.max(value, this._minimum); this._value = Math.max(Math.min(this._value, this._maximum), this._minimum); } /** Gets or sets step value */ get step() { return this._step; } set step(value) { if (this._step === value) { return; } this._step = Math.max(Math.min(value, this._maximum - this._minimum), SLIDER_STEP); } /** Gets or sets current value */ get value() { return this._value; } set value(value) { if (this._value === value) { return; } this._value = Math.max(Math.min(value, this._maximum), this._minimum); if (this._sliderThumb) { this._sliderThumb.position.x = this._convertToPosition(this.value); } this.onValueChangedObservable.notifyObservers(this._value); } get start() { if (!this.node) { return -SLIDER_SCALING / 2; } return this._sliderBar.position.x - this._sliderBar.scaling.x / 2; } get end() { if (!this.node) { return SLIDER_SCALING / 2; } return this._sliderBar.position.x + this._sliderBar.scaling.x / 2; } /** * Gets the slider bar material used by this control */ get sliderBarMaterial() { return this._sliderBarMaterial; } /** * Gets the slider thumb material used by this control */ get sliderThumbMaterial() { return this._sliderThumbMaterial; } /** * Gets the slider backplate material used by this control */ get sliderBackplateMaterial() { return this._sliderBackplateMaterial; } /** * Gets the slider bar mesh used by this control */ get sliderBar() { return this._sliderBar; } /** * Gets the slider thumb mesh used by this control */ get sliderThumb() { return this._sliderThumb; } /** * Gets the slider backplate mesh used by this control */ get sliderBackplate() { return this._sliderBackplate; } /** Sets a boolean indicating if the control is visible */ set isVisible(value) { if (this._isVisible === value) { return; } this._isVisible = value; this.node?.setEnabled(value); } // Mesh association _createNode(scene) { const sliderBackplate = CreateBox(`${this.name}_sliderbackplate`, { width: 1.0, height: 1.0, depth: 1.0, }, scene); sliderBackplate.isPickable = false; sliderBackplate.visibility = 0; sliderBackplate.scaling = new Vector3(1, 0.5, 0.8); const baseUrl = Tools.GetAssetUrl(Slider3D.MODEL_BASE_URL); // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then SceneLoader.ImportMeshAsync(undefined, baseUrl, Slider3D.MODEL_FILENAME, scene).then((result) => { // make all meshes not pickable. Required meshes' pickable state will be set later. for (const m of result.meshes) { m.isPickable = false; } const sliderBackplateModel = result.meshes[1]; const sliderBarModel = result.meshes[1].clone(`${this.name}_sliderbar`, sliderBackplate); const sliderThumbModel = result.meshes[1].clone(`${this.name}_sliderthumb`, sliderBackplate); sliderBackplateModel.visibility = 0; if (this._sliderBackplateVisible) { sliderBackplateModel.visibility = 1; sliderBackplateModel.name = `${this.name}_sliderbackplate`; sliderBackplateModel.scaling.x = 1; sliderBackplateModel.scaling.z = 0.2; sliderBackplateModel.parent = sliderBackplate; if (this._sliderBackplateMaterial) { sliderBackplateModel.material = this._sliderBackplateMaterial; } this._sliderBackplate = sliderBackplateModel; } if (sliderBarModel) { sliderBarModel.parent = sliderBackplate; sliderBarModel.position.z = -0.1; sliderBarModel.scaling = new Vector3(SLIDER_SCALING - SLIDER_MARGIN, 0.04, 0.3); if (this._sliderBarMaterial) { sliderBarModel.material = this._sliderBarMaterial; } this._sliderBar = sliderBarModel; } if (sliderThumbModel) { sliderThumbModel.parent = sliderBackplate; sliderThumbModel.isPickable = true; sliderThumbModel.position.z = -0.115; sliderThumbModel.scaling = new Vector3(0.025, 0.3, 0.6); sliderThumbModel.position.x = this._convertToPosition(this.value); sliderThumbModel.addBehavior(this._createBehavior()); if (this._sliderThumbMaterial) { sliderThumbModel.material = this._sliderThumbMaterial; } this._sliderThumb = sliderThumbModel; } this._injectGUI3DReservedDataStore(sliderBackplate).control = this; const meshes = sliderBackplate.getChildMeshes(); for (const mesh of meshes) { this._injectGUI3DReservedDataStore(mesh).control = this; } }); this._affectMaterial(sliderBackplate); return sliderBackplate; } _affectMaterial(mesh) { this._sliderBackplateMaterial = this._sliderBackplateMaterial ?? new MRDLBackplateMaterial(`${this.name}_sliderbackplate_material`, mesh.getScene()); this._sliderBarMaterial = this._sliderBarMaterial ?? new MRDLSliderBarMaterial(`${this.name}_sliderbar_material`, mesh.getScene()); this._sliderThumbMaterial = this._sliderThumbMaterial ?? new MRDLSliderThumbMaterial(`${this.name}_sliderthumb_material`, mesh.getScene()); } _createBehavior() { const pointerDragBehavior = new PointerDragBehavior({ dragAxis: Vector3.Right() }); pointerDragBehavior.moveAttached = false; pointerDragBehavior.onDragStartObservable.add(() => { this._draggedPosition = this._sliderThumb.position.x; }); pointerDragBehavior.onDragObservable.add((event) => { this._draggedPosition += event.dragDistance / this.scaling.x; this.value = this._convertToValue(this._draggedPosition); }); return pointerDragBehavior; } _convertToPosition(value) { const position = ((value - this.minimum) / (this.maximum - this.minimum)) * (this.end - this.start) + this.start; return Math.min(Math.max(position, this.start), this.end); } _convertToValue(position) { let value = ((position - this.start) / (this.end - this.start)) * (this.maximum - this.minimum); value = this.step ? Math.round(value / this.step) * this.step : value; return Math.max(Math.min(this.minimum + value, this._maximum), this._minimum); } /** * Releases all associated resources */ dispose() { super.dispose(); this._sliderBar?.dispose(); this._sliderThumb?.dispose(); this._sliderBarMaterial?.dispose(); this._sliderThumbMaterial?.dispose(); this._sliderBackplate?.dispose(); this._sliderBackplateMaterial?.dispose(); } } /** * Base Url for the models. */ Slider3D.MODEL_BASE_URL = "https://assets.babylonjs.com/core/MRTK/"; /** * File name for the 8x4 model. */ Slider3D.MODEL_FILENAME = "mrtk-fluent-backplate.glb"; //# sourceMappingURL=slider3D.js.map