advancedDynamicTexture.ts 9.3 KB

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