dynamicTexture.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import { Logger } from "../../Misc/logger";
  2. import { Nullable } from "../../types";
  3. import { Scene } from "../../scene";
  4. import { ISize } from "../../Maths/math.size";
  5. import { Engine } from "../../Engines/engine";
  6. import { Texture } from "../../Materials/Textures/texture";
  7. import { _TimeToken } from "../../Instrumentation/timeToken";
  8. import { Constants } from "../../Engines/constants";
  9. import "../../Engines/Extensions/engine.dynamicTexture";
  10. import { CanvasGenerator } from '../../Misc/canvasGenerator';
  11. /**
  12. * A class extending Texture allowing drawing on a texture
  13. * @see http://doc.babylonjs.com/how_to/dynamictexture
  14. */
  15. export class DynamicTexture extends Texture {
  16. private _generateMipMaps: boolean;
  17. private _canvas: HTMLCanvasElement | OffscreenCanvas;
  18. private _context: CanvasRenderingContext2D;
  19. private _engine: Engine;
  20. /**
  21. * Creates a DynamicTexture
  22. * @param name defines the name of the texture
  23. * @param options provides 3 alternatives for width and height of texture, a canvas, object with width and height properties, number for both width and height
  24. * @param scene defines the scene where you want the texture
  25. * @param generateMipMaps defines the use of MinMaps or not (default is false)
  26. * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
  27. * @param format defines the texture format to use (default is Engine.TEXTUREFORMAT_RGBA)
  28. */
  29. constructor(name: string, options: any, scene: Nullable<Scene> = null, generateMipMaps: boolean, samplingMode: number = Constants.TEXTURE_TRILINEAR_SAMPLINGMODE, format: number = Constants.TEXTUREFORMAT_RGBA) {
  30. super(null, scene, !generateMipMaps, undefined, samplingMode, undefined, undefined, undefined, undefined, format);
  31. this.name = name;
  32. this._engine = (<Scene>this.getScene()).getEngine();
  33. this.wrapU = Texture.CLAMP_ADDRESSMODE;
  34. this.wrapV = Texture.CLAMP_ADDRESSMODE;
  35. this._generateMipMaps = generateMipMaps;
  36. if (options.getContext) {
  37. this._canvas = options;
  38. this._texture = this._engine.createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
  39. } else {
  40. this._canvas = CanvasGenerator.CreateCanvas(1, 1);
  41. if (options.width || options.width === 0) {
  42. this._texture = this._engine.createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
  43. } else {
  44. this._texture = this._engine.createDynamicTexture(options, options, generateMipMaps, samplingMode);
  45. }
  46. }
  47. var textureSize = this.getSize();
  48. this._canvas.width = textureSize.width;
  49. this._canvas.height = textureSize.height;
  50. this._context = <CanvasRenderingContext2D>this._canvas.getContext("2d");
  51. }
  52. /**
  53. * Get the current class name of the texture useful for serialization or dynamic coding.
  54. * @returns "DynamicTexture"
  55. */
  56. public getClassName(): string {
  57. return "DynamicTexture";
  58. }
  59. /**
  60. * Gets the current state of canRescale
  61. */
  62. public get canRescale(): boolean {
  63. return true;
  64. }
  65. private _recreate(textureSize: ISize): void {
  66. this._canvas.width = textureSize.width;
  67. this._canvas.height = textureSize.height;
  68. this.releaseInternalTexture();
  69. this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this.samplingMode);
  70. }
  71. /**
  72. * Scales the texture
  73. * @param ratio the scale factor to apply to both width and height
  74. */
  75. public scale(ratio: number): void {
  76. var textureSize = this.getSize();
  77. textureSize.width *= ratio;
  78. textureSize.height *= ratio;
  79. this._recreate(textureSize);
  80. }
  81. /**
  82. * Resizes the texture
  83. * @param width the new width
  84. * @param height the new height
  85. */
  86. public scaleTo(width: number, height: number): void {
  87. var textureSize = this.getSize();
  88. textureSize.width = width;
  89. textureSize.height = height;
  90. this._recreate(textureSize);
  91. }
  92. /**
  93. * Gets the context of the canvas used by the texture
  94. * @returns the canvas context of the dynamic texture
  95. */
  96. public getContext(): CanvasRenderingContext2D {
  97. return this._context;
  98. }
  99. /**
  100. * Clears the texture
  101. */
  102. public clear(): void {
  103. var size = this.getSize();
  104. this._context.fillRect(0, 0, size.width, size.height);
  105. }
  106. /**
  107. * Updates the texture
  108. * @param invertY defines the direction for the Y axis (default is true - y increases downwards)
  109. * @param premulAlpha defines if alpha is stored as premultiplied (default is false)
  110. */
  111. public update(invertY?: boolean, premulAlpha = false): void {
  112. this._engine.updateDynamicTexture(this._texture, this._canvas, invertY === undefined ? true : invertY, premulAlpha, this._format || undefined);
  113. }
  114. /**
  115. * Draws text onto the texture
  116. * @param text defines the text to be drawn
  117. * @param x defines the placement of the text from the left
  118. * @param y defines the placement of the text from the top when invertY is true and from the bottom when false
  119. * @param font defines the font to be used with font-style, font-size, font-name
  120. * @param color defines the color used for the text
  121. * @param clearColor defines the color for the canvas, use null to not overwrite canvas
  122. * @param invertY defines the direction for the Y axis (default is true - y increases downwards)
  123. * @param update defines whether texture is immediately update (default is true)
  124. */
  125. public drawText(text: string, x: number, y: number, font: string, color: string, clearColor: string, invertY?: boolean, update = true) {
  126. var size = this.getSize();
  127. if (clearColor) {
  128. this._context.fillStyle = clearColor;
  129. this._context.fillRect(0, 0, size.width, size.height);
  130. }
  131. this._context.font = font;
  132. if (x === null || x === undefined) {
  133. var textSize = this._context.measureText(text);
  134. x = (size.width - textSize.width) / 2;
  135. }
  136. if (y === null || y === undefined) {
  137. var fontSize = parseInt((font.replace(/\D/g, '')));
  138. y = (size.height / 2) + (fontSize / 3.65);
  139. }
  140. this._context.fillStyle = color;
  141. this._context.fillText(text, x, y);
  142. if (update) {
  143. this.update(invertY);
  144. }
  145. }
  146. /**
  147. * Clones the texture
  148. * @returns the clone of the texture.
  149. */
  150. public clone(): DynamicTexture {
  151. let scene = this.getScene();
  152. if (!scene) {
  153. return this;
  154. }
  155. var textureSize = this.getSize();
  156. var newTexture = new DynamicTexture(this.name, textureSize, scene, this._generateMipMaps);
  157. // Base texture
  158. newTexture.hasAlpha = this.hasAlpha;
  159. newTexture.level = this.level;
  160. // Dynamic Texture
  161. newTexture.wrapU = this.wrapU;
  162. newTexture.wrapV = this.wrapV;
  163. return newTexture;
  164. }
  165. /**
  166. * Serializes the dynamic texture. The scene should be ready before the dynamic texture is serialized
  167. * @returns a serialized dynamic texture object
  168. */
  169. public serialize(): any {
  170. const scene = this.getScene();
  171. if (scene && !scene.isReady()) {
  172. Logger.Warn("The scene must be ready before serializing the dynamic texture");
  173. }
  174. const serializationObject = super.serialize();
  175. if ((this._canvas as HTMLCanvasElement).toDataURL) {
  176. serializationObject.base64String = (this._canvas as HTMLCanvasElement).toDataURL();
  177. }
  178. serializationObject.invertY = this._invertY;
  179. serializationObject.samplingMode = this.samplingMode;
  180. return serializationObject;
  181. }
  182. /** @hidden */
  183. public _rebuild(): void {
  184. this.update();
  185. }
  186. }