advancedDynamicTexture.ts 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /// <reference path="../../../dist/preview release/babylon.d.ts"/>
  2. /**
  3. * This module hosts all controls for 2D and 3D GUIs
  4. * @see http://doc.babylonjs.com/how_to/gui
  5. */
  6. module BABYLON.GUI {
  7. /**
  8. * Interface used to define a control that can receive focus
  9. */
  10. export interface IFocusableControl {
  11. /**
  12. * Function called when the control receives the focus
  13. */
  14. onFocus(): void;
  15. /**
  16. * Function called when the control loses the focus
  17. */
  18. onBlur(): void;
  19. /**
  20. * Function called to let the control handle keyboard events
  21. * @param evt defines the current keyboard event
  22. */
  23. processKeyboard(evt: KeyboardEvent): void;
  24. }
  25. /**
  26. * Class used to create texture to support 2D GUI elements
  27. * @see http://doc.babylonjs.com/how_to/gui
  28. */
  29. export class AdvancedDynamicTexture extends DynamicTexture {
  30. private _isDirty = false;
  31. private _renderObserver: Nullable<Observer<Camera>>;
  32. private _resizeObserver: Nullable<Observer<Engine>>;
  33. private _preKeyboardObserver: Nullable<Observer<KeyboardInfoPre>>;
  34. private _pointerMoveObserver: Nullable<Observer<PointerInfoPre>>;
  35. private _pointerObserver: Nullable<Observer<PointerInfo>>;
  36. private _canvasPointerOutObserver: Nullable<Observer<PointerEvent>>;
  37. private _background: string;
  38. /** @hidden */
  39. public _rootContainer = new Container("root");
  40. /** @hidden */
  41. public _lastPickedControl: Control;
  42. /** @hidden */
  43. public _lastControlOver: {[pointerId:number]:Control} = {};
  44. /** @hidden */
  45. public _lastControlDown: {[pointerId:number]:Control} = {};
  46. /** @hidden */
  47. public _capturingControl: {[pointerId:number]:Control} = {};
  48. /** @hidden */
  49. public _shouldBlockPointer: boolean;
  50. /** @hidden */
  51. public _layerToDispose: Nullable<Layer>;
  52. /** @hidden */
  53. public _linkedControls = new Array<Control>();
  54. private _isFullscreen = false;
  55. private _fullscreenViewport = new Viewport(0, 0, 1, 1);
  56. private _idealWidth = 0;
  57. private _idealHeight = 0;
  58. private _useSmallestIdeal: boolean = false;
  59. private _renderAtIdealSize = false;
  60. private _focusedControl: Nullable<IFocusableControl>;
  61. private _blockNextFocusCheck = false;
  62. private _renderScale = 1;
  63. /**
  64. * Gets or sets a boolean defining if alpha is stored as premultiplied
  65. */
  66. public premulAlpha = false;
  67. /**
  68. * Gets or sets a number used to scale rendering size (2 means that the texture will be twice bigger).
  69. * Useful when you want more antialiasing
  70. */
  71. public get renderScale(): number {
  72. return this._renderScale;
  73. }
  74. public set renderScale(value: number) {
  75. if (value === this._renderScale) {
  76. return;
  77. }
  78. this._renderScale = value;
  79. this._onResize();
  80. }
  81. /** Gets or sets the background color */
  82. public get background(): string {
  83. return this._background;
  84. }
  85. public set background(value: string) {
  86. if (this._background === value) {
  87. return;
  88. }
  89. this._background = value;
  90. this.markAsDirty();
  91. }
  92. /**
  93. * Gets or sets the ideal width used to design controls.
  94. * The GUI will then rescale everything accordingly
  95. * @see http://doc.babylonjs.com/how_to/gui#adaptive-scaling
  96. */
  97. public get idealWidth(): number {
  98. return this._idealWidth;
  99. }
  100. public set idealWidth(value: number) {
  101. if (this._idealWidth === value) {
  102. return;
  103. }
  104. this._idealWidth = value;
  105. this.markAsDirty();
  106. this._rootContainer._markAllAsDirty();
  107. }
  108. /**
  109. * Gets or sets the ideal height used to design controls.
  110. * The GUI will then rescale everything accordingly
  111. * @see http://doc.babylonjs.com/how_to/gui#adaptive-scaling
  112. */
  113. public get idealHeight(): number {
  114. return this._idealHeight;
  115. }
  116. public set idealHeight(value: number) {
  117. if (this._idealHeight === value) {
  118. return;
  119. }
  120. this._idealHeight = value;
  121. this.markAsDirty();
  122. this._rootContainer._markAllAsDirty();
  123. }
  124. /**
  125. * Gets or sets a boolean indicating if the smallest ideal value must be used if idealWidth and idealHeight are both set
  126. * @see http://doc.babylonjs.com/how_to/gui#adaptive-scaling
  127. */
  128. public get useSmallestIdeal(): boolean {
  129. return this._useSmallestIdeal;
  130. }
  131. public set useSmallestIdeal(value: boolean) {
  132. if (this._useSmallestIdeal === value) {
  133. return;
  134. }
  135. this._useSmallestIdeal = value;
  136. this.markAsDirty();
  137. this._rootContainer._markAllAsDirty();
  138. }
  139. /**
  140. * Gets or sets a boolean indicating if adaptive scaling must be used
  141. * @see http://doc.babylonjs.com/how_to/gui#adaptive-scaling
  142. */
  143. public get renderAtIdealSize(): boolean {
  144. return this._renderAtIdealSize;
  145. }
  146. public set renderAtIdealSize(value: boolean) {
  147. if (this._renderAtIdealSize === value) {
  148. return;
  149. }
  150. this._renderAtIdealSize = value;
  151. this._onResize();
  152. }
  153. /**
  154. * Gets the underlying layer used to render the texture when in fullscreen mode
  155. */
  156. public get layer(): Nullable<Layer> {
  157. return this._layerToDispose;
  158. }
  159. /**
  160. * Gets the root container control
  161. */
  162. public get rootContainer(): Container {
  163. return this._rootContainer;
  164. }
  165. /**
  166. * Gets or sets the current focused control
  167. */
  168. public get focusedControl(): Nullable<IFocusableControl> {
  169. return this._focusedControl;
  170. }
  171. public set focusedControl(control: Nullable<IFocusableControl>) {
  172. if (this._focusedControl == control) {
  173. return;
  174. }
  175. if (this._focusedControl) {
  176. this._focusedControl.onBlur();
  177. }
  178. if (control) {
  179. control.onFocus();
  180. }
  181. this._focusedControl = control;
  182. }
  183. /**
  184. * Gets or sets a boolean indicating if the texture must be rendered in background or foreground when in fullscreen mode
  185. */
  186. public get isForeground(): boolean {
  187. if (!this.layer) {
  188. return true;
  189. }
  190. return (!this.layer.isBackground);
  191. }
  192. public set isForeground(value: boolean) {
  193. if (!this.layer) {
  194. return;
  195. }
  196. if (this.layer.isBackground === !value) {
  197. return;
  198. }
  199. this.layer.isBackground = !value;
  200. }
  201. /**
  202. * Creates a new AdvancedDynamicTexture
  203. * @param name defines the name of the texture
  204. * @param width defines the width of the texture
  205. * @param height defines the height of the texture
  206. * @param scene defines the hosting scene
  207. * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
  208. * @param samplingMode defines the texture sampling mode (BABYLON.Texture.NEAREST_SAMPLINGMODE by default)
  209. */
  210. constructor(name: string, width = 0, height = 0, scene: Nullable<Scene>, generateMipMaps = false, samplingMode = Texture.NEAREST_SAMPLINGMODE) {
  211. super(name, { width: width, height: height }, scene, generateMipMaps, samplingMode, Engine.TEXTUREFORMAT_RGBA);
  212. scene = this.getScene();
  213. if (!scene || !this._texture) {
  214. return;
  215. }
  216. this._renderObserver = scene.onBeforeCameraRenderObservable.add((camera: Camera) => this._checkUpdate(camera));
  217. this._preKeyboardObserver = scene.onPreKeyboardObservable.add(info => {
  218. if (!this._focusedControl) {
  219. return;
  220. }
  221. if (info.type === KeyboardEventTypes.KEYDOWN) {
  222. this._focusedControl.processKeyboard(info.event);
  223. }
  224. info.skipOnPointerObservable = true;
  225. });
  226. this._rootContainer._link(null, this);
  227. this.hasAlpha = true;
  228. if (!width || !height) {
  229. this._resizeObserver = scene.getEngine().onResizeObservable.add(() => this._onResize());
  230. this._onResize();
  231. }
  232. this._texture.isReady = true;
  233. }
  234. /**
  235. * Function used to execute a function on all controls
  236. * @param func defines the function to execute
  237. * @param container defines the container where controls belong. If null the root container will be used
  238. */
  239. public executeOnAllControls(func: (control: Control) => void, container?: Container) {
  240. if (!container) {
  241. container = this._rootContainer;
  242. }
  243. for (var child of container.children) {
  244. if ((<any>child).children) {
  245. this.executeOnAllControls(func, (<Container>child));
  246. continue;
  247. }
  248. func(child);
  249. }
  250. }
  251. /**
  252. * Marks the texture as dirty forcing a complete update
  253. */
  254. public markAsDirty() {
  255. this._isDirty = true;
  256. this.executeOnAllControls((control) => {
  257. if (control._isFontSizeInPercentage) {
  258. control._resetFontCache();
  259. }
  260. });
  261. }
  262. /**
  263. * Helper function used to create a new style
  264. * @returns a new style
  265. * @see http://doc.babylonjs.com/how_to/gui#styles
  266. */
  267. public createStyle(): Style {
  268. return new Style(this);
  269. }
  270. /**
  271. * Adds a new control to the root container
  272. * @param control defines the control to add
  273. * @returns the current texture
  274. */
  275. public addControl(control: Control): AdvancedDynamicTexture {
  276. this._rootContainer.addControl(control);
  277. return this;
  278. }
  279. /**
  280. * Removes a control from the root container
  281. * @param control defines the control to remove
  282. * @returns the current texture
  283. */
  284. public removeControl(control: Control): AdvancedDynamicTexture {
  285. this._rootContainer.removeControl(control);
  286. return this;
  287. }
  288. /**
  289. * Release all resources
  290. */
  291. public dispose(): void {
  292. let scene = this.getScene();
  293. if (!scene) {
  294. return;
  295. }
  296. scene.onBeforeCameraRenderObservable.remove(this._renderObserver);
  297. if (this._resizeObserver) {
  298. scene.getEngine().onResizeObservable.remove(this._resizeObserver);
  299. }
  300. if (this._pointerMoveObserver) {
  301. scene.onPrePointerObservable.remove(this._pointerMoveObserver);
  302. }
  303. if (this._pointerObserver) {
  304. scene.onPointerObservable.remove(this._pointerObserver);
  305. }
  306. if (this._preKeyboardObserver) {
  307. scene.onPreKeyboardObservable.remove(this._preKeyboardObserver);
  308. }
  309. if (this._canvasPointerOutObserver) {
  310. scene.getEngine().onCanvasPointerOutObservable.remove(this._canvasPointerOutObserver);
  311. }
  312. if (this._layerToDispose) {
  313. this._layerToDispose.texture = null;
  314. this._layerToDispose.dispose();
  315. this._layerToDispose = null;
  316. }
  317. this._rootContainer.dispose();
  318. super.dispose();
  319. }
  320. private _onResize(): void {
  321. let scene = this.getScene();
  322. if (!scene) {
  323. return;
  324. }
  325. // Check size
  326. var engine = scene.getEngine();
  327. var textureSize = this.getSize();
  328. var renderWidth = engine.getRenderWidth() * this._renderScale;
  329. var renderHeight = engine.getRenderHeight() * this._renderScale;
  330. if (this._renderAtIdealSize) {
  331. if (this._idealWidth) {
  332. renderHeight = (renderHeight * this._idealWidth) / renderWidth;
  333. renderWidth = this._idealWidth;
  334. } else if (this._idealHeight) {
  335. renderWidth = (renderWidth * this._idealHeight) / renderHeight;
  336. renderHeight = this._idealHeight;
  337. }
  338. }
  339. if (textureSize.width !== renderWidth || textureSize.height !== renderHeight) {
  340. this.scaleTo(renderWidth, renderHeight);
  341. this.markAsDirty();
  342. if (this._idealWidth || this._idealHeight) {
  343. this._rootContainer._markAllAsDirty();
  344. }
  345. }
  346. }
  347. /** @hidden */
  348. public _getGlobalViewport(scene: Scene): Viewport {
  349. var engine = scene.getEngine();
  350. return this._fullscreenViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
  351. }
  352. /**
  353. * Get screen coordinates for a vector3
  354. * @param position defines the position to project
  355. * @param worldMatrix defines the world matrix to use
  356. * @returns the projected position
  357. */
  358. public getProjectedPosition(position: Vector3, worldMatrix: Matrix): Vector2 {
  359. var scene = this.getScene();
  360. if (!scene) {
  361. return Vector2.Zero();
  362. }
  363. var globalViewport = this._getGlobalViewport(scene);
  364. var projectedPosition = Vector3.Project(position, worldMatrix, scene.getTransformMatrix(), globalViewport);
  365. projectedPosition.scaleInPlace(this.renderScale);
  366. return new Vector2(projectedPosition.x, projectedPosition.y);
  367. }
  368. private _checkUpdate(camera: Camera): void {
  369. if (this._layerToDispose) {
  370. if ((camera.layerMask & this._layerToDispose.layerMask) === 0) {
  371. return;
  372. }
  373. }
  374. if (this._isFullscreen && this._linkedControls.length) {
  375. var scene = this.getScene();
  376. if (!scene) {
  377. return;
  378. }
  379. var globalViewport = this._getGlobalViewport(scene);
  380. for (var control of this._linkedControls) {
  381. if (!control.isVisible) {
  382. continue;
  383. }
  384. var mesh = control._linkedMesh;
  385. if (!mesh || mesh.isDisposed()) {
  386. Tools.SetImmediate(() => {
  387. control.linkWithMesh(null);
  388. });
  389. continue;
  390. }
  391. var position = mesh.getBoundingInfo().boundingSphere.center;
  392. var projectedPosition = Vector3.Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
  393. if (projectedPosition.z < 0 || projectedPosition.z > 1) {
  394. control.notRenderable = true;
  395. continue;
  396. }
  397. control.notRenderable = false;
  398. // Account for RenderScale.
  399. projectedPosition.scaleInPlace(this.renderScale);
  400. control._moveToProjectedPosition(projectedPosition);
  401. }
  402. }
  403. if (!this._isDirty && !this._rootContainer.isDirty) {
  404. return;
  405. }
  406. this._isDirty = false;
  407. this._render();
  408. this.update(true, this.premulAlpha);
  409. }
  410. private _render(): void {
  411. var textureSize = this.getSize();
  412. var renderWidth = textureSize.width;
  413. var renderHeight = textureSize.height;
  414. // Clear
  415. var context = this.getContext();
  416. context.clearRect(0, 0, renderWidth, renderHeight);
  417. if (this._background) {
  418. context.save();
  419. context.fillStyle = this._background;
  420. context.fillRect(0, 0, renderWidth, renderHeight);
  421. context.restore();
  422. }
  423. // Render
  424. context.font = "18px Arial";
  425. context.strokeStyle = "white";
  426. var measure = new Measure(0, 0, renderWidth, renderHeight);
  427. this._rootContainer._draw(measure, context);
  428. }
  429. private _doPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): void {
  430. var scene = this.getScene();
  431. if (!scene) {
  432. return;
  433. }
  434. var engine = scene.getEngine();
  435. var textureSize = this.getSize();
  436. if (this._isFullscreen) {
  437. x = x * (textureSize.width / engine.getRenderWidth());
  438. y = y * (textureSize.height / engine.getRenderHeight());
  439. }
  440. if (this._capturingControl[pointerId]) {
  441. this._capturingControl[pointerId]._processObservables(type, x, y, pointerId, buttonIndex);
  442. return;
  443. }
  444. if (!this._rootContainer._processPicking(x, y, type, pointerId, buttonIndex)) {
  445. if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
  446. if (this._lastControlOver[pointerId]) {
  447. this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
  448. }
  449. delete this._lastControlOver[pointerId];
  450. }
  451. }
  452. this._manageFocus();
  453. }
  454. /** @hidden */
  455. public _cleanControlAfterRemovalFromList(list: {[pointerId:number]:Control}, control:Control) {
  456. for (var pointerId in list) {
  457. if (!list.hasOwnProperty(pointerId)) {
  458. continue;
  459. }
  460. var lastControlOver = list[pointerId];
  461. if (lastControlOver === control) {
  462. delete list[pointerId];
  463. }
  464. }
  465. }
  466. /** @hidden */
  467. public _cleanControlAfterRemoval(control: Control) {
  468. this._cleanControlAfterRemovalFromList(this._lastControlDown, control);
  469. this._cleanControlAfterRemovalFromList(this._lastControlOver, control);
  470. }
  471. /** Attach to all scene events required to support pointer events */
  472. public attach(): void {
  473. var scene = this.getScene();
  474. if (!scene) {
  475. return;
  476. }
  477. this._pointerMoveObserver = scene.onPrePointerObservable.add((pi, state) => {
  478. if (scene!.isPointerCaptured((<PointerEvent>(pi.event)).pointerId)) {
  479. return;
  480. }
  481. if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE
  482. && pi.type !== BABYLON.PointerEventTypes.POINTERUP
  483. && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
  484. return;
  485. }
  486. if (!scene) {
  487. return;
  488. }
  489. let camera = scene.cameraToUseForPointers || scene.activeCamera;
  490. if (!camera) {
  491. return;
  492. }
  493. let engine = scene.getEngine();
  494. let viewport = camera.viewport;
  495. let x = (scene.pointerX / engine.getHardwareScalingLevel() - viewport.x * engine.getRenderWidth()) / viewport.width;
  496. let y = (scene.pointerY / engine.getHardwareScalingLevel() - viewport.y * engine.getRenderHeight()) / viewport.height;
  497. this._shouldBlockPointer = false;
  498. this._doPicking(x, y, pi.type, (pi.event as PointerEvent).pointerId || 0, pi.event.button);
  499. pi.skipOnPointerObservable = this._shouldBlockPointer;
  500. });
  501. this._attachToOnPointerOut(scene);
  502. }
  503. /**
  504. * Connect the texture to a hosting mesh to enable interactions
  505. * @param mesh defines the mesh to attach to
  506. * @param supportPointerMove defines a boolean indicating if pointer move events must be catched as well
  507. */
  508. public attachToMesh(mesh: AbstractMesh, supportPointerMove = true): void {
  509. var scene = this.getScene();
  510. if (!scene) {
  511. return;
  512. }
  513. this._pointerObserver = scene.onPointerObservable.add((pi, state) => {
  514. if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE
  515. && pi.type !== BABYLON.PointerEventTypes.POINTERUP
  516. && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
  517. return;
  518. }
  519. var pointerId = (pi.event as PointerEvent).pointerId || 0;
  520. if (pi.pickInfo && pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
  521. var uv = pi.pickInfo.getTextureCoordinates();
  522. if (uv) {
  523. let size = this.getSize();
  524. this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi.type, pointerId, pi.event.button);
  525. }
  526. } else if (pi.type === BABYLON.PointerEventTypes.POINTERUP) {
  527. if (this._lastControlDown[pointerId]) {
  528. this._lastControlDown[pointerId]._forcePointerUp(pointerId);
  529. }
  530. delete this._lastControlDown[pointerId];
  531. this.focusedControl = null;
  532. } else if (pi.type === BABYLON.PointerEventTypes.POINTERMOVE) {
  533. if (this._lastControlOver[pointerId]) {
  534. this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
  535. }
  536. delete this._lastControlOver[pointerId];
  537. }
  538. });
  539. mesh.enablePointerMoveEvents = supportPointerMove;
  540. this._attachToOnPointerOut(scene);
  541. }
  542. /**
  543. * Move the focus to a specific control
  544. * @param control defines the control which will receive the focus
  545. */
  546. public moveFocusToControl(control: IFocusableControl): void {
  547. this.focusedControl = control;
  548. this._lastPickedControl = <any>control;
  549. this._blockNextFocusCheck = true;
  550. }
  551. private _manageFocus(): void {
  552. if (this._blockNextFocusCheck) {
  553. this._blockNextFocusCheck = false;
  554. this._lastPickedControl = <any>this._focusedControl;
  555. return;
  556. }
  557. // Focus management
  558. if (this._focusedControl) {
  559. if (this._focusedControl !== (<any>this._lastPickedControl)) {
  560. if (this._lastPickedControl.isFocusInvisible) {
  561. return;
  562. }
  563. this.focusedControl = null;
  564. }
  565. }
  566. }
  567. private _attachToOnPointerOut(scene: Scene): void {
  568. this._canvasPointerOutObserver = scene.getEngine().onCanvasPointerOutObservable.add((pointerEvent) => {
  569. if (this._lastControlOver[pointerEvent.pointerId]) {
  570. this._lastControlOver[pointerEvent.pointerId]._onPointerOut(this._lastControlOver[pointerEvent.pointerId]);
  571. }
  572. delete this._lastControlOver[pointerEvent.pointerId];
  573. if (this._lastControlDown[pointerEvent.pointerId]) {
  574. this._lastControlDown[pointerEvent.pointerId]._forcePointerUp();
  575. }
  576. delete this._lastControlDown[pointerEvent.pointerId];
  577. });
  578. }
  579. // Statics
  580. /**
  581. * Creates a new AdvancedDynamicTexture in projected mode (ie. attached to a mesh)
  582. * @param mesh defines the mesh which will receive the texture
  583. * @param width defines the texture width (1024 by default)
  584. * @param height defines the texture height (1024 by default)
  585. * @param supportPointerMove defines a boolean indicating if the texture must capture move events (true by default)
  586. * @returns a new AdvancedDynamicTexture
  587. */
  588. public static CreateForMesh(mesh: AbstractMesh, width = 1024, height = 1024, supportPointerMove = true): AdvancedDynamicTexture {
  589. var result = new AdvancedDynamicTexture(mesh.name + " AdvancedDynamicTexture", width, height, mesh.getScene(), true, Texture.TRILINEAR_SAMPLINGMODE);
  590. var material = new BABYLON.StandardMaterial("AdvancedDynamicTextureMaterial", mesh.getScene());
  591. material.backFaceCulling = false;
  592. material.diffuseColor = BABYLON.Color3.Black();
  593. material.specularColor = BABYLON.Color3.Black();
  594. material.emissiveTexture = result;
  595. material.opacityTexture = result;
  596. mesh.material = material;
  597. result.attachToMesh(mesh, supportPointerMove);
  598. return result;
  599. }
  600. /**
  601. * Creates a new AdvancedDynamicTexture in fullscreen mode.
  602. * In this mode the texture will rely on a layer for its rendering.
  603. * This allows it to be treated like any other layer.
  604. * As such, if you have a multi camera setup, you can set the layerMask on the GUI as well.
  605. * LayerMask is set through advancedTexture.layer.layerMask
  606. * @param name defines name for the texture
  607. * @param foreground defines a boolean indicating if the texture must be rendered in foreground (default is true)
  608. * @param scene defines the hsoting scene
  609. * @param sampling defines the texture sampling mode (BABYLON.Texture.BILINEAR_SAMPLINGMODE by default)
  610. * @returns a new AdvancedDynamicTexture
  611. */
  612. public static CreateFullscreenUI(name: string, foreground: boolean = true, scene: Nullable<Scene> = null, sampling = Texture.BILINEAR_SAMPLINGMODE): AdvancedDynamicTexture {
  613. var result = new AdvancedDynamicTexture(name, 0, 0, scene, false, sampling);
  614. // Display
  615. var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
  616. layer.texture = result;
  617. result._layerToDispose = layer;
  618. result._isFullscreen = true;
  619. // Attach
  620. result.attach();
  621. return result;
  622. }
  623. }
  624. }