babylon.gizmoManager.ts 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. module BABYLON {
  2. /**
  3. * Helps setup gizmo's in the scene to rotate/scale/position meshes
  4. */
  5. export class GizmoManager implements IDisposable{
  6. /**
  7. * Gizmo's created by the gizmo manager, gizmo will be null until gizmo has been enabled for the first time
  8. */
  9. public gizmos:{positionGizmo: Nullable<PositionGizmo>, rotationGizmo: Nullable<RotationGizmo>, scaleGizmo: Nullable<ScaleGizmo>, boundingBoxGizmo: Nullable<BoundingBoxGizmo>};
  10. private _gizmosEnabled = {positionGizmo: false, rotationGizmo: false, scaleGizmo: false, boundingBoxGizmo: false};
  11. private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
  12. private _attachedMesh:Nullable<AbstractMesh> = null;
  13. private _boundingBoxColor = BABYLON.Color3.FromHexString("#0984e3");
  14. private _defaultUtilityLayer:UtilityLayerRenderer;
  15. private _defaultKeepDepthUtilityLayer:UtilityLayerRenderer;
  16. /**
  17. * When bounding box gizmo is enabled, this can be used to track drag/end events
  18. */
  19. public boundingBoxDragBehavior = new BABYLON.SixDofDragBehavior();
  20. /**
  21. * Array of meshes which will have the gizmo attached when a pointer selected them. If null, all meshes are attachable. (Default: null)
  22. */
  23. public attachableMeshes:Nullable<Array<AbstractMesh>> = null;
  24. /**
  25. * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh. (Default: true)
  26. */
  27. public usePointerToAttachGizmos = true;
  28. /**
  29. * Instatiates a gizmo manager
  30. * @param scene the scene to overlay the gizmos on top of
  31. */
  32. constructor(private scene:Scene){
  33. this._defaultKeepDepthUtilityLayer = new UtilityLayerRenderer(scene);
  34. this._defaultKeepDepthUtilityLayer.utilityLayerScene.autoClearDepthAndStencil = false;
  35. this._defaultUtilityLayer = new UtilityLayerRenderer(scene);
  36. this.gizmos = {positionGizmo: null, rotationGizmo: null, scaleGizmo: null, boundingBoxGizmo: null};
  37. // Instatiate/dispose gizmos based on pointer actions
  38. this._pointerObserver = scene.onPointerObservable.add((pointerInfo, state)=>{
  39. if(!this.usePointerToAttachGizmos){
  40. return;
  41. }
  42. if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN){
  43. if(pointerInfo.pickInfo && pointerInfo.pickInfo.pickedMesh){
  44. var node:Nullable<Node> = pointerInfo.pickInfo.pickedMesh;
  45. if(this.attachableMeshes == null){
  46. // Attach to the most parent node
  47. while(node && node.parent != null){
  48. node = node.parent;
  49. }
  50. }else{
  51. // Attach to the parent node that is an attachableMesh
  52. var found = false;
  53. this.attachableMeshes.forEach((mesh)=>{
  54. if(node && (node == mesh || node.isDescendantOf(mesh))){
  55. node = mesh;
  56. found = true;
  57. }
  58. })
  59. if(!found){
  60. node = null;
  61. }
  62. }
  63. if(node instanceof AbstractMesh){
  64. this.attachToMesh(node);
  65. }else{
  66. this.attachToMesh(null);
  67. }
  68. }else{
  69. this.attachToMesh(null);
  70. }
  71. }
  72. })
  73. }
  74. /**
  75. * Attaches a set of gizmos to the specified mesh
  76. * @param mesh The mesh the gizmo's should be attached to
  77. */
  78. public attachToMesh(mesh:Nullable<AbstractMesh>){
  79. if(this._attachedMesh){
  80. this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
  81. }
  82. this._attachedMesh = mesh;
  83. for(var key in this.gizmos){
  84. var gizmo = <Nullable<Gizmo>>((<any>this.gizmos)[key]);
  85. if(gizmo && (<any>this._gizmosEnabled)[key]){
  86. gizmo.attachedMesh = mesh;
  87. }
  88. }
  89. if(this.boundingBoxGizmoEnabled && this._attachedMesh){
  90. this._attachedMesh.addBehavior(this.boundingBoxDragBehavior);
  91. }
  92. }
  93. /**
  94. * If the position gizmo is enabled
  95. */
  96. public set positionGizmoEnabled(value:boolean){
  97. if(value){
  98. if(!this.gizmos.positionGizmo){
  99. this.gizmos.positionGizmo = new PositionGizmo(this._defaultUtilityLayer);
  100. }
  101. this.gizmos.positionGizmo.attachedMesh = this._attachedMesh;
  102. }else if(this.gizmos.positionGizmo){
  103. this.gizmos.positionGizmo.attachedMesh = null;
  104. }
  105. this._gizmosEnabled.positionGizmo = value;
  106. }
  107. public get positionGizmoEnabled():boolean{
  108. return this._gizmosEnabled.positionGizmo;
  109. }
  110. /**
  111. * If the rotation gizmo is enabled
  112. */
  113. public set rotationGizmoEnabled(value:boolean){
  114. if(value){
  115. if(!this.gizmos.rotationGizmo){
  116. this.gizmos.rotationGizmo = new RotationGizmo(this._defaultUtilityLayer);
  117. }
  118. this.gizmos.rotationGizmo.attachedMesh = this._attachedMesh;
  119. }else if(this.gizmos.rotationGizmo){
  120. this.gizmos.rotationGizmo.attachedMesh = null;
  121. }
  122. this._gizmosEnabled.rotationGizmo = value;
  123. }
  124. public get rotationGizmoEnabled():boolean{
  125. return this._gizmosEnabled.rotationGizmo;
  126. }
  127. /**
  128. * If the scale gizmo is enabled
  129. */
  130. public set scaleGizmoEnabled(value:boolean){
  131. if(value){
  132. this.gizmos.scaleGizmo = this.gizmos.scaleGizmo || new ScaleGizmo(this._defaultUtilityLayer);
  133. this.gizmos.scaleGizmo.attachedMesh = this._attachedMesh;
  134. }else if(this.gizmos.scaleGizmo){
  135. this.gizmos.scaleGizmo.attachedMesh = null;
  136. }
  137. this._gizmosEnabled.scaleGizmo = value;
  138. }
  139. public get scaleGizmoEnabled():boolean{
  140. return this._gizmosEnabled.scaleGizmo;
  141. }
  142. /**
  143. * If the boundingBox gizmo is enabled
  144. */
  145. public set boundingBoxGizmoEnabled(value:boolean){
  146. if(value){
  147. this.gizmos.boundingBoxGizmo = this.gizmos.boundingBoxGizmo || new BoundingBoxGizmo(this._boundingBoxColor, this._defaultKeepDepthUtilityLayer);
  148. this.gizmos.boundingBoxGizmo.attachedMesh = this._attachedMesh;
  149. if(this._attachedMesh){
  150. this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
  151. this._attachedMesh.addBehavior(this.boundingBoxDragBehavior);
  152. }
  153. }else if(this.gizmos.boundingBoxGizmo){
  154. this.gizmos.boundingBoxGizmo.attachedMesh = null;
  155. }
  156. this._gizmosEnabled.boundingBoxGizmo = value;
  157. }
  158. public get boundingBoxGizmoEnabled():boolean{
  159. return this._gizmosEnabled.boundingBoxGizmo;
  160. }
  161. /**
  162. * Disposes of the gizmo manager
  163. */
  164. public dispose(){
  165. this.scene.onPointerObservable.remove(this._pointerObserver);
  166. for(var key in this.gizmos){
  167. var gizmo = <Nullable<Gizmo>>((<any>this.gizmos)[key]);
  168. if(gizmo){
  169. gizmo.dispose();
  170. }
  171. }
  172. this._defaultKeepDepthUtilityLayer.dispose();
  173. this._defaultUtilityLayer.dispose();
  174. this.boundingBoxDragBehavior.detach();
  175. }
  176. }
  177. }