import * as React from "react" ; import { Observable } from "babylonjs/Misc/observable" ; import { PropertyChangedEvent } from "../../../../propertyChangedEvent" ; import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent" ; import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent" ; import { TextLineComponent } from "../../../../../sharedUiComponents/lines/textLineComponent" ; import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject" ; import { GlobalState } from "../../../../globalState" ; import { Skeleton } from "babylonjs/Bones/skeleton" ; import { AnimationGridComponent } from "../animations/animationPropertyGridComponent" ; import { SkeletonViewer } from "babylonjs/Debug/skeletonViewer" ; import { CustomPropertyGridComponent } from "../customPropertyGridComponent" ; import { OptionsLineComponent } from "../../../../../sharedUiComponents/lines/optionsLineComponent" ; import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent" ; import { ButtonLineComponent } from "../../../../../sharedUiComponents/lines/buttonLineComponent" ; interface ISkeletonPropertyGridComponentProps { globalState : GlobalState ; skeleton : Skeleton ; lockObject : LockObject ; onPropertyChangedObservable ? : Observable < PropertyChangedEvent > ; } export class SkeletonPropertyGridComponent extends React . Component < ISkeletonPropertyGridComponentProps > { private _skeletonViewersEnabled = false ; private _skeletonViewerDisplayOptions = { displayMode : SkeletonViewer . DISPLAY_LINES , sphereBaseSize : 0.15 , sphereScaleUnit : 2 , sphereFactor : 0.865 , midStep : 0.235 , midStepFactor : 0.155 , } ; private _skeletonViewers = new Array < SkeletonViewer > ( ) ; constructor ( props ) { super ( props ) ; this . checkSkeletonViewerState ( this . props ) ; } switchSkeletonViewers ( ) { this . _skeletonViewersEnabled = ! this . _skeletonViewersEnabled ; const scene = this . props . skeleton . getScene ( ) ; if ( this . _skeletonViewersEnabled ) { for ( var mesh of scene . meshes ) { if ( mesh . skeleton === this . props . skeleton ) { var found = false ; for ( var sIndex = 0 ; sIndex < this . _skeletonViewers . length ; sIndex ++ ) { if ( this . _skeletonViewers [ sIndex ] . skeleton === mesh . skeleton ) { found = true ; break ; } } if ( found ) { continue ; } var viewer = new SkeletonViewer ( mesh . skeleton , mesh , scene , false , 3 , { displayMode : this . _skeletonViewerDisplayOptions . displayMode , displayOptions : { sphereBaseSize : this . _skeletonViewerDisplayOptions . sphereBaseSize , sphereScaleUnit : this . _skeletonViewerDisplayOptions . sphereScaleUnit , sphereFactor : this . _skeletonViewerDisplayOptions . sphereFactor , midStep : this . _skeletonViewerDisplayOptions . midStep , midStepFactor : this . _skeletonViewerDisplayOptions . midStepFactor , } , } ) ; viewer . isEnabled = true ; this . _skeletonViewers . push ( viewer ) ; if ( ! mesh . reservedDataStore ) { mesh . reservedDataStore = { } ; } mesh . reservedDataStore . skeletonViewer = viewer ; } } } else { for ( var index = 0 ; index < this . _skeletonViewers . length ; index ++ ) { this . _skeletonViewers [ index ] . mesh . reservedDataStore . skeletonViewer = null ; this . _skeletonViewers [ index ] . dispose ( ) ; } this . _skeletonViewers = [ ] ; } } checkSkeletonViewerState ( props ) { const scene = props . skeleton . getScene ( ) ; this . _skeletonViewers = [ ] ; if ( ! scene ) { return ; } var needInit = true ; for ( var mesh of scene . meshes ) { if ( mesh . skeleton === props . skeleton && mesh . reservedDataStore && mesh . reservedDataStore . skeletonViewer ) { this . _skeletonViewers . push ( mesh . reservedDataStore . skeletonViewer ) ; if ( needInit ) { needInit = false ; this . _skeletonViewerDisplayOptions . displayMode = this . _skeletonViewers [ 0 ] . displayMode ; for ( var key in this . _skeletonViewers [ 0 ] . options . displayOptions ) { if ( ! key ) { continue ; } ( this . _skeletonViewerDisplayOptions as any ) [ key ] = ( this . _skeletonViewers [ 0 ] . options as any ) . displayOptions [ key ] ; } } } } this . _skeletonViewersEnabled = this . _skeletonViewers . length > 0 ; } changeDisplayMode ( ) { if ( this . _skeletonViewersEnabled ) { for ( var index = 0 ; index < this . _skeletonViewers . length ; index ++ ) { this . _skeletonViewers [ index ] . changeDisplayMode ( this . _skeletonViewerDisplayOptions . displayMode || 0 ) ; } } } changeDisplayOptions ( option , value ) { if ( this . _skeletonViewersEnabled ) { for ( var index = 0 ; index < this . _skeletonViewers . length ; index ++ ) { this . _skeletonViewers [ index ] . changeDisplayOptions ( option , value ) ; } if ( ( this . _skeletonViewerDisplayOptions as any ) [ option ] !== undefined ) { ( this . _skeletonViewerDisplayOptions as any ) [ option ] = value ; } } } shouldComponentUpdate ( nextProps ) { if ( nextProps . skeleton !== this . props . skeleton ) { this . checkSkeletonViewerState ( nextProps ) ; } return true ; } onOverrideMeshLink ( ) { if ( ! this . props . globalState . onSelectionChangedObservable ) { return ; } const skeleton = this . props . skeleton ; this . props . globalState . onSelectionChangedObservable . notifyObservers ( skeleton . overrideMesh ) ; } render ( ) { const skeleton = this . props . skeleton ; const debugModeOptions = [ { label : "Lines" , value : SkeletonViewer . DISPLAY_LINES } , { label : "Spheres" , value : SkeletonViewer . DISPLAY_SPHERES } , { label : "Sphere and Spurs" , value : SkeletonViewer . DISPLAY_SPHERE_AND_SPURS } , ] ; let displayOptions ; if ( this . _skeletonViewerDisplayOptions . displayMode > SkeletonViewer . DISPLAY_LINES ) { displayOptions = ( < LineContainerComponent title = "DISPLAY OPTIONS" selection = { this . props . globalState } > < FloatLineComponent label = "sphereBaseSize" target = { this . _skeletonViewerDisplayOptions } propertyName = "sphereBaseSize" onPropertyChangedObservable = { this . props . onPropertyChangedObservable } onChange = { ( value ) => { this . changeDisplayOptions ( "sphereBaseSize" , value ) ; } } /> < FloatLineComponent label = "sphereScaleUnit" target = { this . _skeletonViewerDisplayOptions } propertyName = "sphereScaleUnit" onPropertyChangedObservable = { this . props . onPropertyChangedObservable } onChange = { ( value ) => { this . changeDisplayOptions ( "sphereScaleUnit" , value ) ; } } /> < FloatLineComponent label = "sphereFactor" target = { this . _skeletonViewerDisplayOptions } propertyName = "sphereFactor" onPropertyChangedObservable = { this . props . onPropertyChangedObservable } onChange = { ( value ) => { this . changeDisplayOptions ( "sphereFactor" , value ) ; } } /> < FloatLineComponent label = "midStep" target = { this . _skeletonViewerDisplayOptions } propertyName = "midStep" onPropertyChangedObservable = { this . props . onPropertyChangedObservable } onChange = { ( value ) => { this . changeDisplayOptions ( "midStep" , value ) ; } } /> < FloatLineComponent label = "midStepFactor" target = { this . _skeletonViewerDisplayOptions } propertyName = "midStepFactor" onPropertyChangedObservable = { this . props . onPropertyChangedObservable } onChange = { ( value ) => { this . changeDisplayOptions ( "midStepFactor" , value ) ; } } /> < /LineContainerComponent>); } else { displayOptions = null ; } return ( < div className = "pane" > < CustomPropertyGridComponent globalState = { this . props . globalState } target = { skeleton } lockObject = { this . props . lockObject } onPropertyChangedObservable = { this . props . onPropertyChangedObservable } / > < LineContainerComponent title = "GENERAL" selection = { this . props . globalState } > < TextLineComponent label = "ID" value = { skeleton . id } / > < TextLineComponent label = "Bone count" value = { skeleton . bones . length . toString ( ) } / > { skeleton . overrideMesh && < TextLineComponent label = "Override mesh" value = { skeleton . overrideMesh . name } onLink = { ( ) => this . onOverrideMeshLink ( ) } / > } < CheckBoxLineComponent label = "Use texture to store matrices" target = { skeleton } propertyName = "useTextureToStoreBoneMatrices" onPropertyChangedObservable = { this . props . onPropertyChangedObservable } / > < ButtonLineComponent label = "Return to rest" onClick = { ( ) => skeleton . returnToRest ( ) } /> < /LineContainerComponent> < LineContainerComponent title = "DEBUG" selection = { this . props . globalState } > < CheckBoxLineComponent label = "Enabled" isSelected = { ( ) => this . _skeletonViewersEnabled } onSelect = { ( ) => this . switchSkeletonViewers ( ) } /> < OptionsLineComponent label = "displayMode" options = { debugModeOptions } target = { this . _skeletonViewerDisplayOptions } propertyName = "displayMode" onPropertyChangedObservable = { this . props . onPropertyChangedObservable } onSelect = { ( ) => this . changeDisplayMode ( ) } /> { displayOptions } < /LineContainerComponent> < AnimationGridComponent globalState = { this . props . globalState } animatable = { skeleton } scene = { skeleton . getScene ( ) } lockObject = { this . props . lockObject } / > < /div>); } }