gui3DManager.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /// <reference path="../../../dist/preview release/babylon.d.ts"/>
  2. module BABYLON.GUI {
  3. /**
  4. * Class used to manage 3D user interface
  5. */
  6. export class GUI3DManager implements BABYLON.IDisposable {
  7. private _scene: Scene;
  8. private _sceneDisposeObserver: Nullable<Observer<Scene>>;
  9. private _utilityLayer: Nullable<UtilityLayerRenderer>;
  10. private _rootContainer: Container3D;
  11. private _pointerObserver: Nullable<Observer<PointerInfoPre>>;
  12. /** @hidden */
  13. public _lastPickedControl: Control3D;
  14. /** @hidden */
  15. public _lastControlOver: {[pointerId:number]: Control3D} = {};
  16. /** @hidden */
  17. public _lastControlDown: {[pointerId:number]: Control3D} = {};
  18. /**
  19. * Observable raised when the point picked by the pointer events changed
  20. */
  21. public onPickedPointChangedObservable = new Observable<Nullable<Vector3>>();
  22. // Shared resources
  23. /** @hidden */
  24. public _sharedMaterials: {[key:string]: Material} = {};
  25. /** Gets the hosting scene */
  26. public get scene(): Scene {
  27. return this._scene;
  28. }
  29. /** Gets associated utility layer */
  30. public get utilityLayer(): Nullable<UtilityLayerRenderer> {
  31. return this._utilityLayer;
  32. }
  33. /**
  34. * Creates a new GUI3DManager
  35. * @param scene
  36. */
  37. public constructor(scene?: Scene) {
  38. this._scene = scene || Engine.LastCreatedScene!;
  39. this._sceneDisposeObserver = this._scene.onDisposeObservable.add(() => {
  40. this._sceneDisposeObserver = null;
  41. this._utilityLayer = null;
  42. this.dispose();
  43. })
  44. this._utilityLayer = new UtilityLayerRenderer(this._scene);
  45. // Root
  46. this._rootContainer = new Container3D("RootContainer");
  47. this._rootContainer._host = this;
  48. // Events
  49. this._pointerObserver = this._scene.onPrePointerObservable.add((pi, state) => {
  50. let pointerEvent = <PointerEvent>(pi.event);
  51. if (this._scene.isPointerCaptured(pointerEvent.pointerId)) {
  52. return;
  53. }
  54. if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE
  55. && pi.type !== BABYLON.PointerEventTypes.POINTERUP
  56. && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
  57. return;
  58. }
  59. let camera = this._scene.cameraToUseForPointers || this._scene.activeCamera;
  60. if (!camera) {
  61. return;
  62. }
  63. pi.skipOnPointerObservable = this._doPicking(pi.type, pointerEvent, pi.ray)
  64. });
  65. // Scene
  66. this._utilityLayer.utilityLayerScene.autoClear = false;
  67. this._utilityLayer.utilityLayerScene.autoClearDepthAndStencil = false;
  68. new BABYLON.HemisphericLight("hemi", Vector3.Up(), this._utilityLayer.utilityLayerScene);
  69. }
  70. private _doPicking(type: number, pointerEvent: PointerEvent, ray?:Nullable<Ray>): boolean {
  71. if (!this._utilityLayer || !this._utilityLayer.utilityLayerScene.activeCamera) {
  72. return false;
  73. }
  74. let pointerId = pointerEvent.pointerId || 0;
  75. let buttonIndex = pointerEvent.button;
  76. var utilityScene = this._utilityLayer.utilityLayerScene;
  77. let pickingInfo = ray ? utilityScene.pickWithRay(ray): utilityScene.pick(this._scene.pointerX, this._scene.pointerY);
  78. if (!pickingInfo || !pickingInfo.hit) {
  79. var previousControlOver = this._lastControlOver[pointerId];
  80. if (previousControlOver) {
  81. previousControlOver._onPointerOut(previousControlOver);
  82. delete this._lastControlOver[pointerId];
  83. }
  84. if (type === BABYLON.PointerEventTypes.POINTERUP) {
  85. if (this._lastControlDown[pointerEvent.pointerId]) {
  86. this._lastControlDown[pointerEvent.pointerId].forcePointerUp();
  87. delete this._lastControlDown[pointerEvent.pointerId];
  88. }
  89. }
  90. this.onPickedPointChangedObservable.notifyObservers(null);
  91. return false;
  92. }
  93. let control = <Control3D>(pickingInfo.pickedMesh!.metadata);
  94. if (pickingInfo.pickedPoint) {
  95. this.onPickedPointChangedObservable.notifyObservers(pickingInfo.pickedPoint);
  96. }
  97. if (!control._processObservables(type, pickingInfo.pickedPoint!, pointerId, buttonIndex)) {
  98. if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
  99. if (this._lastControlOver[pointerId]) {
  100. this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
  101. }
  102. delete this._lastControlOver[pointerId];
  103. }
  104. }
  105. if (type === BABYLON.PointerEventTypes.POINTERUP) {
  106. if (this._lastControlDown[pointerEvent.pointerId]) {
  107. this._lastControlDown[pointerEvent.pointerId].forcePointerUp();
  108. delete this._lastControlDown[pointerEvent.pointerId];
  109. }
  110. }
  111. return true;
  112. }
  113. /**
  114. * Gets the root container
  115. */
  116. public get rootContainer(): Container3D {
  117. return this._rootContainer;
  118. }
  119. /**
  120. * Gets a boolean indicating if the given control is in the root child list
  121. * @param control defines the control to check
  122. * @returns true if the control is in the root child list
  123. */
  124. public containsControl(control: Control3D): boolean {
  125. return this._rootContainer.containsControl(control);
  126. }
  127. /**
  128. * Adds a control to the root child list
  129. * @param control defines the control to add
  130. * @returns the current manager
  131. */
  132. public addControl(control: Control3D): GUI3DManager {
  133. this._rootContainer.addControl(control);
  134. return this;
  135. }
  136. /**
  137. * Removes the control from the root child list
  138. * @param control defines the control to remove
  139. * @returns the current container
  140. */
  141. public removeControl(control: Control3D): GUI3DManager {
  142. this._rootContainer.removeControl(control);
  143. return this;
  144. }
  145. /**
  146. * Releases all associated resources
  147. */
  148. public dispose() {
  149. this._rootContainer.dispose();
  150. for (var materialName in this._sharedMaterials) {
  151. if (!this._sharedMaterials.hasOwnProperty(materialName)) {
  152. continue;
  153. }
  154. this._sharedMaterials[materialName].dispose();
  155. }
  156. this._sharedMaterials = {};
  157. this.onPickedPointChangedObservable.clear();
  158. if (this._scene) {
  159. if (this._pointerObserver) {
  160. this._scene.onPrePointerObservable.remove(this._pointerObserver);
  161. this._pointerObserver = null;
  162. }
  163. if (this._sceneDisposeObserver) {
  164. this._scene.onDisposeObservable.remove(this._sceneDisposeObserver);
  165. this._sceneDisposeObserver = null;
  166. }
  167. }
  168. if (this._utilityLayer) {
  169. this._utilityLayer.dispose();
  170. }
  171. }
  172. }
  173. }