import { Nullable } from "babylonjs/types" ; import { Observable } from "babylonjs/Misc/observable" ; import { Vector3 } from "babylonjs/Maths/math.vector" ; import { PointerEventTypes } from "babylonjs/Events/pointerEvents" ; import { TransformNode } from "babylonjs/Meshes/transformNode" ; import { AbstractMesh } from "babylonjs/Meshes/abstractMesh" ; import { IBehaviorAware , Behavior } from "babylonjs/Behaviors/behavior" ; import { IDisposable , Scene } from "babylonjs/scene" ; import { GUI3DManager } from "../gui3DManager" ; import { Vector3WithInfo } from "../vector3WithInfo" ; import { Container3D } from "./container3D" ; declare type TouchButton3D = import ( "./touchButton3D" ) . TouchButton3D ; /**
 * Class used as base class for controls
 */ export class Control3D implements IDisposable , IBehaviorAware < Control3D > { hidden public _host : GUI3DManager ; private _node : Nullable < TransformNode > ; private _downCount = 0 ; private _enterCount = - 1 ; private _downPointerIds : { [ id ] : number ; } = { } ; private _isVisible = true ; hidden public _isScaledByManager = false ; /** Gets or sets the control position in world space */ public get position ( ) : Vector3 { if ( ! this . _node ) { return Vector3 . Zero ( ) ; } return this . _node . position ; } public set position ( value ) { if ( ! this . _node ) { return ; } this . _node . position = value ; } /** Gets or sets the control scaling in world space */ public get scaling ( ) : Vector3 { if ( ! this . _node ) { return new Vector3 ( 1 , 1 , 1 ) ; } return this . _node . scaling ; } public set scaling ( value ) { if ( ! this . _node ) { return ; } this . _isScaledByManager = false ; this . _node . scaling = value ; } /** Callback used to start pointer enter animation */ public pointerEnterAnimation : ( ) => void ; /** Callback used to start pointer out animation */ public pointerOutAnimation : ( ) => void ; /** Callback used to start pointer down animation */ public pointerDownAnimation : ( ) => void ; /** Callback used to start pointer up animation */ public pointerUpAnimation : ( ) => void ; /**
     * An event triggered when the pointer moves over the control
     */ public onPointerMoveObservable = new Observable < Vector3 > ( ) ; /**
     * An event triggered when the pointer moves out of the control
     */ public onPointerOutObservable = new Observable < Control3D > ( ) ; /**
     * An event triggered when the pointer taps the control
     */ public onPointerDownObservable = new Observable < Vector3WithInfo > ( ) ; /**
     * An event triggered when pointer is up
     */ public onPointerUpObservable = new Observable < Vector3WithInfo > ( ) ; /**
     * An event triggered when a control is clicked on (with a mouse)
     */ public onPointerClickObservable = new Observable < Vector3WithInfo > ( ) ; /**
     * An event triggered when pointer enters the control
     */ public onPointerEnterObservable = new Observable < Control3D > ( ) ; /**
     * Gets or sets the parent container
     */ public parent : Nullable < Container3D > ; private _behaviors = new Array < Behavior < Control3D > > ( ) ; see https public get behaviors ( ) : Behavior < Control3D > [ ] { return this . _behaviors ; } see https param behavior returns public addBehavior ( behavior ) { var index = this . _behaviors . indexOf ( behavior ) ; if ( index !== - 1 ) { return this ; } behavior . init ( ) ; let scene = this . _host . scene ; if ( scene . isLoading ) { scene . onDataLoadedObservable . addOnce ( ( ) => { behavior . attach ( this ) ; } ) ; } else { behavior . attach ( this ) ; } this . _behaviors . push ( behavior ) ; return this ; } see https param behavior returns public removeBehavior ( behavior ) { var index = this . _behaviors . indexOf ( behavior ) ; if ( index === - 1 ) { return this ; } this . _behaviors [ index ] . detach ( ) ; this . _behaviors . splice ( index , 1 ) ; return this ; } param name see https returns public getBehaviorByName ( name ) { for ( var behavior of this . _behaviors ) { if ( behavior . name === name ) { return behavior ; } } return null ; } /** Gets or sets a boolean indicating if the control is visible */ public get isVisible ( ) : boolean { return this . _isVisible ; } public set isVisible ( value ) { if ( this . _isVisible === value ) { return ; } this . _isVisible = value ; let mesh = this . mesh ; if ( mesh ) { mesh . setEnabled ( value ) ; } } param name constructor ( /** Defines the control name */ public name ? ) { } /**
     * Gets a string representing the class name
     */ public get typeName ( ) : string { return this . _getTypeName ( ) ; } returns public getClassName ( ) { return this . _getTypeName ( ) ; } protected _getTypeName ( ) { return "Control3D" ; } /**
     * Gets the transform node used by this control
     */ public get node ( ) : Nullable < TransformNode > { return this . _node ; } /**
     * Gets the mesh used to render this control
     */ public get mesh ( ) : Nullable < AbstractMesh > { if ( this . _node instanceof AbstractMesh ) { return this . _node as AbstractMesh ; } return null ; } param node returns public linkToTransformNode ( node ) { if ( this . _node ) { this . _node . parent = node ; } return this ; } hidden public _prepareNode ( scene ) { if ( ! this . _node ) { this . _node = this . _createNode ( scene ) ; if ( ! this . node ) { return ; } this . _injectGUI3DReservedDataStore ( this . node ) . control = this ; let mesh = this . mesh ; if ( mesh ) { mesh . isPickable = true ; this . _affectMaterial ( mesh ) ; } } } protected _injectGUI3DReservedDataStore ( node ) { node . reservedDataStore = node . reservedDataStore ?? { } ; node . reservedDataStore . GUI3D = node . reservedDataStore . GUI3D ?? { } ; return node . reservedDataStore . GUI3D ; } param scene returns protected _createNode ( scene ) { return null ; } param mesh protected _affectMaterial ( mesh ) { mesh . material = null ; } private _IsTouchButton3D ( control ) { return ( control as TouchButton3D ) . _generatePointerEventType !== undefined ; } hidden public _onPointerMove ( target , coordinates ) { this . onPointerMoveObservable . notifyObservers ( coordinates , - 1 , target , this ) ; } hidden public _onPointerEnter ( target ) { if ( this . _enterCount === - 1 ) { this . _enterCount = 0 ; } this . _enterCount ++ ; if ( this . _enterCount > 1 ) { return false ; } this . onPointerEnterObservable . notifyObservers ( this , - 1 , target , this ) ; if ( this . pointerEnterAnimation ) { this . pointerEnterAnimation ( ) ; } return true ; } hidden public _onPointerOut ( target ) { this . _enterCount -- ; if ( this . _enterCount > 0 ) { return ; } this . _enterCount = 0 ; this . onPointerOutObservable . notifyObservers ( this , - 1 , target , this ) ; if ( this . pointerOutAnimation ) { this . pointerOutAnimation ( ) ; } } hidden public _onPointerDown ( target , coordinates , pointerId , buttonIndex ) { this . _downCount ++ ; this . _downPointerIds [ pointerId ] = this . _downPointerIds [ pointerId ] + 1 || 1 ; if ( this . _downCount !== 1 ) { return false ; } this . onPointerDownObservable . notifyObservers ( new Vector3WithInfo ( coordinates , buttonIndex ) , - 1 , target , this ) ; if ( this . pointerDownAnimation ) { this . pointerDownAnimation ( ) ; } return true ; } hidden public _onPointerUp ( target , coordinates , pointerId , buttonIndex , notifyClick ) { this . _downCount -- ; this . _downPointerIds [ pointerId ] -- ; if ( this . _downPointerIds [ pointerId ] <= 0 ) { delete this . _downPointerIds [ pointerId ] ; } if ( this . _downCount < 0 ) { this . _downCount = 0 ; return ; } if ( this . _downCount == 0 ) { if ( notifyClick && ( this . _enterCount > 0 || this . _enterCount === - 1 ) ) { this . onPointerClickObservable . notifyObservers ( new Vector3WithInfo ( coordinates , buttonIndex ) , - 1 , target , this ) ; } this . onPointerUpObservable . notifyObservers ( new Vector3WithInfo ( coordinates , buttonIndex ) , - 1 , target , this ) ; if ( this . pointerUpAnimation ) { this . pointerUpAnimation ( ) ; } } } hidden public forcePointerUp ( pointerId = null ) { if ( pointerId !== null ) { this . _onPointerUp ( this , Vector3 . Zero ( ) , pointerId , 0 , true ) ; } else { for ( var key in this . _downPointerIds ) { this . _onPointerUp ( this , Vector3 . Zero ( ) , + key as number , 0 , true ) ; } if ( this . _downCount > 0 ) { this . _downCount = 1 ; this . _onPointerUp ( this , Vector3 . Zero ( ) , 0 , 0 , true ) ; } } } hidden public _processObservables ( type , pickedPoint , originMeshPosition , pointerId , buttonIndex ) { if ( this . _IsTouchButton3D ( this ) && originMeshPosition ) { type = this . _generatePointerEventType ( type , originMeshPosition , this . _downCount ) ; } if ( type === PointerEventTypes . POINTERMOVE ) { this . _onPointerMove ( this , pickedPoint ) ; var previousControlOver = this . _host . _lastControlOver [ pointerId ] ; if ( previousControlOver && previousControlOver !== this ) { previousControlOver . _onPointerOut ( this ) ; } if ( previousControlOver !== this ) { this . _onPointerEnter ( this ) ; } this . _host . _lastControlOver [ pointerId ] = this ; return true ; } if ( type === PointerEventTypes . POINTERDOWN ) { this . _onPointerDown ( this , pickedPoint , pointerId , buttonIndex ) ; this . _host . _lastControlDown [ pointerId ] = this ; this . _host . _lastPickedControl = this ; return true ; } if ( type === PointerEventTypes . POINTERUP || type === PointerEventTypes . POINTERDOUBLETAP ) { if ( this . _host . _lastControlDown [ pointerId ] ) { this . _host . _lastControlDown [ pointerId ] . _onPointerUp ( this , pickedPoint , pointerId , buttonIndex , true ) ; } delete this . _host . _lastControlDown [ pointerId ] ; return true ; } return false ; } hidden public _disposeNode ( ) { if ( this . _node ) { this . _node . dispose ( ) ; this . _node = null ; } } /**
     * Releases all associated resources
     */ public dispose ( ) { this . onPointerDownObservable . clear ( ) ; this . onPointerEnterObservable . clear ( ) ; this . onPointerMoveObservable . clear ( ) ; this . onPointerOutObservable . clear ( ) ; this . onPointerUpObservable . clear ( ) ; this . onPointerClickObservable . clear ( ) ; this . _disposeNode ( ) ; for ( var behavior of this . _behaviors ) { behavior . detach ( ) ; } } }