advancedDynamicTexture.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /// <reference path="../../dist/preview release/babylon.d.ts"/>
  2. module BABYLON.GUI {
  3. export class AdvancedDynamicTexture extends DynamicTexture {
  4. private _isDirty = false;
  5. private _renderObserver: Observer<Camera>;
  6. private _resizeObserver: Observer<Engine>;
  7. private _pointerMoveObserver: Observer<PointerInfoPre>;
  8. private _background: string;
  9. public _rootContainer = new Container("root");
  10. public _lastControlOver: Control;
  11. public _lastControlDown: Control;
  12. public _shouldBlockPointer: boolean;
  13. public _toDispose: IDisposable;
  14. public _linkedControls = new Array<Control>();
  15. private _isFullscreen = false;
  16. public get background(): string {
  17. return this._background;
  18. }
  19. public set background(value: string) {
  20. if (this._background === value) {
  21. return;
  22. }
  23. this._background = value;
  24. this.markAsDirty();
  25. }
  26. constructor(name: string, width = 0, height = 0, scene: Scene, generateMipMaps = false, samplingMode = Texture.NEAREST_SAMPLINGMODE) {
  27. super(name, {width: width, height: height}, scene, generateMipMaps, samplingMode, Engine.TEXTUREFORMAT_RGBA);
  28. this._renderObserver = this.getScene().onBeforeCameraRenderObservable.add((camera: Camera) => this._checkUpdate(camera));
  29. this._rootContainer._link(null, this);
  30. this.hasAlpha = true;
  31. if (!width || !height) {
  32. this._resizeObserver = this.getScene().getEngine().onResizeObservable.add(() => this._onResize());
  33. this._onResize();
  34. }
  35. }
  36. public markAsDirty() {
  37. this._isDirty = true;
  38. }
  39. public addControl(control: Control): AdvancedDynamicTexture {
  40. this._rootContainer.addControl(control);
  41. return this;
  42. }
  43. public removeControl(control: Control): AdvancedDynamicTexture {
  44. this._rootContainer.removeControl(control);
  45. return this;
  46. }
  47. public dispose() {
  48. this.getScene().onBeforeCameraRenderObservable.remove(this._renderObserver);
  49. if (this._resizeObserver) {
  50. this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
  51. }
  52. if (this._pointerMoveObserver) {
  53. this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
  54. }
  55. if (this._toDispose) {
  56. this._toDispose.dispose();
  57. this._toDispose = null;
  58. }
  59. super.dispose();
  60. }
  61. private _onResize(): void {
  62. // Check size
  63. var engine = this.getScene().getEngine();
  64. var textureSize = this.getSize();
  65. var renderWidth = engine.getRenderWidth();
  66. var renderHeight = engine.getRenderHeight();
  67. if (textureSize.width !== renderWidth || textureSize.height !== renderHeight) {
  68. this.scaleTo(renderWidth, renderHeight);
  69. this.markAsDirty();
  70. }
  71. }
  72. private _checkUpdate(camera: Camera): void {
  73. if (this._isFullscreen && this._linkedControls.length) {
  74. var scene = this.getScene();
  75. var engine = scene.getEngine();
  76. var viewport = camera.viewport;
  77. var globalViewport = viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
  78. for (var control of this._linkedControls) {
  79. var mesh = control._linkedMesh;
  80. var position = mesh.getBoundingInfo().boundingSphere.center;
  81. var projectedPosition = Vector3.Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
  82. control._moveToProjectedPosition(projectedPosition);
  83. }
  84. }
  85. if (!this._isDirty && !this._rootContainer.isDirty) {
  86. return;
  87. }
  88. this._isDirty = false;
  89. this._render();
  90. this.update();
  91. }
  92. private _render(): void {
  93. var textureSize = this.getSize();
  94. var renderWidth = textureSize.width;
  95. var renderHeight = textureSize.height;
  96. // Clear
  97. var context = this.getContext();
  98. context.clearRect(0, 0, renderWidth, renderHeight);
  99. if (this._background) {
  100. context.save();
  101. context.fillStyle = this._background;
  102. context.fillRect(0, 0, renderWidth, renderHeight);
  103. context.restore();
  104. }
  105. // Render
  106. context.font = "18px Arial";
  107. var measure = new Measure(0, 0, renderWidth, renderHeight);
  108. this._rootContainer._draw(measure, context);
  109. }
  110. private _doPicking(x: number, y: number, type: number): void {
  111. if (!this._rootContainer._processPicking(x, y, type)) {
  112. if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
  113. if (this._lastControlOver && this._lastControlOver.onPointerOutObservable.hasObservers()) {
  114. this._lastControlOver.onPointerOutObservable.notifyObservers(this._lastControlOver);
  115. }
  116. this._lastControlOver = null;
  117. }
  118. }
  119. }
  120. public attach(): void {
  121. var scene = this.getScene();
  122. this._pointerMoveObserver = scene.onPrePointerObservable.add((pi, state) => {
  123. if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE
  124. && pi.type !== BABYLON.PointerEventTypes.POINTERUP
  125. && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
  126. return;
  127. }
  128. this._shouldBlockPointer = false;
  129. this._doPicking(scene.pointerX, scene.pointerY, pi.type);
  130. pi.skipOnPointerObservable = this._shouldBlockPointer && pi.type !== BABYLON.PointerEventTypes.POINTERUP;
  131. });
  132. }
  133. // Statics
  134. public static CreateForMesh(mesh: AbstractMesh, width = 1024, height = 1024): AdvancedDynamicTexture {
  135. var result = new AdvancedDynamicTexture(mesh.name + " AdvancedDynamicTexture", width, height, mesh.getScene(), true, Texture.TRILINEAR_SAMPLINGMODE);
  136. var material = new BABYLON.StandardMaterial("AdvancedDynamicTextureMaterial", mesh.getScene());
  137. material.backFaceCulling = false;
  138. material.diffuseColor = BABYLON.Color3.Black();
  139. material.specularColor = BABYLON.Color3.Black();
  140. material.emissiveTexture = result;
  141. material.opacityTexture = result;
  142. mesh.material = material;
  143. mesh.getScene().onPointerObservable.add(function(pi, state) {
  144. if (pi.type !== BABYLON.PointerEventTypes.POINTERUP && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
  145. return;
  146. }
  147. if (pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
  148. var uv = pi.pickInfo.getTextureCoordinates();
  149. result._doPicking(uv.x * width, (1.0 - uv.y) * height, pi.type);
  150. }
  151. });
  152. return result;
  153. }
  154. public static CreateFullscreenUI(name: string, foreground: boolean = true, scene: Scene): AdvancedDynamicTexture {
  155. var result = new AdvancedDynamicTexture(name, 0, 0, scene);
  156. // Display
  157. var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
  158. layer.texture = result;
  159. result._toDispose = layer;
  160. result._isFullscreen = true;
  161. // Attach
  162. result.attach();
  163. return result;
  164. }
  165. }
  166. }