@babylonjs/gui
Version:
Babylon.js GUI module =====================
536 lines • 21.6 kB
JavaScript
import { __decorate } from "@babylonjs/core/tslib.es6.js";
import { serializeAsColor4, serializeAsVector3, serialize } from "@babylonjs/core/Misc/decorators.js";
import { SerializationHelper } from "@babylonjs/core/Misc/decorators.serialization.js";
import { Vector3, Vector4 } from "@babylonjs/core/Maths/math.vector.js";
import { Texture } from "@babylonjs/core/Materials/Textures/texture.js";
import { MaterialDefines } from "@babylonjs/core/Materials/materialDefines.js";
import { PushMaterial } from "@babylonjs/core/Materials/pushMaterial.js";
import { VertexBuffer } from "@babylonjs/core/Buffers/buffer.js";
import { RegisterClass } from "@babylonjs/core/Misc/typeStore.js";
import { Color3, Color4 } from "@babylonjs/core/Maths/math.color.js";
import { EffectFallbacks } from "@babylonjs/core/Materials/effectFallbacks.js";
import { Constants } from "@babylonjs/core/Engines/constants.js";
import "./shaders/fluentButton.fragment.js";
import "./shaders/fluentButton.vertex.js";
import { HandleFallbacksForShadows, PrepareAttributesForInstances, PrepareDefinesForAttributes, PrepareUniformsAndSamplersList } from "@babylonjs/core/Materials/materialHelper.functions.js";
import { Tools } from "@babylonjs/core/Misc/tools.js";
/** @internal */
class FluentButtonMaterialDefines extends MaterialDefines {
constructor() {
super();
this.RELATIVE_WIDTH = true;
this.ENABLE_FADE = true;
this._needNormals = true;
this._needUVs = true;
this.rebuild();
}
}
/**
* Class used to render square buttons with fluent design
* @since 5.0.0
*/
export class FluentButtonMaterial extends PushMaterial {
constructor(name, scene) {
super(name, scene);
/**
* Gets or sets the width of the glowing edge, relative to the scale of the button.
* (Default is 4% of the height).
*/
this.edgeWidth = 0.04;
/**
* Gets or sets the color of the glowing edge.
*/
this.edgeColor = new Color4(0.592157, 0.592157, 0.592157, 1.0);
/**
* Gets or sets the maximum intensity of the proximity light.
*/
this.proximityMaxIntensity = 0.45;
/**
* Gets or sets the maximum distance for the proximity light (Default is 16mm).
*/
this.proximityFarDistance = 0.16;
/**
* Gets or sets the radius of the proximity light when near to the surface.
*/
this.proximityNearRadius = 1.5;
/**
* Gets or sets the anisotropy of the proximity light.
*/
this.proximityAnisotropy = 1;
/**
* Gets or sets the amount of fuzzing in the selection focus.
*/
this.selectionFuzz = 0.5;
/**
* Gets or sets an override value to display the button as selected.
*/
this.selected = 0;
/**
* Gets or sets a value to manually fade the blob size.
*/
this.selectionFade = 0;
/**
* Gets or sets a value to manually shrink the blob size as it fades (see selectionFade).
*/
this.selectionFadeSize = 0.3;
/**
* Gets or sets the distance from the button the cursor should be for the button
* to appear selected (Default is 8cm).
*/
this.selectedDistance = 0.08;
/**
* Gets or sets the fall-off distance for the selection fade (Default is 8cm).
*/
this.selectedFadeLength = 0.08;
/**
* Gets or sets the intensity of the luminous blob (Ranges 0-1, default is 0.5).
*/
this.blobIntensity = 0.5;
/**
* The size of the blob when the pointer is at the blobFarDistance (Default is 5cm).
*/
this.blobFarSize = 0.05;
/**
* The distance at which the pointer is considered near. See [left|right]BlobNearSize. (Default is 0cm).
*/
this.blobNearDistance = 0;
/**
* The distance at which the pointer is considered far. See [left|right]BlobFarSize. (Default is 8cm).
*/
this.blobFarDistance = 0.08;
/**
* The distance over which the blob intensity fades from full to none (Default is 8cm).
*/
this.blobFadeLength = 0.08;
/**
* Gets or sets whether the blob corresponding to the left index finger is enabled.
*/
this.leftBlobEnable = true;
/**
* Gets or sets the size of the left blob when the left pointer is considered near. See blobNearDistance. (Default is 2.5cm).
*/
this.leftBlobNearSize = 0.025;
/**
* Gets or sets the progress of the pulse animation on the left blob (Ranges 0-1).
*/
this.leftBlobPulse = 0;
/**
* Gets or sets the fade factor on the left blob.
*/
this.leftBlobFade = 1;
/**
* Gets or sets the inner fade on the left blob;
*/
this.leftBlobInnerFade = 0.01;
/**
* Gets or sets whether the blob corresponding to the right index finger is enabled.
*/
this.rightBlobEnable = true;
/**
* Gets or sets the size of the right blob when the right pointer is considered near. See blobNearDistance. (Default is 2.5cm).
*/
this.rightBlobNearSize = 0.025;
/**
* Gets or sets the progress of the pulse animation on the right blob (Ranges 0-1).
*/
this.rightBlobPulse = 0;
/**
* Gets or sets the fade factor on the right blob.
*/
this.rightBlobFade = 1;
/**
* Gets or sets the inner fade on the right blob;
*/
this.rightBlobInnerFade = 0.01;
/**
* Gets or sets the direction of the active face before the world transform is applied.
* This should almost always be set to -z.
*/
this.activeFaceDir = new Vector3(0, 0, -1);
/**
* Gets or sets the button's up direction before the world transform is applied.
* This should almost always be set to +y.
*/
this.activeFaceUp = new Vector3(0, 1, 0);
/**
* Gets or sets whether the edge fade effect is enabled.
*/
this.enableFade = true;
/**
* Gets or sets a value corresponding to the width of the edge fade effect (Default 1.5).
*/
this.fadeWidth = 1.5;
/**
* Gets or sets whether the active face is smoothly interpolated.
*/
this.smoothActiveFace = true;
/**
* Gets or sets whether the frame of the fluent button model is visible.
* This is usually only enabled for debugging purposes.
*/
this.showFrame = false;
/**
* Gets or sets whether the blob color texture is used for the proximity
* light effect. This is usually only disabled for debugging purposes.
*/
this.useBlobTexture = true;
/**
* Gets or sets the world-space position of the tip of the left index finger.
*/
this.globalLeftIndexTipPosition = Vector3.Zero();
/**
* Gets or sets the world-space position of the tip of the right index finger.
*/
this.globalRightIndexTipPosition = Vector3.Zero();
this.alphaMode = Constants.ALPHA_ADD;
this.disableDepthWrite = true;
this.backFaceCulling = false;
const blobTextureUrl = Tools.GetAssetUrl(FluentButtonMaterial.BLOB_TEXTURE_URL);
this._blobTexture = new Texture(blobTextureUrl, this.getScene(), true, false, Texture.NEAREST_SAMPLINGMODE);
}
needAlphaBlending() {
return true;
}
needAlphaTesting() {
return true;
}
getAlphaTestTexture() {
return null;
}
// Methods
isReadyForSubMesh(mesh, subMesh) {
const drawWrapper = subMesh._drawWrapper;
if (this.isFrozen) {
if (drawWrapper.effect && drawWrapper._wasPreviouslyReady) {
return true;
}
}
if (!subMesh.materialDefines) {
subMesh.materialDefines = new FluentButtonMaterialDefines();
}
const defines = subMesh.materialDefines;
const scene = this.getScene();
if (this._isReadyForSubMesh(subMesh)) {
return true;
}
const engine = scene.getEngine();
// Attribs
PrepareDefinesForAttributes(mesh, defines, true, false);
// Get correct effect
if (defines.isDirty) {
defines.markAsProcessed();
scene.resetCachedMaterial();
// Fallbacks
const fallbacks = new EffectFallbacks();
if (defines.FOG) {
fallbacks.addFallback(1, "FOG");
}
HandleFallbacksForShadows(defines, fallbacks);
defines.IMAGEPROCESSINGPOSTPROCESS = scene.imageProcessingConfiguration.applyByPostProcess;
//Attributes
const attribs = [VertexBuffer.PositionKind];
if (defines.NORMAL) {
attribs.push(VertexBuffer.NormalKind);
}
if (defines.UV1) {
attribs.push(VertexBuffer.UVKind);
}
if (defines.UV2) {
attribs.push(VertexBuffer.UV2Kind);
}
if (defines.VERTEXCOLOR) {
attribs.push(VertexBuffer.ColorKind);
}
if (defines.TANGENT) {
attribs.push(VertexBuffer.TangentKind);
}
PrepareAttributesForInstances(attribs, defines);
// Legacy browser patch
const shaderName = "fluentButton";
const join = defines.toString();
const uniforms = [
"world",
"viewProjection",
"cameraPosition",
"_Edge_Width_",
"_Edge_Color_",
"_Relative_Width_",
"_Proximity_Max_Intensity_",
"_Proximity_Far_Distance_",
"_Proximity_Near_Radius_",
"_Proximity_Anisotropy_",
"_Selection_Fuzz_",
"_Selected_",
"_Selection_Fade_",
"_Selection_Fade_Size_",
"_Selected_Distance_",
"_Selected_Fade_Length_",
"_Blob_Enable_",
"_Blob_Position_",
"_Blob_Intensity_",
"_Blob_Near_Size_",
"_Blob_Far_Size_",
"_Blob_Near_Distance_",
"_Blob_Far_Distance_",
"_Blob_Fade_Length_",
"_Blob_Inner_Fade_",
"_Blob_Pulse_",
"_Blob_Fade_",
"_Blob_Texture_",
"_Blob_Enable_2_",
"_Blob_Position_2_",
"_Blob_Near_Size_2_",
"_Blob_Inner_Fade_2_",
"_Blob_Pulse_2_",
"_Blob_Fade_2_",
"_Active_Face_Dir_",
"_Active_Face_Up_",
"_Enable_Fade_",
"_Fade_Width_",
"_Smooth_Active_Face_",
"_Show_Frame_",
"_Use_Blob_Texture_",
"Use_Global_Left_Index",
"Use_Global_Right_Index",
"Global_Left_Index_Tip_Position",
"Global_Right_Index_Tip_Position",
"Global_Left_Thumb_Tip_Position",
"Global_Right_Thumb_Tip_Position",
"Global_Left_Index_Tip_Proximity",
"Global_Right_Index_Tip_Proximity",
];
const samplers = ["_Blob_Texture_"];
const uniformBuffers = [];
PrepareUniformsAndSamplersList({
uniformsNames: uniforms,
uniformBuffersNames: uniformBuffers,
samplers: samplers,
defines: defines,
maxSimultaneousLights: 4,
});
subMesh.setEffect(scene.getEngine().createEffect(shaderName, {
attributes: attribs,
uniformsNames: uniforms,
uniformBuffersNames: uniformBuffers,
samplers: samplers,
defines: join,
fallbacks: fallbacks,
onCompiled: this.onCompiled,
onError: this.onError,
indexParameters: { maxSimultaneousLights: 4 },
}, engine), defines, this._materialContext);
}
if (!subMesh.effect || !subMesh.effect.isReady()) {
return false;
}
defines._renderId = scene.getRenderId();
drawWrapper._wasPreviouslyReady = true;
return true;
}
bindForSubMesh(world, mesh, subMesh) {
const scene = this.getScene();
const defines = subMesh.materialDefines;
if (!defines) {
return;
}
const effect = subMesh.effect;
if (!effect) {
return;
}
this._activeEffect = effect;
// Matrices
this.bindOnlyWorldMatrix(world);
this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
this._activeEffect.setVector3("cameraPosition", scene.activeCamera.position);
// "Blob Texture"
this._activeEffect.setTexture("_Blob_Texture_", this._blobTexture);
// "Wireframe"
this._activeEffect.setFloat("_Edge_Width_", this.edgeWidth);
this._activeEffect.setColor4("_Edge_Color_", new Color3(this.edgeColor.r, this.edgeColor.g, this.edgeColor.b), this.edgeColor.a);
//define _Relative_Width_ true;
// "Proximity"
this._activeEffect.setFloat("_Proximity_Max_Intensity_", this.proximityMaxIntensity);
this._activeEffect.setFloat("_Proximity_Far_Distance_", this.proximityFarDistance);
this._activeEffect.setFloat("_Proximity_Near_Radius_", this.proximityNearRadius);
this._activeEffect.setFloat("_Proximity_Anisotropy_", this.proximityAnisotropy);
// "Selection"
this._activeEffect.setFloat("_Selection_Fuzz_", this.selectionFuzz);
this._activeEffect.setFloat("_Selected_", this.selected);
this._activeEffect.setFloat("_Selection_Fade_", this.selectionFade);
this._activeEffect.setFloat("_Selection_Fade_Size_", this.selectionFadeSize);
this._activeEffect.setFloat("_Selected_Distance_", this.selectedDistance);
this._activeEffect.setFloat("_Selected_Fade_Length_", this.selectedFadeLength);
// "Blob"
this._activeEffect.setFloat("_Blob_Enable_", this.leftBlobEnable ? 1.0 : 0.0);
this._activeEffect.setFloat("_Blob_Intensity_", this.blobIntensity);
this._activeEffect.setFloat("_Blob_Near_Size_", this.leftBlobNearSize);
this._activeEffect.setFloat("_Blob_Far_Size_", this.blobFarSize);
this._activeEffect.setFloat("_Blob_Near_Distance_", this.blobNearDistance);
this._activeEffect.setFloat("_Blob_Far_Distance_", this.blobFarDistance);
this._activeEffect.setFloat("_Blob_Fade_Length_", this.blobFadeLength);
this._activeEffect.setFloat("_Blob_Inner_Fade_", this.leftBlobInnerFade);
this._activeEffect.setFloat("_Blob_Pulse_", this.leftBlobPulse);
this._activeEffect.setFloat("_Blob_Fade_", this.leftBlobFade);
// "Blob 2"
this._activeEffect.setFloat("_Blob_Enable_2_", this.rightBlobEnable ? 1.0 : 0.0);
this._activeEffect.setFloat("_Blob_Near_Size_2_", this.rightBlobNearSize);
this._activeEffect.setFloat("_Blob_Inner_Fade_2_", this.rightBlobInnerFade);
this._activeEffect.setFloat("_Blob_Pulse_2_", this.rightBlobPulse);
this._activeEffect.setFloat("_Blob_Fade_2_", this.rightBlobFade);
// "Active Face"
this._activeEffect.setVector3("_Active_Face_Dir_", this.activeFaceDir);
this._activeEffect.setVector3("_Active_Face_Up_", this.activeFaceUp);
// "Hololens Edge Fade"
//define _Enable_Fade_ true;
this._activeEffect.setFloat("_Fade_Width_", this.fadeWidth);
this._activeEffect.setFloat("_Smooth_Active_Face_", this.smoothActiveFace ? 1.0 : 0.0);
// "Debug"
this._activeEffect.setFloat("_Show_Frame_", this.showFrame ? 1.0 : 0.0);
this._activeEffect.setFloat("_Use_Blob_Texture_", this.useBlobTexture ? 1.0 : 0.0);
// Global inputs
this._activeEffect.setFloat("Use_Global_Left_Index", 1.0);
this._activeEffect.setFloat("Use_Global_Right_Index", 1.0);
this._activeEffect.setVector4("Global_Left_Index_Tip_Position", new Vector4(this.globalLeftIndexTipPosition.x, this.globalLeftIndexTipPosition.y, this.globalLeftIndexTipPosition.z, 1.0));
this._activeEffect.setVector4("Global_Right_Index_Tip_Position", new Vector4(this.globalRightIndexTipPosition.x, this.globalRightIndexTipPosition.y, this.globalRightIndexTipPosition.z, 1.0));
this._afterBind(mesh, this._activeEffect, subMesh);
}
/**
* Get the list of animatables in the material.
* @returns the list of animatables object used in the material
*/
getAnimatables() {
return [];
}
dispose(forceDisposeEffect) {
super.dispose(forceDisposeEffect);
}
clone(name) {
return SerializationHelper.Clone(() => new FluentButtonMaterial(name, this.getScene()), this);
}
serialize() {
const serializationObject = super.serialize();
serializationObject.customType = "BABYLON.FluentButtonMaterial";
return serializationObject;
}
getClassName() {
return "FluentButtonMaterial";
}
// Statics
static Parse(source, scene, rootUrl) {
return SerializationHelper.Parse(() => new FluentButtonMaterial(source.name, scene), source, scene, rootUrl);
}
}
/**
* URL pointing to the texture used to define the coloring for the fluent blob effect.
*/
FluentButtonMaterial.BLOB_TEXTURE_URL = "https://assets.babylonjs.com/core/MRTK/mrtk-fluent-button-blob.png";
__decorate([
serialize()
], FluentButtonMaterial.prototype, "edgeWidth", void 0);
__decorate([
serializeAsColor4()
], FluentButtonMaterial.prototype, "edgeColor", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "proximityMaxIntensity", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "proximityFarDistance", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "proximityNearRadius", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "proximityAnisotropy", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "selectionFuzz", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "selected", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "selectionFade", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "selectionFadeSize", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "selectedDistance", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "selectedFadeLength", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "blobIntensity", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "blobFarSize", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "blobNearDistance", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "blobFarDistance", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "blobFadeLength", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "leftBlobEnable", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "leftBlobNearSize", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "leftBlobPulse", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "leftBlobFade", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "leftBlobInnerFade", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "rightBlobEnable", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "rightBlobNearSize", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "rightBlobPulse", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "rightBlobFade", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "rightBlobInnerFade", void 0);
__decorate([
serializeAsVector3()
], FluentButtonMaterial.prototype, "activeFaceDir", void 0);
__decorate([
serializeAsVector3()
], FluentButtonMaterial.prototype, "activeFaceUp", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "enableFade", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "fadeWidth", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "smoothActiveFace", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "showFrame", void 0);
__decorate([
serialize()
], FluentButtonMaterial.prototype, "useBlobTexture", void 0);
__decorate([
serializeAsVector3()
], FluentButtonMaterial.prototype, "globalLeftIndexTipPosition", void 0);
__decorate([
serializeAsVector3()
], FluentButtonMaterial.prototype, "globalRightIndexTipPosition", void 0);
RegisterClass("BABYLON.GUI.FluentButtonMaterial", FluentButtonMaterial);
//# sourceMappingURL=fluentButtonMaterial.js.map