import { IAction } from '@babylonjs/core/Actions/action.js' ; import { ActionEvent } from '@babylonjs/core/Actions/actionEvent.js' ; import { ActionManager } from '@babylonjs/core/Actions/actionManager.js' ; import { ExecuteCodeAction } from '@babylonjs/core/Actions/directActions.js' ; import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh.js' ; import { Mesh } from '@babylonjs/core/Meshes/mesh.js' ; import { EventState , Observer } from '@babylonjs/core/Misc/observable.js' ; import { Nullable } from '@babylonjs/core/types.js' ; import { Control } from '@babylonjs/gui/2D/controls/control.js' ; import { MutableRefObject , useEffect , useRef , useState } from 'react' ; import { CustomPropsHandler , ICustomPropsHandler } from '../PropsHandler.js' ; export const useCustomPropsHandler = ( propsHandler ) : void => { const firstRun = useRef < boolean > ( true ) ; if ( firstRun . current === true ) { CustomPropsHandler . RegisterPropsHandler ( propsHandler ) ; firstRun . current = false ; } useEffect ( ( ) => { return ( ) => { CustomPropsHandler . UnregisterPropsHandler ( propsHandler ) ; } ; } , [ ] ) ; } ; export type MeshEventType = { ( ev ) : void ; } ; export type Gui2dEventType = { ( eventData , eventState ) : void ; } ; export type HoverType = MeshEventType | Gui2dEventType ; param over param out param ownRef export const useHover = ( over ? , out ? , ownRef ? ) : [ MutableRefObject < Mesh | Control | null > , boolean ] => { const [ value , setValue ] = useState ( false ) ; const createdRef = useRef < Mesh > ( null ) as MutableRefObject < Mesh | Control | null > ; const ref = ownRef ?? createdRef ; useEffect ( ( ) => { if ( ref . current ) { const registeredMeshActions = [ ] ; let observer2dGuiEnter = null ; let observer2dGuiOut = null ; if ( ref . current instanceof AbstractMesh ) { const mesh = ref . current as Mesh ; if ( ! mesh . actionManager ) { mesh . actionManager = new ActionManager ( mesh . getScene ( ) ) ; } const onPointerOverAction = mesh . actionManager . registerAction ( new ExecuteCodeAction ( ActionManager . OnPointerOverTrigger , ( ev ) => { over && ( over as MeshEventType ) ( ev ) ; setValue ( true ) ; } ) ) ; const onPointerOutAction = mesh . actionManager . registerAction ( new ExecuteCodeAction ( ActionManager . OnPointerOutTrigger , ( ev ) => { out && ( out as MeshEventType ) ( ev ) ; setValue ( false ) ; } ) ) ; registeredMeshActions . push ( onPointerOverAction ) ; registeredMeshActions . push ( onPointerOutAction ) ; } else if ( ref . current instanceof Control ) { const control = ref . current as Control ; observer2dGuiEnter = control . onPointerEnterObservable . add ( over as Gui2dEventType ) ; observer2dGuiOut = control . onPointerOutObservable . add ( out as Gui2dEventType ) ; } else { console . warn ( 'Can only apply useHover to non-mesh/2D control currently.' , ref . current ) ; } if ( registeredMeshActions . length > 0 || observer2dGuiEnter !== null ) { return ( ) => { if ( ref . current ) { if ( registeredMeshActions . length > 0 ) { registeredMeshActions . forEach ( ( action ) => { if ( action !== null ) { const mesh = ref . current as Mesh ; mesh . actionManager ?. unregisterAction ( action ) ; } } ) ; registeredMeshActions . splice ( 0 , registeredMeshActions . length ) ; } if ( observer2dGuiEnter !== null ) { const control = ref . current as Control ; control . onPointerEnterObservable . remove ( observer2dGuiEnter ) ; control . onPointerOutObservable . remove ( observer2dGuiOut ) ; observer2dGuiEnter = null ; observer2dGuiOut = null ; } } } ; } } } , [ ref . current ] ) ; return [ ref , value ] ; } ; param onClick param ownRef export function useClick ( onClick , ownRef ? ) { const createdRef = useRef < Nullable < Mesh > > ( null ) ; const ref = ownRef ?? createdRef ; useEffect ( ( ) => { if ( ref . current ) { if ( ref . current instanceof AbstractMesh ) { const mesh = ref . current as Mesh ; if ( ! mesh . actionManager ) { mesh . actionManager = new ActionManager ( mesh . getScene ( ) ) ; } const action = mesh . actionManager . registerAction ( new ExecuteCodeAction ( ActionManager . OnPickTrigger , function ( ev ) { onClick ( ev ) ; } ) ) ; return ( ) => { mesh . actionManager ?. unregisterAction ( action ! ) ; } ; } else { console . warn ( 'onClick hook only supports referencing Meshes' ) ; } } } , [ ref ] ) ; return [ ref ] ; }