sceneTreeItemComponent.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import { Scene, Observable, PointerInfo, Observer, Nullable, GizmoManager, IExplorerExtensibilityGroup } from "babylonjs";
  2. import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
  3. import { faSyncAlt, faImage, faCrosshairs, faArrowsAlt, faCompress, faRedoAlt } from '@fortawesome/free-solid-svg-icons';
  4. import { ExtensionsComponent } from "../extensionsComponent";
  5. import * as React from "react";
  6. interface ISceneTreeItemComponentProps {
  7. scene: Scene,
  8. onRefresh: () => void,
  9. selectedEntity?: any,
  10. extensibilityGroups?: IExplorerExtensibilityGroup[],
  11. onSelectionChangeObservable?: Observable<any>
  12. }
  13. export class SceneTreeItemComponent extends React.Component<ISceneTreeItemComponentProps, { isSelected: boolean, isInPickingMode: boolean, gizmoMode: number }> {
  14. private _onPointerObserver: Nullable<Observer<PointerInfo>>;
  15. private _onSelectionChangeObserver: Nullable<Observer<any>>;
  16. constructor(props: ISceneTreeItemComponentProps) {
  17. super(props);
  18. const scene = this.props.scene;
  19. let gizmoMode = 0;
  20. if (scene.metadata && scene.metadata.gizmoManager) {
  21. const manager: GizmoManager = scene.metadata.gizmoManager;
  22. if (manager.positionGizmoEnabled) {
  23. gizmoMode = 1;
  24. } else if (manager.rotationGizmoEnabled) {
  25. gizmoMode = 2;
  26. } else if (manager.scaleGizmoEnabled) {
  27. gizmoMode = 3;
  28. }
  29. }
  30. this.state = { isSelected: false, isInPickingMode: false, gizmoMode: gizmoMode };
  31. }
  32. shouldComponentUpdate(nextProps: ISceneTreeItemComponentProps, nextState: { isSelected: boolean, isInPickingMode: boolean }) {
  33. if (nextProps.selectedEntity) {
  34. if (nextProps.scene === nextProps.selectedEntity) {
  35. nextState.isSelected = true;
  36. return true;
  37. } else {
  38. nextState.isSelected = false;
  39. }
  40. }
  41. return true;
  42. }
  43. componentWillMount() {
  44. if (!this.props.onSelectionChangeObservable) {
  45. return;
  46. }
  47. const scene = this.props.scene;
  48. this._onSelectionChangeObserver = this.props.onSelectionChangeObservable.add((entity) => {
  49. if (scene.metadata && scene.metadata.gizmoManager) {
  50. const manager: GizmoManager = scene.metadata.gizmoManager;
  51. const className = entity.getClassName();
  52. if (className === "TransformNode" || className.indexOf("Mesh") !== -1) {
  53. manager.attachToMesh(entity);
  54. }
  55. }
  56. });
  57. }
  58. componentWillUnmount() {
  59. const scene = this.props.scene;
  60. if (this._onPointerObserver) {
  61. scene.onPointerObservable.remove(this._onPointerObserver);
  62. this._onPointerObserver = null;
  63. }
  64. if (this._onSelectionChangeObserver && this.props.onSelectionChangeObservable) {
  65. this.props.onSelectionChangeObservable.remove(this._onSelectionChangeObserver);
  66. }
  67. }
  68. onSelect() {
  69. if (!this.props.onSelectionChangeObservable) {
  70. return;
  71. }
  72. const scene = this.props.scene;
  73. this.props.onSelectionChangeObservable.notifyObservers(scene);
  74. }
  75. onPickingMode() {
  76. const scene = this.props.scene;
  77. if (this._onPointerObserver) {
  78. scene.onPointerObservable.remove(this._onPointerObserver);
  79. this._onPointerObserver = null;
  80. }
  81. if (!this.state.isInPickingMode) {
  82. this._onPointerObserver = scene.onPointerObservable.add(() => {
  83. const pickPosition = scene.unTranslatedPointer;
  84. const pickInfo = scene.pick(pickPosition.x, pickPosition.y, mesh => mesh.isEnabled() && mesh.isVisible && mesh.getTotalVertices() > 0);
  85. if (pickInfo && pickInfo.hit && this.props.onSelectionChangeObservable) {
  86. this.props.onSelectionChangeObservable.notifyObservers(pickInfo.pickedMesh);
  87. }
  88. }, BABYLON.PointerEventTypes.POINTERTAP)
  89. }
  90. this.setState({ isInPickingMode: !this.state.isInPickingMode });
  91. }
  92. setGizmoMode(mode: number) {
  93. const scene = this.props.scene;
  94. if (!scene.metadata) {
  95. scene.metadata = {};
  96. }
  97. if (!scene.metadata.gizmoManager) {
  98. scene.metadata.gizmoManager = new GizmoManager(scene);
  99. }
  100. const manager: GizmoManager = scene.metadata.gizmoManager;
  101. manager.positionGizmoEnabled = false;
  102. manager.rotationGizmoEnabled = false;
  103. manager.scaleGizmoEnabled = false;
  104. if (this.state.gizmoMode === mode) {
  105. mode = 0;
  106. manager.dispose();
  107. scene.metadata.gizmoManager = null;
  108. } else {
  109. switch (mode) {
  110. case 1:
  111. manager.positionGizmoEnabled = true;
  112. break;
  113. case 2:
  114. manager.rotationGizmoEnabled = true;
  115. break;
  116. case 3:
  117. manager.scaleGizmoEnabled = true;
  118. break;
  119. }
  120. }
  121. this.setState({ gizmoMode: mode });
  122. }
  123. render() {
  124. return (
  125. <div className={this.state.isSelected ? "itemContainer selected" : "itemContainer"}>
  126. <div className="sceneNode">
  127. <div className="sceneTitle" onClick={() => this.onSelect()} >
  128. <FontAwesomeIcon icon={faImage} />&nbsp;Scene
  129. </div>
  130. <div className={this.state.gizmoMode === 1 ? "translation selected icon" : "translation icon"} onClick={() => this.setGizmoMode(1)} title="Enable/Disable position mode">
  131. <FontAwesomeIcon icon={faArrowsAlt} />
  132. </div>
  133. <div className={this.state.gizmoMode === 2 ? "rotation selected icon" : "rotation icon"} onClick={() => this.setGizmoMode(2)} title="Enable/Disable rotation mode">
  134. <FontAwesomeIcon icon={faRedoAlt} />
  135. </div>
  136. <div className={this.state.gizmoMode === 3 ? "scaling selected icon" : "scaling icon"} onClick={() => this.setGizmoMode(3)} title="Enable/Disable scaling mode">
  137. <FontAwesomeIcon icon={faCompress} />
  138. </div>
  139. <div className="separator" />
  140. <div className={this.state.isInPickingMode ? "pickingMode selected icon" : "pickingMode icon"} onClick={() => this.onPickingMode()} title="Turn picking mode on/off">
  141. <FontAwesomeIcon icon={faCrosshairs} />
  142. </div>
  143. <div className="refresh icon" onClick={() => this.props.onRefresh()} title="Refresh the explorer">
  144. <FontAwesomeIcon icon={faSyncAlt} />
  145. </div>
  146. {
  147. <ExtensionsComponent target={this.props.scene} extensibilityGroups={this.props.extensibilityGroups} />
  148. }
  149. </div>
  150. </div>
  151. )
  152. }
  153. }