skeletonPropertyGridComponent.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import * as React from "react";
  2. import { Observable } from "babylonjs/Misc/observable";
  3. import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
  4. import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
  5. import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
  6. import { TextLineComponent } from "../../../../../sharedUiComponents/lines/textLineComponent";
  7. import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
  8. import { GlobalState } from '../../../../globalState';
  9. import { Skeleton } from 'babylonjs/Bones/skeleton';
  10. import { AnimationGridComponent } from '../animations/animationPropertyGridComponent';
  11. import { SkeletonViewer } from 'babylonjs/Debug/skeletonViewer';
  12. import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
  13. import { OptionsLineComponent } from "../../../../../sharedUiComponents/lines/optionsLineComponent";
  14. import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
  15. interface ISkeletonPropertyGridComponentProps {
  16. globalState: GlobalState;
  17. skeleton: Skeleton,
  18. lockObject: LockObject,
  19. onPropertyChangedObservable?: Observable<PropertyChangedEvent>
  20. }
  21. export class SkeletonPropertyGridComponent extends React.Component<ISkeletonPropertyGridComponentProps> {
  22. private _skeletonViewersEnabled = false;
  23. private _skeletonViewerDisplayOptions = {
  24. displayMode : SkeletonViewer.DISPLAY_LINES,
  25. sphereBaseSize : 0.15,
  26. sphereScaleUnit : 2,
  27. sphereFactor : 0.865,
  28. midStep : 0.235,
  29. midStepFactor : 0.155
  30. }
  31. private _skeletonViewers = new Array<SkeletonViewer>();
  32. constructor(props: ISkeletonPropertyGridComponentProps) {
  33. super(props);
  34. this.checkSkeletonViewerState(this.props);
  35. }
  36. switchSkeletonViewers() {
  37. this._skeletonViewersEnabled = !this._skeletonViewersEnabled;
  38. const scene = this.props.skeleton.getScene();
  39. if (this._skeletonViewersEnabled) {
  40. for (var mesh of scene.meshes) {
  41. if (mesh.skeleton === this.props.skeleton) {
  42. var found = false;
  43. for (var sIndex = 0; sIndex < this._skeletonViewers.length; sIndex++) {
  44. if (this._skeletonViewers[sIndex].skeleton === mesh.skeleton) {
  45. found = true;
  46. break;
  47. }
  48. }
  49. if (found) {
  50. continue;
  51. }
  52. var viewer = new SkeletonViewer(mesh.skeleton, mesh, scene, false, 3, {
  53. displayMode: this._skeletonViewerDisplayOptions.displayMode,
  54. displayOptions : {
  55. sphereBaseSize : this._skeletonViewerDisplayOptions.sphereBaseSize,
  56. sphereScaleUnit : this._skeletonViewerDisplayOptions.sphereScaleUnit,
  57. sphereFactor : this._skeletonViewerDisplayOptions.sphereFactor,
  58. midStep : this._skeletonViewerDisplayOptions.midStep,
  59. midStepFactor : this._skeletonViewerDisplayOptions.midStepFactor
  60. }
  61. });
  62. viewer.isEnabled = true;
  63. this._skeletonViewers.push(viewer);
  64. if (!mesh.reservedDataStore) {
  65. mesh.reservedDataStore = {};
  66. }
  67. mesh.reservedDataStore.skeletonViewer = viewer;
  68. }
  69. }
  70. } else {
  71. for (var index = 0; index < this._skeletonViewers.length; index++) {
  72. this._skeletonViewers[index].mesh.reservedDataStore.skeletonViewer = null;
  73. this._skeletonViewers[index].dispose();
  74. }
  75. this._skeletonViewers = [];
  76. }
  77. }
  78. checkSkeletonViewerState(props: ISkeletonPropertyGridComponentProps) {
  79. const scene = props.skeleton.getScene();
  80. this._skeletonViewers = [];
  81. if (!scene) {
  82. return;
  83. }
  84. var needInit = true;
  85. for (var mesh of scene.meshes) {
  86. if (mesh.skeleton === props.skeleton && mesh.reservedDataStore && mesh.reservedDataStore.skeletonViewer) {
  87. this._skeletonViewers.push(mesh.reservedDataStore.skeletonViewer);
  88. if (needInit) {
  89. needInit = false;
  90. this._skeletonViewerDisplayOptions.displayMode = this._skeletonViewers[0].displayMode;
  91. for (var key in this._skeletonViewers[0].options.displayOptions) {
  92. if (!key) {
  93. continue;
  94. }
  95. (this._skeletonViewerDisplayOptions as any)[key] = (this._skeletonViewers[0].options as any).displayOptions[key];
  96. }
  97. }
  98. }
  99. }
  100. this._skeletonViewersEnabled = (this._skeletonViewers.length > 0);
  101. }
  102. changeDisplayMode(){
  103. if (this._skeletonViewersEnabled){
  104. for (var index = 0; index < this._skeletonViewers.length; index++) {
  105. this._skeletonViewers[index].changeDisplayMode( this._skeletonViewerDisplayOptions.displayMode || 0 );
  106. }
  107. }
  108. }
  109. changeDisplayOptions(option: string, value: number){
  110. if (this._skeletonViewersEnabled){
  111. for (var index = 0; index < this._skeletonViewers.length; index++) {
  112. this._skeletonViewers[index].changeDisplayOptions( option, value );
  113. }
  114. if((this._skeletonViewerDisplayOptions as any)[option] !== undefined ){
  115. (this._skeletonViewerDisplayOptions as any)[option] = value;
  116. }
  117. }
  118. }
  119. shouldComponentUpdate(nextProps: ISkeletonPropertyGridComponentProps) {
  120. if (nextProps.skeleton !== this.props.skeleton) {
  121. this.checkSkeletonViewerState(nextProps);
  122. }
  123. return true;
  124. }
  125. onOverrideMeshLink() {
  126. if (!this.props.globalState.onSelectionChangedObservable) {
  127. return;
  128. }
  129. const skeleton = this.props.skeleton;
  130. this.props.globalState.onSelectionChangedObservable.notifyObservers(skeleton.overrideMesh);
  131. }
  132. render() {
  133. const skeleton = this.props.skeleton;
  134. const debugModeOptions = [
  135. { label: "Lines", value: SkeletonViewer.DISPLAY_LINES },
  136. { label: "Spheres", value: SkeletonViewer.DISPLAY_SPHERES },
  137. { label: "Sphere and Spurs", value: SkeletonViewer.DISPLAY_SPHERE_AND_SPURS }
  138. ];
  139. let displayOptions;
  140. if(this._skeletonViewerDisplayOptions.displayMode > SkeletonViewer.DISPLAY_LINES){
  141. displayOptions =
  142. (<LineContainerComponent title="DISPLAY OPTIONS">
  143. <FloatLineComponent label="sphereBaseSize" target={this._skeletonViewerDisplayOptions} propertyName='sphereBaseSize' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('sphereBaseSize', value)}}/>
  144. <FloatLineComponent label="sphereScaleUnit" target={this._skeletonViewerDisplayOptions} propertyName='sphereScaleUnit' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('sphereScaleUnit', value)}}/>
  145. <FloatLineComponent label="sphereFactor" target={this._skeletonViewerDisplayOptions} propertyName='sphereFactor' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('sphereFactor', value)}}/>
  146. <FloatLineComponent label="midStep" target={this._skeletonViewerDisplayOptions} propertyName='midStep' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('midStep', value)}}/>
  147. <FloatLineComponent label="midStepFactor" target={this._skeletonViewerDisplayOptions} propertyName='midStepFactor' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('midStepFactor', value)}}/>
  148. </LineContainerComponent>)
  149. }else{
  150. displayOptions = (null)
  151. }
  152. return (
  153. <div className="pane">
  154. <CustomPropertyGridComponent globalState={this.props.globalState} target={skeleton}
  155. lockObject={this.props.lockObject}
  156. onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  157. <LineContainerComponent title="GENERAL">
  158. <TextLineComponent label="ID" value={skeleton.id} />
  159. <TextLineComponent label="Bone count" value={skeleton.bones.length.toString()} />
  160. {
  161. skeleton.overrideMesh &&
  162. <TextLineComponent label="Override mesh" value={skeleton.overrideMesh.name} onLink={() => this.onOverrideMeshLink()}/>
  163. }
  164. <CheckBoxLineComponent label="Use texture to store matrices" target={skeleton} propertyName="useTextureToStoreBoneMatrices" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  165. <LineContainerComponent title="DEBUG">
  166. <CheckBoxLineComponent label="Enabled" isSelected={() => this._skeletonViewersEnabled} onSelect={() => this.switchSkeletonViewers()} />
  167. <OptionsLineComponent label="displayMode" options={debugModeOptions} target={this._skeletonViewerDisplayOptions} propertyName="displayMode" onPropertyChangedObservable={this.props.onPropertyChangedObservable} onSelect={() => this.changeDisplayMode()} />
  168. {displayOptions}
  169. </LineContainerComponent>
  170. </LineContainerComponent>
  171. <AnimationGridComponent globalState={this.props.globalState} animatable={skeleton} scene={skeleton.getScene()} lockObject={this.props.lockObject} />
  172. </div>
  173. );
  174. }
  175. }