import { Vector3 } from "babylonjs/Maths/math.vector" ; import { Mesh } from "babylonjs/Meshes/mesh" ; import { PointerEventTypes } from "babylonjs/Events/pointerEvents" ; import { TransformNode } from "babylonjs/Meshes/transformNode" ; import { Scene } from "babylonjs/scene" ; import { TmpVectors } from "babylonjs/Maths/math.vector" ; import { Observable } from "babylonjs/Misc/observable" ; import { Button3D } from "./button3D" ; /**
 * Class used to create a touchable button in 3D
 */ export class TouchButton3D extends Button3D { private _collisionMesh : Mesh ; private _collidableFrontDirection : Vector3 ; protected _isNearPressed = false ; private _isToggleButton = false ; private _toggleState = false ; private _toggleButtonCallback = ( ) => { this . _onToggle ( ! this . _toggleState ) ; } ; /**
     * An event triggered when the button is toggled. Only fired if 'isToggleButton' is true
     */ public onToggleObservable = new Observable < boolean > ( ) ; param name param collisionMesh constructor ( name ? , collisionMesh ? ) { super ( name ) ; this . collidableFrontDirection = Vector3 . Zero ( ) ; if ( collisionMesh ) { this . collisionMesh = collisionMesh ; } } param frontDir public set collidableFrontDirection ( frontWorldDir ) { this . _collidableFrontDirection = frontWorldDir . normalize ( ) ; if ( this . _collisionMesh ) { const invert = TmpVectors . Matrix [ 0 ] ; invert . copyFrom ( this . _collisionMesh . getWorldMatrix ( ) ) ; invert . invert ( ) ; Vector3 . TransformNormalToRef ( this . _collidableFrontDirection , invert , this . _collidableFrontDirection ) ; this . _collidableFrontDirection . normalize ( ) ; } } /**
     * Returns the front-facing direction of the button, or Vector3.Zero if there is no 'front'
     */ public get collidableFrontDirection ( ) { if ( this . _collisionMesh ) { const transformedDirection = TmpVectors . Vector3 [ 0 ] ; Vector3 . TransformNormalToRef ( this . _collidableFrontDirection , this . _collisionMesh . getWorldMatrix ( ) , transformedDirection ) ; return transformedDirection . normalize ( ) ; } return this . _collidableFrontDirection ; } param collisionMesh public set collisionMesh ( collisionMesh ) { if ( this . _collisionMesh ) { this . _collisionMesh . dispose ( ) ; } if ( ! collisionMesh . parent && this . mesh ) { collisionMesh . setParent ( this . mesh ) ; } this . _collisionMesh = collisionMesh ; this . _injectGUI3DReservedDataStore ( this . _collisionMesh ) . control = this ; this . _collisionMesh . isNearPickable = true ; this . collidableFrontDirection = collisionMesh . forward ; } param value public set isToggleButton ( value ) { if ( value === this . _isToggleButton ) { return ; } this . _isToggleButton = value ; if ( value ) { this . onPointerUpObservable . add ( this . _toggleButtonCallback ) ; } else { this . onPointerUpObservable . removeCallback ( this . _toggleButtonCallback ) ; if ( this . _toggleState ) { this . _onToggle ( false ) ; } } } public get isToggleButton ( ) { return this . _isToggleButton ; } param newState public set isToggled ( newState ) { if ( this . _isToggleButton && this . _toggleState !== newState ) { this . _onToggle ( newState ) ; } } public get isToggled ( ) { return this . _toggleState ; } protected _onToggle ( newState ) { this . _toggleState = newState ; this . onToggleObservable . notifyObservers ( newState ) ; } private _isInteractionInFrontOfButton ( collidablePos ) { return this . _getInteractionHeight ( collidablePos , this . _collisionMesh . getAbsolutePosition ( ) ) > 0 ; } protected _getInteractionHeight ( interactionPos , basePos ) { const frontDir = this . collidableFrontDirection ; if ( frontDir . length ( ) === 0 ) { return Vector3 . Distance ( interactionPos , basePos ) ; } const d = Vector3 . Dot ( basePos , frontDir ) ; const abc = Vector3 . Dot ( interactionPos , frontDir ) ; return abc - d ; } hidden public _generatePointerEventType ( providedType , nearMeshPosition , activeInteractionCount ) { if ( providedType === PointerEventTypes . POINTERDOWN ) { if ( ! this . _isInteractionInFrontOfButton ( nearMeshPosition ) ) { return PointerEventTypes . POINTERMOVE ; } else { this . _isNearPressed = true ; } } if ( providedType === PointerEventTypes . POINTERUP ) { if ( activeInteractionCount == 0 ) { return PointerEventTypes . POINTERMOVE ; } else { this . _isNearPressed = false ; } } return providedType ; } protected _getTypeName ( ) { return "TouchButton3D" ; } protected _createNode ( scene ) { return super . _createNode ( scene ) ; } /**
     * Releases all associated resources
     */ public dispose ( ) { super . dispose ( ) ; this . onPointerUpObservable . removeCallback ( this . _toggleButtonCallback ) ; this . onToggleObservable . clear ( ) ; if ( this . _collisionMesh ) { this . _collisionMesh . dispose ( ) ; } } }